- Node.js 24.16+ and TypeScript
- Express +
wsfor HTTP and WebSocket - xterm.js in the browser, React for the shell UI
- Pseudo-terminals via
@lydell/node-pty(prebuilt binaries, never node-gyp) - Persistence via Node's built-in
node:sqlite - Mocha for tests
See docs/architecture.md for how it fits together.
bin/cc-web.js— CLI entry pointsrc/server/— server, routes, bridges, chat adapters, auth, persistencesrc/client/— browser TypeScript;shell/is React,terminal/is xtermsrc/shared/— types and logic used by both sidessrc/public/— static HTML, CSS, manifest, service workerscripts/build.js— the build pipelinetest/*.test.js— unit tests
git clone https://github.com/dnviti/code-agents-webcli.git
cd code-agents-webcli
npm install
npm run devnpm run build # compile server, bundle client, copy assets
npm run build:watch # rebuild on change
npm run dev # build, then start with extra logging
npm test # tests available on this host; reports capability-gated files
npm run test:strict # require every integration capability (used by CI)
npm run typecheck # server and client
npm run test:browser # headless browser checks against the real bundle
npm run verify:install # install the working tree into a clean prefix and start it- Keep diffs focused.
- Match the existing TypeScript and CommonJS style where each file already uses it.
- 2 spaces, semicolons.
- Comments explain why, not what. This codebase leans on them heavily for decisions that look arbitrary until you know what went wrong last time — keep that up.
- Prefer fast, isolated tests. Do not add real network calls or real agent CLIs to tests when a mock will do.
npx --allow-git=all github:dnviti/code-agents-webcli has to stay a single
command that compiles nothing. That is not a preference — npm 12 blocks
dependency install scripts by default, and an npx run has no project
package.json in which to record an approval, so one dependency with an
install script silently turns the documented one-liner back into a
toolchain-and-four-commands ritual.
So:
- Do not add a production dependency that compiles or has an install script.
test/install-surface.test.jsfails if you do, and CI installs the working tree into an empty prefix on a clean runner to catch what a local test cannot. - Anything only needed to build belongs in
devDependencies. React, xterm and Mermaid are bundled at build time and never loaded at runtime; shipping them as runtime dependencies added ~150 MB to every install for nothing.@xterm/headlessis the exception — the server actually runs it. - The two platform bindings are isolated in
src/server/services/pty.tsandsrc/server/services/sqlite.ts. Change them there, not at the call sites.
Run npm run verify:install before touching anything in package.json,
scripts/build.js, or those two modules.
- GitHub OAuth is the only supported user authentication flow.
- Internal users are keyed by GitHub numeric IDs.
- Do not reintroduce token-based login paths.
- Treat the SQLite database as sensitive: it stores auth session data and OAuth configuration.
- The installer account (the first ever to sign in) is the only one that may change runtime profiles or apply an update. Both change what runs for everybody, so keep new privileged actions on the same footing.
- One per-user
app.sqliteowns installation settings, users, auth sessions, runtime/session metadata, composer drafts, usage accounting and immutable references to each session's project storage scope. - Projects do not contain SQLite databases. Bulk project data lives in the
authorised workspace's
.cc-web/: scrollback, chat events and transcripts are append-only files with fixed-width indexes, alongside pasted images and attachments. - Production has no automatic migration from older storage layouts. Leave unrecognised legacy files untouched.
- Keep schema changes backward-compatible where possible.
- If you change persisted structures, update the tests and the docs in the same change.
User-facing documentation lives in docs/; the README is
deliberately short and links out. If you change a flag, an environment variable,
an auth flow, the install steps or the release behaviour, update the matching
guide in the same pull request — a wrong flag name in the docs is a real defect.
- Use Conventional Commits.
- Include screenshots for UI changes.
- Call out auth, persistence, install-surface or workflow risks explicitly.
main is the release branch.
- Land the version bump on
main. .github/workflows/release-on-main.ymlruns.- It validates the build, tags
v<version>, cuts a GitHub release, and pushes the image to GHCR.
The project is distributed from git and as a container image, not through the
npm registry, so a release needs no npm account or token. Pushing to GHCR uses
the GITHUB_TOKEN Actions provides automatically.