AI Operations Dashboard Handbook
A four-day tour from a fresh clone to a dashboard you use every morning. Each day is a 10-to-15-minute session. Finish all four and you have a branded, data-fed, AI-maintainable operator view of your project.
Reference manual: USAGE.md. This is the tour.
Day 1 β Your first dashboard (10 minutes)
What to do
Open a terminal in the folder where you keep your projects and clone the starter. Then run the one-shot setup.
git clone https://github.com/your-org/ai-ops-dashboard.git my-dashboard
cd my-dashboard
npm install
npm run setupnpm run setup is a six-step wizard at http://localhost:3000/setup. It opens automatically. You will:
- Read the welcome screen, click Get started.
- Type the product name, tagline, and a one-line eyebrow string. These are the three lines at the top of every dashboard render.
- Pick a template. Nine starters ship in
templates/:indie-saas-founder,ai-founder,content-creator,consulting-agency,ecommerce-operator,oss-maintainer,personal-os,research-lab,blank-slate. Each one ships its own panel mix and its own sample data. If you are unsure, pickindie-saas-founderβ it is the most balanced and the rest of this Handbook assumes it. - Confirm the panel list. The template pre-selects the right panels for your role; you can drop or reorder freely later.
- Confirm the data wiring. The wizard copies sample data from the chosen template into
data/,docs/,plans/, andknowledge/so the very first render shows real-looking content. - Decide whether to install the AI-agent integration. Say yes β Day 4 needs it. Say no if you do not have Claude Code or a similar coding agent installed; you can flip it on later.
When the wizard says Setup complete, run:
npm run devOpen http://localhost:3000. You should see a populated dashboard.
What to expect on screen
A header with your product title and tagline. A row of up to five hero stat cards. A tab strip with one tab per panel β Overview, Plan, Sprints, Activity, Pending, Log, Postmortems, Usage, Scheduled Jobs, Repos, Docs, Skills in the default template. A banner at the very top tracking AI spend (green at $0 today). Whichever tab is selected fills the rest of the page with a mix of stat cards, tables, and prose. The footer notes how many panels are active and which theme you are on.
Nothing on screen is real yet. Every panel is reading from the sample files the template dropped into your repo. The shape is real, the numbers are not.
What to do if it breaks
- Port 3000 already in use β run
PORT=3001 npm run dev. Or kill whatever owns the port. - The wizard never opens β go to
http://localhost:3000/setupmanually. - Hero stats show `β` everywhere β open
data/pending.jsonanddata/usage.jsonand check they are valid JSON. The readers fall back silently on parse errors. - Tabs render but show "no data yet" β the template did not copy its sample data. Re-run
npm run setupand pick the template again; it is idempotent. - Banner is red on a fresh install β
data/usage.jsonships with sample spend numbers. Edit it to{"today": 0, "month": 0}to clear.
Day 2 β Make it yours (10 minutes)
What to do
The dashboard runs. Now it needs to look like *your* product, not the template. Two files, three edits.
Open ai-ops-dashboard.config.ts. This is the only configuration file you ever edit. Change four fields:
product: {
title: "Acme Operator",
tagline: "Live view of what we shipped, what is pending, and where the spend went.",
description: "Acme Operator β one page for the team.",
eyebrow: "Internal Β· ops",
},
theme: "warm",Save. Tab back to the browser β the dashboard re-renders in under a second.
Now decide your panel mix. Below theme: is a panels array. Drop the ones you do not need. For a solo indie founder shipping every day, this is plenty:
panels: [
overview,
pending,
activity,
usage,
],Save again. The tab strip collapses to four tabs. Whatever you remove is just hidden β no data is deleted.
Want a different feel? Three themes ship in app/globals.css: dark (default, near-black background), warm (cream paper, brown ink, looks like a notebook), and paper (true white, monochrome, very minimal). To roll your own theme: copy the [data-theme="dark"] block in globals.css, rename it, and edit the color tokens. The theme name in the config matches the data-theme attribute the layout sets.
What to expect on screen
Header text matches what you typed. The tab strip is shorter. If you switched themes, the entire palette flipped β background, text, accent color, card borders, the hero stats. Nothing else moved. Layout, typography, and information density stay constant across themes.
What to do if it breaks
- Edit saves but nothing changes β Next.js Fast Refresh sometimes misses the config file on the first save. Hit
Cmd-Rto force-reload once. - Theme name does not exist β the dashboard falls back to
darkand logs a warning in the dev terminal. Check for typos. - Dropped panel still appears β you have two
panelsarrays in the config. Search forpanels:and make sure there is only one. - The page is blank after a config edit β syntax error in the config file. Look at the dev terminal; it prints the line number.
Day 3 β Wire your real data (10 minutes)
What to do
The dashboard is branded. Now replace the sample data with yours, panel by panel. You do not need to do all of them today β pick the two or three you will actually look at every morning and wire those.
AI Operations Dashboard reads from files in your repo, never a database. The files live in three places:
data/*.jsonβ structured records (pending items, scheduled jobs, usage rollup)docs/*.mdβ prose logs (operator log, session notes)knowledge/,plans/β postmortems and roadmap docs
Each panel knows which file or folder to read. The bindings are listed at the top of every panel file in components/panels/. Open components/panels/pending-panel.tsx and you will see something like:
const pending = readJson<PendingItem[]>(
path.join(ctx.projectRoot, "data/pending.json"),
[]
)That data/pending.json is the only thing you change. The panel re-reads on every render.
Start with the Pending panel because it pays back immediately. Open data/pending.json. Replace its contents with your actual pending work:
{
"items": [
{
"title": "Ship the Stripe webhook retry path",
"priority": "high",
"doer": "claude",
"why": "Failing payments silently drop today; retry queue closes the gap.",
"dateAdded": "2026-06-01"
}
]
}Save. The Pending tab now shows your work. The hero stat for "open items" updates to match.
Next the Operator Log. Open docs/operator-log.md. Wipe the sample entries. Write one new entry in the same shape:
## 2026-06-02 09:00 β Stripe webhook retry path shipped
**Why:** Failing payments were dropping silently.
**What shipped:** Retry queue with exponential backoff (commit a1b2c3d).
**Tags:** payments, reliability
**Next:** Add a Datadog alarm on retry-queue depth.Save. The Log tab shows your entry at the top. Activity-tab freshness ticks forward.
Finally the Activity panel. This one is automatic β it reads data/recent-commits.json, which is regenerated on every npm run dev and every pre-push hook. As you commit, Activity fills in.
That is enough for a useful dashboard. Wire more panels as you need them. The pattern is always the same: open the panel file, find the readJson or readMarkdown call, edit the file it points to.
What to expect on screen
Pending tab: your real items, with priority chips and the "why" line under each title. Hero stats reflect your counts (3 open not 12 open). Log tab: your most recent operator-log entry at the top, full prose rendered. Activity tab: whatever you committed in the last 90 days, newest first.
What to do if it breaks
- Panel shows "no items" but the file is full β JSON parse error. Run
node -e "JSON.parse(require('fs').readFileSync('data/pending.json','utf8'))". It will print the parse error with a character offset. - Operator log shows nothing after a real entry β entry is missing the
## YYYY-MM-DD HH:MM β titleheader. The parser is strict about that line. - Hero stats stuck on the old numbers β the dashboard reads on every render but Next.js dev caches the import graph. Save the panel file (any whitespace edit) and the cache invalidates.
- You broke a sample file and want it back β every template ships its own copy. Re-run
npm run setup, choose the same template, decline to overwrite the files you want to keep, accept the ones you broke.
Day 4: Connect your other repos so AI keeps it fresh
A single-repo dashboard is a toy. The point of AI Operations Dashboard is to be the one page that aggregates *every* project you ship from. Most operators have somewhere between 5 and 15 separate repos β a SaaS product, a marketing site, a side-project, an internal tool, a content vault, a few experiments. The dashboard becomes powerful when each of those repos auto-reports into it.
Day 4 is wiring that up. After this, you stop maintaining the dashboard by hand. Your AI sessions across every connected repo do it for you.
What to do
1. Re-run setup β connect tab. Or `npx ai-ops-dashboard init` from each external repo.
There are two ways to connect a new repo to the dashboard. The wizard path is for the first one or two repos β visit http://localhost:3000/setup, click the Connect tab, and follow the prompts. It writes a .ai-ops-dashboard.json config file to the target repo with the absolute path back to your dashboard.
For everything after that, the CLI is faster:
cd ~/code/some-other-repo
npx ai-ops-dashboard init --dashboard ~/code/my-dashboardThat single command does the same thing the wizard does: drops .ai-ops-dashboard.json, drops an AGENTS.md briefing tuned to this repo, registers the repo in your dashboard's data/connected-repos.json.
2. Per external repo, paste the briefing prompt into your Claude Code session.
Open the connected repo in Claude Code (or Cursor, or any agent that reads AGENTS.md). At the start of your first session in that repo, paste the briefing prompt that npx ai-ops-dashboard init printed at the end of its output. It's a one-paragraph instruction telling the agent:
- This repo reports into an AI Operations Dashboard.
- At session end, run
npx ai-ops-dashboard logto append an operator-log entry there. - When work surfaces a follow-up, run
npx ai-ops-dashboard pending addto register it. - Commits in this repo will be picked up by the dashboard's Activity panel automatically.
You only paste the briefing once per repo, per agent β the agent stores it in its working memory for the session and the AGENTS.md file picks it up automatically on future sessions.
3. Work normally. At session end, the AI runs `npx ai-ops-dashboard log` and `npx ai-ops-dashboard pending add` as needed.
This is the whole loop. You write code. You debug something. You ship a feature. At the end of the session, the agent β having read AGENTS.md β calls the CLI to write the right files in your dashboard repo. You don't think about the dashboard during the work; the dashboard updates as a side effect of the work being done.
4. Reload the dashboard. Latest work shows up across Activity, Pending, Log.
Open http://localhost:3000 (or your deployed dashboard URL). The new entries are there. The hero stats recalculate. The repo badge on each entry shows which project it came from.
What to expect on screen
After connecting three repos and running two or three sessions in each, here is what changes:
- `/repos` tab β shows three connected repos with a "last reported" timestamp per row, the count of operator-log entries each has contributed, and a health dot (green if the repo reported in the last 7 days, yellow at 7-30, red past 30).
- Activity heat map β now interleaves commits from all three repos. The repo source is color-coded so you can spot at a glance which project drove the busy week.
- Pending tab β items from all three repos, each tagged with its source. You can filter by repo or view them as one merged backlog.
- Log tab β entries from every repo, sorted strictly chronologically. Read the page top-to-bottom and you have a true cross-project narrative of what you shipped this week.
The Usage banner stays single-source (it tracks your dashboard repo's AI spend), but every other surface becomes a cross-repo aggregator.
What to do if it breaks
- Wrong `dashboardPath` β the most common gotcha.
.ai-ops-dashboard.jsonin the connected repo points at a dashboard folder that doesn't exist, or that moved. Open the file, fix the absolute path, re-runnpx ai-ops-dashboard logto confirm it writes successfully. - CLI not on PATH β
npx ai-ops-dashboardworks anywhere if you havenpx, but if your agent is in a sandboxed shell it may not find it. Install globally withnpm i -g ai-ops-dashboard-cliand useai-ops-dashboard logdirectly. - AI hasn't read the briefing β the agent skipped
AGENTS.mdand isn't calling the CLI at session end. Most agents need to be reminded to read it. Start the session with "Read AGENTS.md first" or paste the briefing prompt again. - Dashboard on a different machine (v0.3 limit) β the current CLI only writes to a dashboard on the same filesystem. If your dashboard is deployed to Vercel and your dev machine doesn't have a local clone, you cannot yet auto-report. Workaround: keep a local clone of the dashboard repo and
git pushit after each session. Remote-dashboard support is on the roadmap for v0.4.
End state
The dashboard is no longer a thing the operator maintains. It maintains itself, written to by AI sessions across every connected repo. Your morning view of "what did I ship this week across everything" stops being a thing you assemble in your head from five different tabs and becomes a single page that already knows.
Day 5: Add tabs for your unique work (15-20 minutes)
The twelve built-in panels β Overview, Plan, Sprints, Activity, Pending, Log, Postmortems, Usage, Scheduled Jobs, Repos, Docs, Skills β cover the operator basics. They will not cover your domain. A teacher needs a Students tab. A consultant needs a Clients tab. A reseller needs an Inventory tab. AI Operations Dashboard ships an authoring flow that turns "I wish I had a tab for X" into a working tab in under twenty minutes, without you writing any panel code by hand.
The trick: nearly every domain-specific tab fits one of five archetypes. Pick the archetype, name your fields, and the generator writes the panel, the data file, the CLAUDE.md / AGENTS.md briefing, and the manifest entry in one pass.
What to do
Open http://localhost:3000/admin/add-tab. It is a five-step wizard, same shape as the setup wizard from Day 1.
- Name the tab. Title (
Customer feedback), slug (customer-feedback, auto-filled from the title), one-line description ("Bug reports, feature requests, and praise β categorised, with a status per item"). The slug becomes the URL fragment (/?tab=customer-feedback) and the file basename indata/. - Pick the archetype. Five options, each with a thumbnail and a one-line "use this whenβ¦":
- List β repeating records with sortable columns and chips (Pending, Postmortems, Inventory, CRM-style tabs). - Timeline β chronological prose entries with a date header (Operator Log, Decisions, Customer Calls). - Metrics β hero stats plus a few charts off a single time-series JSON file (Usage, Revenue, Email-list growth). - Folder β render an entire folder of Markdown files as cards (Postmortems already uses this β re-use for SOPs, Playbooks, Case studies). - REST β pull from a live API endpoint at request time, cache for N minutes (Stripe charges, Shopify orders, Linear issues β anything you do not want to mirror into the repo).
- Define the fields. For a List archetype, you name each column:
title(string, required),severity(enum: low/medium/high),status(enum: open/triaged/closed),source(string),dateAdded(date),notes(markdown). The wizard infers reasonable widget types β enum becomes a colored chip, date becomes a relative timestamp, markdown becomes a collapsible cell. - Permissions. Decide who can write to this tab. Default is "you and your AI agents." If you toggle "team-editable," the generator adds a writer-auth check the same way the Pending tab does it.
- Review and generate. The wizard shows you exactly which files it will create or touch:
components/panels/customer-feedback-panel.tsx(new),data/customer-feedback.json(new, seeded with one sample row),ai-ops-dashboard.config.ts(panel added to the array),CLAUDE.mdandAGENTS.md(a "Customer feedback tab" section appended so AI knows how to update it),data/manifest.json(entry registered so the dashboard knows the tab exists). Click Generate.
The wizard returns to the dashboard with your new tab live in the strip.
What to expect on screen
The new tab sits at the end of the strip in the order you added it (drag to reorder via the panel config later). Click in and you see a single seed row demonstrating each field. The table header is sortable. Severity and status render as colored chips matching your enum values. The "add row" button at the top right is wired to a local-only form for human entry; the AI uses the CLI path (npx ai-ops-dashboard add customer-feedback --title "β¦" --severity high) which the briefing in AGENTS.md documents.
Open CLAUDE.md (or AGENTS.md). At the bottom is a fresh section: "## Customer feedback tab β how to update it." It lists the schema, the CLI invocation, and a worked example. Drop a fresh Claude session into the repo, ask it to log a piece of feedback, and it knows exactly which file to edit and which format to use.
What to do if it breaks
- Wizard refuses to generate, says "slug already taken" β you have a panel with that slug already. Pick a different slug or remove the existing one from
ai-ops-dashboard.config.tsfirst. - Tab appears but renders blank β the JSON seed did not write. Open
data/<slug>.json, paste{"items": []}, refresh. - AI updates the wrong file β
AGENTS.mdgot appended but Claude is reading a stale copy. Restart the agent session, or paste the new section into the prompt directly. - You want to delete a generated tab β remove the entry from
ai-ops-dashboard.config.tsand delete the four generated files. There is no destructive "uninstall" command yet; do it by hand so you cannot lose a tab to a typo.
Day 6: See your Claude Code installation (Claude users only)
This day is for the subset of operators who use Claude Code as their primary agent. If you do not, skip β the Skills tab simply will not be in your strip.
Most Claude Code users accumulate skills, plugins, MCP servers, and agents the way a desktop accumulates icons: a few dozen installed deliberately, the rest from a tutorial you tried once and forgot. After a year, the ~/.claude/ directory has 50 to 200 entries and nobody β including you β knows which ones are actually doing work. The Skills tab is a read-only window into that directory plus an opt-in cleanup mode.
What to do
If you enabled the Skills tab during setup, it is already in your strip. If not: open ai-ops-dashboard.config.ts, add skills to the panels array, save.
Click into the Skills tab. The first render runs a scan of ~/.claude/ β plugins, user-level skills, project skills, MCP server definitions, and registered agents. Each is shown as a card with: name, source (plugin / user / project), install date, last-modified date, and (where claude-mem is installed) a usage count pulled from your observation history.
Read-only mode is the default. Sort, filter, click a card to expand and see the full SKILL.md or plugin.json. Nothing on disk changes.
Flip Review mode on (top right) when you want to clean house. Each card grows a checkbox. Tick the ones you do not recognise, the ones you have not used in 90 days, the duplicates from competing tutorials. The footer counter tracks how many you have flagged.
Click Export manifest. The dashboard writes data/skills-cleanup-manifest.json β a structured file listing every flagged item with its install path, the exact removal command (rm -rf ~/.claude/plugins/<name> or the corresponding claude plugin uninstall), and a one-line reason you can edit if you want notes for future-you.
Open a fresh Claude Code session. Paste:
> Read data/skills-cleanup-manifest.json and execute the removal commands listed. Confirm each one before running. Print a final summary of what was removed.
Claude works through the list. You watch. Done.
What to expect on screen
The card grid. A filter bar at the top with three quick-filters: "Never used" (claude-mem-aware, off if claude-mem is not installed), "Installed > 6 months ago, not touched since," "Duplicate name across plugin and user level." A small banner if the scan found broken entries (a SKILL.md referencing a missing tool, an MCP server with no command). The footer shows totals β "Scanned 87 items in 240ms. 12 flagged for review."
After export, the manifest file appears in your data/ directory. The Activity tab logs the export as an event so you can find your own audit later.
What to do if it breaks
- Skills tab shows "no Claude installation found" β
~/.claude/either does not exist or is not readable by the dashboard process. Confirm Claude Code is installed and you have run it at least once. On Linux, check permissions. - Scan is slow (more than 5 seconds) β you have a deep plugin tree. The Skills panel caches scan output for 60 seconds; the first hit pays the cost, the rest are instant.
- Usage counts are all zero β claude-mem is not installed, or its observation database is empty. The panel still works without it; you just lose the "actually used" signal.
- Removal session deleted something you wanted β every removal command in the manifest is reversible by re-installing the source. The manifest itself is not deleted after export; keep it as the receipt of what changed.
After Day 6
You have a branded dashboard, real data in the panels you care about, an agent that keeps the rest fresh, custom tabs for your unique work, and (if you are on Claude Code) a clean inventory of what is installed on your machine. The reference manual in USAGE.md covers what you did not need today: custom panels written by hand, deployment to Vercel, the prebuild audit chain, alternate data sources, and the hero-stat contract.
If you forget how a panel reads its data, open components/panels/<panel-name>-panel.tsx. Every panel declares its data sources in the first 20 lines β the file you read is the file that runs.