Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Command Center — starter

Your own dashboard, running only the sections you install. Nothing here reads anyone else's data: your notes live in this folder, and the tokens are yours.

Wired up out of the box, grouped into Today, Archives and Guide:

TabWhat it doesReads / writes
☀️ Today ▸ DayThe cockpit: backlog size, what you owe from meetings, and a panel listing every Claude Code session you have openreads content/ (counts); the sessions panel reads ~/.claude
✅ Today ▸ TasksEisenhower-quadrant backlog + a Today blockcontent/tasks/active.md
🔀 Today ▸ PRsPer-squad PR checkpoints from GitHub, stacked-PR chains, Slack channel signals, and a ready-to-paste Slack draft.data/
📓 Archives ▸ JournalPer-day journalcontent/tasks/journal.md
📅 Archives ▸ MeetingsMeeting notes by bucket, with live action-item checkboxes and archivingcontent/meetings/
📖 GuideSetup, How to use, FAQs — describing your tabs— (src/GuideView.tsx)

Setup (~2 minutes)

1. Install. The section packages are public on npm — no token, no registry config, nothing to authenticate:

pnpm install

Upgrading from an early copy of this template? Delete any .npmrc in this folder first. An earlier version told you to point the @asucregonzalez scope at GitHub Packages; the packages now live on npm, and a leftover .npmrc sends the install to the wrong registry and 404s. .npmrc is gitignored, so git pull can't remove it for you:

rm -f .npmrc && pnpm install

2. Configure.

cp .env.example .env
  • GITHUB_TOKENrequired by Pull requests. Classic token with repo scope, so it can read PRs in the orgs you track.
  • SLACK_BOT_TOKEN — optional. Only for channel signals and posting the draft.
  • VITE_OWNER_NAME — your name as it appears in an Owner: field, so Meetings can split action items into yours vs everyone else's.

Tasks, Journal and Meetings need no tokens at all — they're just your markdown.

3. Run.

pnpm dev # or: make dev

make on its own lists every shortcut — make setup does the one-time bootstrap (isolated Google Workspace config dir + local settings), make run launches Claude with this workspace's environment.

Open http://localhost:5273. The API runs on :4320 and the dev server proxies /api to it.

Pull requests starts with no projects — add your first squad from its own UI (a name plus the GitHub logins to track). Tasks, Journal and Meetings start from the seeded files in content/, which double as format documentation.

The skills

.claude/skills/ ships ten Claude Code skills. These five keep the dashboard's data current, so you're not hand-editing markdown:

SkillWhat it does
task-managementCreates and edits tasks in content/tasks/active.md, enforcing one action per task
daily-briefingReconciles yesterday, gathers calendar + mail + Slack + PR queue + backlog, proposes today's Top 3, writes the Today block and archives yesterday to the journal
meeting-processorPulls yesterday's meetings from Granola into content/meetings/, and their action items into your task list
sync-meetingsSame, but from a Google Drive folder — use whichever matches where your notes live
google-workspace-cliReference for the gws CLI, which the two Google-backed skills above rely on

Each needs a few blanks filled in before first use — your GitHub login, Slack member ID, Granola folder names or a Drive folder id. Every skill says so at the top. A skill whose tool you haven't authenticated skips that source and tells you, rather than making something up.

The two meeting skills are the ones you'll hit first: both start with no source configured, so they'll ask instead of syncing. That's deliberate — a bucket is a decision about how you organise your work, not something to guess. Answer with a Drive folder id (sync-meetings), your Granola folder names (meeting-processor), or "neither, I'll write notes by hand" — the Meetings tab reads content/meetings/*.md either way.

Ask for them in plain language ("what's my plan today?", "process yesterday's meetings") or invoke directly with /daily-briefing.

A second brain, if you want one

Four more skills turn content/memory/ into a wiki that compounds:

SkillWhat it does
wikiDrop a document in content/sources/, ask to ingest it, and it becomes linked pages in content/memory/. Also queries and lints the knowledge base
memory-claude-md-syncFires on every wiki write so the navigation hub never drifts from reality
claude-md-templateKeeps every CLAUDE.md to one shape, so the hierarchy stays navigable
/weekly-done-cleanupPrunes completed tasks out of the backlog into content/tasks/done-archive.md, keeping ones that still give context

And these are general-purpose, nothing to do with the dashboard:

Command / skillWhat it does
/setupWalks you through first-time setup — identity, placeholders, isolated Google auth, git history
/wiki-ingestIngest one document into the wiki, proposing what to write before writing it
/grill-meInterrogates a plan branch by branch until the decisions are actually resolved
/compact-sessionCaptures a long chat's context into notes plus a resume prompt for a fresh session
create-presentationBuilds a Fever-brand deck in Google Slides — brand kit and the Slides-API gotchas already solved

content/memory/ ships empty with just its hub file. Nothing is pre-populated — it becomes useful only as you feed it.

Bootstrap scripts

/setup is an interview, not a form: it asks your name, email and GitHub handle, then your role, your current goal for the quarter, your team and timezone, and your Slack ID plus the channels worth scanning. Role and goal are the two that change behaviour rather than just filling in a blank — role picks the work-type buckets on the task board, and the goal becomes the tiebreaker the daily briefing uses when two tasks are equally urgent. Everything is optional and everything is editable afterwards (the "Me" table in CLAUDE.md).

.claude/scripts/setup/ holds the machinery it drives, all parameterized:

ScriptDoes
apply-placeholders.shSubstitutes your profile — {{NAME}} / {{EMAIL}} / {{GH_HANDLE}} positionally, then any TOKEN=value pairs (ROLE, GOAL, TEAM, TIMEZONE, SLACK_ID, SLACK_CHANNELS, and for team leads JIRA_PROJECT_KEY, DATADOG_TEAM_TAG, DATADOG_SERVICE, TEAM_REPOS) — across the template
apply-work-types.mjsBakes your role's work-type buckets into src/work-types.ts. --list shows the presets
ensure-gws-config-dir.sh, verify-gws.shCreates and checks an isolated Google Workspace config dir, so this assistant's auth never collides with anything else
generate-makefile.shWrites a makefile whose run target launches Claude with the right env
init-settings-local.shSeeds .claude/settings.local.json
fresh-git-init.shWipes template history for a clean first commit — destructive, run deliberately

CLAUDE.md documents the workspace conventions all of these follow — worth reading once.

Recommended: rtk

rtk is a CLI proxy that compresses command output before the agent reads it — a single Rust binary, Apache-2.0. It's the cheapest efficiency win available here, because every oversized tool result gets re-read on every subsequent turn.

brew install rtk # or: curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
rtk init -g # registers a global PreToolUse hook + ~/.claude/RTK.md# then restart Claude Code
rtk init --show # verify

Measured on this project's own repo:

CommandRawVia rtk
ls -la1615 B256 B (−84%)
git log -n 2024.2 kB6.6 kB (−73%)
git status636 B282 B (−56%)
git diff --stat414 B413 B (−0%)

Read the claims precisely, because the honest version is less dramatic than "90%":

  • It compresses bash output, which is one input among your prompt, the system prompt and the conversation history — and input is only part of the bill. The reduction dilutes at each step.
  • Its token figures are bytes / 4 estimates; the percentages are trustworthy, the absolute token counts are not.
  • Already-terse commands gain nothing, as the git diff --stat row shows.
  • Read, Grep and Glob bypass it — the hook only intercepts the Bash tool. For big files, reach for rtk read / rtk grep, or a ranged Read.

Install it globally (-g), not as a hook in this repo: a committed hook would fail for anyone who hasn't installed the binary.

Your content

content/ is a plain folder of markdown you can edit directly, in the app, or both — the sections read and write the same files.

content/
├─ tasks/active.md ← Tasks tab. Standing quadrants + a Today block.
├─ tasks/journal.md ← Journal tab. One `## YYYY-MM-DD` entry per day.
├─ team/task-labels.json ← the [@label] chips Tasks can put on a task
├─ memory/CLAUDE.md ← the wiki's hub (starts empty)
├─ sources/ ← drop documents here for /wiki-ingest
└─ meetings/
├─ example.md ← 2 example meetings, with action items owned by you and others
├─ example-planning.md ← a second bucket, so you can see the grouping
└─ archive/ ← notes archived from the UI (one example inside)

Want to see the Pull requests tab populated too? It needs no token for that:

cp -R .data.example .data && make dev

That gives you one example squad and a saved checkpoint — PRs grouped by state, a Slack signal, and a ready-to-paste draft — rendered from stored JSON, so there are no GitHub calls at all. Delete .data/ when you want to add your own squad; see .data.example/README.md.

Two formats are strict, and the files show both:

  • Journal entries need ## YYYY-MM-DD headings. Any other heading is ignored.
  • Tasks needs **Top 3:** written exactly like that, with a numbered list under it, or the Top 3 silently won't render.

A task title can carry two leading markers, both optional and both editable from the Tasks tab:

  • Priority[P0] now · [P1] this cycle · [P2] later · [P3] nice-to-have. The board sorts by it, and an unmarked task sorts above [P3], so dropping the marker isn't a way to park something.
  • Work type[Ship], [Quality], … whatever src/work-types.ts declares. /setup generates that file from your role, because the useful buckets differ: an IC's week splits into shipping / quality / support / growth, a manager's into delivery / capacity / engineering-excellence, a PM's barely touches building at all. Presets cover the engineering ladder plus product management and product design — this board isn't engineering-only. .claude/scripts/setup/apply-work-types.mjs --list shows them; the file is plain TypeScript in your repo, so edit it freely (it survives pnpm update).

Already keep notes somewhere else? Point CONTENT_ROOT at that folder in .env and the sections read it instead — it just needs the same layout.

Adding another section

pnpm add @asucregonzalez/section-<name>

Then three edits:

  1. src/sections.ts — import the descriptor and drop it into the right group's children (this drives the tab bar).
  2. server/index.ts — if the section has a backend, add its register…Routes to the routers list.
  3. src/GuideView.tsx — add a card carrying section: '<its id>'. Nothing breaks if you skip it, but the Guide's "How to use" lists the section at the bottom as undocumented until you do.

Removing one is the same list in reverse, minus the Guide: a card whose section is no longer installed hides itself, so only sections.ts, server/index.ts and the pnpm remove are yours to do.

Layout

PathWhat it is
makefileShortcuts — make lists them
CLAUDE.mdWorkspace map + the conventions the skills and dashboard share
.claude/skills/The skills that maintain your content and wiki
.claude/scripts/setup/One-time bootstrap scripts
content/memory/Your wiki — starts empty
src/sections.tsThe one file that decides which sections you run
src/work-types.tsYour role's work-type buckets, generated by /setup — yours to edit
src/HomeView.tsxThe Home page
src/App.tsxThe shell: tab bar + the active section's view + host config
server/index.tsExpress server; mounts each section's routes
tailwind.config.jsLoads the shared theme preset, and scans installed sections for classes
content/Your markdown (see above)
.data/Pull-requests state: projects, squads, saved checkpoints — gitignored
.data.example/Committed example of the above — cp -R .data.example .data to see it

Gotchas

  • src/index.css: the @import '@asucregonzalez/theme/base.css' must stay above the @tailwind directives. postcss-import only inlines @import at the top of a file, so moving it down silently drops every component class and sections render half-styled.
  • tailwind.config.js: keep the ./node_modules/@asucregonzalez/*/dist/**/*.js content glob. Sections ship compiled markup, and Tailwind purges any class it can't see.
  • No "Regenerate" buttons? Expected. Those re-run a Claude skill on the host; this app sets refreshEnabled: false in src/App.tsx, so sections hide them rather than offer a button that can't work. If you build your own /api/refresh/<skill> route, flip it to true.
  • Sections render unstyled? You're missing presets: [ccPreset] or one of the two points above.
  • pnpm install edited pnpm-workspace.yaml? Expected, and harmless. pnpm 11 quarantines very recently published packages as a supply-chain precaution; when a section release is newer than that window it adds the versions to minimumReleaseAgeExclude and proceeds. Commit it or discard it, either is fine.

About

Start your own Command Center — install the sections you want

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages