A personal command center dashboard. Aggregates GitHub issues and PRs, Google Calendar, Obsidian tasks and notes, daily standups, and local infrastructure status into a single tabbed UI — running locally at https://command.test.
| Urgent & Bugs | Active | PRs |
|---|---|---|
![]() |
![]() |
![]() |
| Backlog | Infra | Notes |
|---|---|---|
![]() |
![]() |
![]() |
| Tasks | Calendar | Repos |
|---|---|---|
![]() |
![]() |
![]() |
| Done | OpenClaw |
|---|---|
![]() |
![]() |
| Tab | Data source | Refresh |
|---|---|---|
| Home | Aggregated summary of all sources | On load |
| Urgent | GitHub issues labeled bug, critical, urgent |
5 min |
| Active | GitHub issues labeled enhancement, feature, etc. |
5 min |
| Backlog | All other open GitHub issues | 5 min |
| PRs | Open pull requests across tracked repos | 5 min |
| Notes | Obsidian daily note + project decisions + daily standup | 5 min |
| Infra | PM2 process list (uptime, memory, restarts) | On demand |
| Tasks | Open tasks from Obsidian vault markdown files | 2 min |
| Calendar | Google Calendar events — next 30 days | 10 min |
| Repos | All GitHub repos with open issue counts | 5 min |
| Analytics | Umami analytics snapshot | 15 min |
Keyboard shortcuts: H Home · U Urgent · A Active · B Backlog · P PRs · N Notes · I Infra · T Tasks · C Calendar · R Repos · / Search · Shift+R Refresh · ? Help
Quick actions: Hover any issue card to reveal a close button (×).
Notification dots: Red pulsing dot appears on tab badges when new issues or PRs arrive since your last visit.
Dark/light mode: Toggle via the moon/sun button in the header. Persists to localStorage.
- Backend: Node.js + Express
- Frontend: Angular + Tailwind
- Process manager: systemd user services for durable local runtime on Linux, PM2 optional for other workflows
- Data sources:
ghCLI · Google Calendar iCal · Obsidian markdown · PM2jlist· Umami
| Tool | Install |
|---|---|
| Node.js 22+ | nodejs.org or nodenv install 22.x |
gh CLI |
brew install gh then gh auth login |
| PM2 (optional) | npm install -g pm2 if you want PM2-managed workflows or live PM2 infra data |
git clone git@github.com:DamageLabs/command-center.git
cd command-center
npm install
npm --prefix frontend installCopy the example env file and config file:
cp .env.example .env
cp config.example.json config.local.jsonEdit .env for calendar URLs:
# Optional custom config path
# COMMAND_CENTER_CONFIG=./config.local.json
# Calendar URLs (optional)
CALENDAR_URLS=
CAL_1=https://calendar.google.com/calendar/ical/you@gmail.com/private-xxxxx/basic.ics
CAL_2=https://calendar.google.com/calendar/ical/group.calendar.google.com/private-xxxxx/basic.icsEdit config.local.json for your machine:
{
"server": {
"host": "127.0.0.1",
"port": 4500
},
"github": {
"trackedRepos": [
"YourOrg/repo-one",
"YourOrg/repo-two",
"yourusername/personal-repo"
],
"orgs": [
{
"owner": "YourOrg",
"repoLimit": 200
}
]
},
"obsidian": {
"vaultDir": "/path/to/your/obsidian/vault",
"dailyDir": "/path/to/your/obsidian/vault/03 - Periodic/01 - Daily",
"decisionsDir": "/path/to/your/obsidian/vault/08 - Projects/DamageLabs/Decisions",
"tasksDir": "/path/to/your/tasks/folder",
"taskFiles": [
{ "file": "Tasks.md", "label": "General", "color": "amber" },
{ "file": "Work Tasks.md", "label": "Work", "color": "blue" }
]
},
"standup": {
"dir": "${HOME}/Code/brain/standups/daily"
}
}config.local.json is ignored by git and is the recommended place for personal paths and repo lists.
Get your iCal URLs: Google Calendar → Settings → [Calendar name] → Secret address in iCal format
Task files should use standard Obsidian checkbox format:
- [ ] Task title #todo 📅 2026-04-10
- [x] Completed task ✅ 2026-04-01Standup files should be named YYYY-MM-DD.md and use ### Repo/Name sections.
Issue bucketing is still controlled in server.js via issuePriority(labels).
# Development (Angular dev server + Express API together)
npm run dev
# Or run them separately
npm run dev:api # Express API on :4500
npm run dev:web # Angular dev server on :4200, proxying /api to :4500
# Durable local runner on Linux via systemd --user
npm run dev:durable:start
npm run dev:durable:status
npm run dev:durable:logs -- -f
# Build the shipped Angular UI
npm run build:web
# Verify the current shipped setup
npm run check
# Serve the built Angular UI through Express
npm start
# PM2 remains optional for PM2-managed workflows
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup # auto-start on rebootRuns on http://localhost:4500.
npm run devis still fine for interactive work, but it has proven brittle on Spark for longer-lived local sessionsnpm run dev:durable:startinstalls and starts user-level systemd services for the API and web processes, reclaiming ports4500and4200from stray old dev processes if needednpm run dev:durable:statusandnpm run dev:durable:logs -- -fare the supported way to inspect or tail the durable local runner- see
docs/local-runtime.mdfor the full workflow
- Angular dev server runs on http://localhost:4200
frontend/proxy.conf.jsonproxies/api/*to the existing Express backend on :4500npm startnow serves the built Angular frontend fromfrontend/dist/frontend/browser- if the Angular dist is missing, Express returns a helpful message telling you to run
npm run build:webornpm run dev - the legacy single-file frontend has been archived under
archive/legacy-static-frontend/ - the Infra view may still degrade when PM2 is not installed, because that panel currently reads PM2 state
Install Caddy and dnsmasq, then:
dnsmasq — resolve *.test to localhost:
# /opt/homebrew/etc/dnsmasq.conf
address=/.test/127.0.0.1
Caddyfile — proxy with auto TLS:
command.test {
reverse_proxy localhost:4500
tls internal
}
sudo brew services start dnsmasq
sudo caddy reload --config /opt/homebrew/etc/CaddyfileThen open https://command.test — first visit will prompt to trust the local CA.
| Endpoint | Method | Description |
|---|---|---|
/api/issues |
GET | Issues grouped as urgent, active, deferred |
/api/repos |
GET | All repos with open issue counts |
/api/prs |
GET | Open pull requests across tracked repos |
/api/calendar |
GET | Events for next 30 days |
/api/tasks |
GET | Open Obsidian tasks |
/api/notes |
GET | Daily note + recent decisions |
/api/analytics |
GET | Umami analytics totals + site breakdown |
/api/standup |
GET | Most recent daily standup |
/api/infra |
GET | PM2 process list |
/api/refresh |
POST | Force refresh all data sources |
/api/issues/:owner/:repo/:number/close |
POST | Close a GitHub issue |
| Source | Interval |
|---|---|
| GitHub issues | 5 min |
| GitHub PRs | 5 min |
| Google Calendar | 10 min |
| Obsidian tasks | 2 min |
| Obsidian notes + decisions | 5 min |
| Daily standup | 10 min |
| UI auto-refresh | 30 sec |
node scripts/capture-doc-screenshots.jsRequires the server to be running on port 4500. Screenshots are saved to docs/screenshots/.
Apache License 2.0. See LICENSE.











