A single-user, workspace-centric application for creating, managing, and interacting with isolated AI agents through persistent direct chat. Built with Node.js, TypeScript, React, and the OpenCode AI engine.
No auth, no multi-tenancy. You install it, you run it, you own it.
| Layer | Technologies |
|---|---|
| Frontend | React 19, Vite, Tailwind CSS v4, Shadcn/UI |
| Backend | Fastify, Drizzle ORM, Zod 4, Pino |
| Database | PostgreSQL (cloud) / SQLite (local) |
| AI | OpenCode engine, MCP SDK, Composio |
| Testing | Vitest, Playwright |
| Tooling | pnpm workspaces, ESLint, Prettier, Husky, GitHub CI |
- Node.js >= 24
- pnpm (
npm install -g pnpm)
git clone <repo-url> cc
cd cc
pnpm install
pnpm devThis starts both the backend (port 3000) and frontend (port 5173) dev servers.
The backend manages a single persistent opencode serve engine process in the background.
opencode serve --hostname=127.0.0.1 --port=4096In CommandsCenter this command is started and monitored by the backend orchestrator.
CommandsCenter production use is centered on the globally installed ccenter binary from the commandscenter npm package. Runtime state is portable and lives in the workspace directory, not in the npm package install directory.
ccenter loads environment variables in this order:
- Existing process environment variables win.
--cc-env-file <path>loads values from an explicit file.ccenter startandccenter servecreate the file from.env.prod.examplefirst when it is missing.- If no
--cc-env-fileis passed,~/.cc/.envis loaded.ccenter startandccenter servecreate it from.env.prod.exampleon first run when missing. - Built-in defaults are used for optional settings.
Default global layout:
~/.cc/
├── .env
└── workspace/Minimal production .env:
NODE_ENV=production
CC_HOST=0.0.0.0
CC_PORT=3000
CC_WORKSPACE_DIR=/home/commandscenter/.cc/workspace
CC_SECRET_KEY=replace-with-a-long-random-secretSQLite is used by default at $CC_WORKSPACE_DIR/database/local.db. Set DATABASE_URL only when you want PostgreSQL as the primary database.
npm install -g commandscenter
ccenter startOn first start, ccenter creates ~/.cc/.env from .env.prod.example, generates a secure CC_SECRET_KEY, and stores runtime state in ~/.cc/workspace. The web UI shows a one-time notice reminding you to save that key.
Useful commands:
ccenter --version
ccenter start --host 127.0.0.1 --port 3000
ccenter start --cc-env-file /opt/commandscenter/.env
ccenter serve --cc-env-file /opt/commandscenter/.env
ccenter upgrade
ccenter upgrade --rollbackRemove the global install:
npm uninstall -g commandscenterRemove the workspace data too:
rm -rf ~/.ccThe npm uninstall removes the ccenter binary, but it does not delete your workspace state unless you remove the workspace directory yourself.
Version status is also exposed over HTTP:
curl http://127.0.0.1:3000/api/system/versionThe repository includes a cross-platform installer for Ubuntu/Linux with systemd and macOS with launchd. It checks for Node.js, installs missing requirements when possible, installs CommandsCenter globally, lets ccenter generate the production .env file on first service start, starts the app as a background service, and prints the app URLs plus filesystem locations.
Install and start the background service:
bash scripts/install-ccenter-service.shGracefully stop the local runtime described by ~/.cc/.env:
bash scripts/stop-ccenter-service.shUse a different env file when needed:
bash scripts/stop-ccenter-service.sh --env-file /opt/commandscenter/.envContributor-only local tarball testing is documented in CONTRIBUTING.md.
Useful overrides:
CCENTER_INSTALL_DIR=/opt/commandscenter \
CCENTER_WORKSPACE_DIR=/opt/commandscenter/workspace \
CCENTER_ENV_FILE=/opt/commandscenter/.env \
CCENTER_HOST=127.0.0.1 \
CCENTER_PORT=3000 \
bash scripts/install-ccenter-service.shOn Ubuntu, the script writes /etc/systemd/system/commandscenter.service. On macOS, it writes ~/Library/LaunchAgents/com.commandscenter.app.plist.
Use a global npm install plus a systemd service. Keep runtime files and .env in /opt/commandscenter.
sudo mkdir -p /opt/commandscenter
sudo chown -R "$USER":"$USER" /opt/commandscenter
cd /opt/commandscenter
npm install -g commandscenterThe first service start creates /opt/commandscenter/.env from .env.prod.example, generates CC_SECRET_KEY, and stores workspace state in /opt/commandscenter/workspace.
Create /etc/systemd/system/commandscenter.service:
[Unit]
Description=CommandsCenter
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/commandscenter
Environment=CC_HOST=127.0.0.1
Environment=CC_PORT=3000
Environment=CC_WORKSPACE_DIR=/opt/commandscenter/workspace
ExecStart=/usr/bin/env ccenter start --host 127.0.0.1 --port 3000 --cc-env-file /opt/commandscenter/.env
Restart=on-failure
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=30
[Install]
WantedBy=multi-user.targetStart and inspect it:
sudo systemctl daemon-reload
sudo systemctl enable commandscenter
sudo systemctl start commandscenter
sudo systemctl status commandscenter
journalctl -u commandscenter -f
curl http://127.0.0.1:3000/api/healthUpgrade on VPS:
cd /opt/commandscenter
ccenter upgrade --cc-env-file /opt/commandscenter/.env
sudo systemctl restart commandscenterccenter upgrade exits after a successful package update. A process supervisor such as systemd should restart the service.
Docker images install the same global commandscenter npm package inside the container and run ccenter start. Docker installations do not self-update from inside the container. The app reports update guidance from /api/system/version and /api/system/update; the operator pulls a new image and restarts the container.
Build the image from the published npm package:
docker build -t commandscenter:local .Pin a specific published version when needed:
docker build --build-arg CCENTER_PACKAGE_SPEC=commandscenter@0.2.6 -t commandscenter:0.2.6 .services:
commandscenter:
image: commandscenter:local
ports:
- "3000:3000"
volumes:
- ./workspace:/workspace
environment:
NODE_ENV: production
CC_DOCKER: "true"
CC_HOST: 0.0.0.0
CC_PORT: "3000"
CC_WORKSPACE_DIR: /workspace/.cc/workspace
restart: unless-stoppedOn first container start, ccenter creates /workspace/.cc/.env on the mounted volume and generates CC_SECRET_KEY there.
Run and verify:
docker compose up -d
docker compose logs -f commandscenter
curl http://127.0.0.1:3000/api/health
curl http://127.0.0.1:3000/api/system/versionUpdate Docker deployment:
docker compose pull
docker compose up -dContributor-only source-build smoke tests are documented in CONTRIBUTING.md.
cc/
├── packages/
│ ├── frontend/ # React 19 + Vite app
│ ├── backend/ # Fastify + Node.js server
│ ├── cli/ # CLI binary (ccenter) — bundles backend + frontend
│ └── shared/ # Shared Zod schemas, types, constants
├── design/ # Screen specs, layout, themes
├── .cc/ # Runtime workspace data (portable)
└── examples/ # Reference repositories (gitignored)
| File | Purpose |
|---|---|
| GOAL.md | Product vision, features, phases |
| AGENTS.md | Coding standards, tech stack, conventions |
| CONTRIBUTING.md | Dev setup, commands, workflow |
| PRD.md | Product requirements |
| tech-research.md | Architecture blueprint |
Releases are published to npm as the commandscenter package. The version in packages/cli/package.json is the source of truth; publishing a GitHub Release with tag vX.Y.Z triggers .github/workflows/publish.yml, which validates the tag, runs the publish gate, and runs npm publish --access public --provenance. See the Releasing section in CONTRIBUTING.md for the full flow.
A floating panel available in development mode to test UI components that are hard to trigger manually (tool renderers, TodoDock, error cards, etc.).
Toggle: Ctrl+Shift+D on any chat page.
| Button | What it injects |
|---|---|
| Inject Todos | 3 todo items — TodoDock appears above composer |
| Clear | Removes all todos |
| Bash | Completed shell command with sample output |
| Context Group | 3 consecutive read/glob/grep parts — collapsed "Gathered context" row |
| Error | Bash tool with error status — red error card |
| Question | Completed Q&A tool with 2 questions and answers |
| Task | Explore subagent task card |
Tool part buttons require at least one assistant message (they attach to the latest). Dev-only via import.meta.env.DEV — zero bundle impact in production.
Source: packages/frontend/src/components/dev/DevDebugPanel.tsx
See LICENSE for details.