Repository map
The git root is the product repo, not the application working directory. Day-to-day code lives in app/. Everything else is packaging, docs, examples, or agent skills.
Top level
| Path | Role |
|---|---|
app/ | The TypeScript application. Bun project. This is where you bun install, bun test, and bun run src/bin.ts. |
docs/ | User-facing wiki source (top-level *.md) plus this internals tree (docs/internals/). VitePress site in docs/.vitepress/. |
schema/devctl.config.schema.json | JSON Schema for .devctl YAML. Must stay in parity with adapters/config (schema-parity.test.ts). |
skills/devctl-onboard/ | Agent skill for onboarding other repos to .devctl/. Not instructions for changing devctl itself. |
skills/devctl-debug/ | Agent skill for diagnosing a service devctl is already running. Does not author .devctl YAML. |
examples/demo-platform/ | Local invoicing stack used in CI (devctl config validate) and docs. No Google Cloud required. |
packaging/npm/ | Node launcher shipped inside the npm tarball (wraps a platform binary). |
design/ | Design notes that are not user docs (for example the OTEL model). |
.github/ | CI, release, wiki publish, issue templates, compile/smoke scripts. |
.cursor/rules/ | Architecture and onboard rules for agents working in this checkout. |
CONTRIBUTING.md | Source loop and pointer to this guide. |
AGENTS.md | Split: onboard other repos vs contribute this app. |
SECURITY.md | Vulnerability reporting. |
CHANGELOG.md | Released user-visible changes. |
There is no Go tree, no cmd/, and no separate daemon binary source. bin.ts is the only entry; _supervisor is a hidden CLI subcommand that stays in-process as a second OS process.
Inside app/
| Path | Role |
|---|---|
src/bin.ts | Shebang entry. Silences GCP metadata warnings, then execute(createClient(), runDaemon). |
src/bootstrap/ | Composition roots: client, daemon, test fixtures. |
src/domain/ | Pure types and policies. No Google SDK, no OpenTUI, no node:fs adapters. |
src/application/ | Use cases: commands, orchestrator, health monitor, compose import, setup starter. |
src/ports/ | Interfaces at replaceable boundaries only. |
src/adapters/ | I/O: config files, processes, Google, proxy, storage, daemon host, RPC. |
src/presentation/ | CLI, TUI, MCP HTTP, web HTTP. May import application/ports/domain/shared. |
src/shared/ | Events, errors, redaction, retry, bearer compare, repo id. Used by every layer. |
src/plugin-sdk.ts | Public re-exports for file plugins. Path kept stable. Knip-ignored as a public entry. |
src/types.ts | RPC Envelope only. |
src/version.ts | VERSION (overridable via DEVCTL_VERSION) and RPC_PROTOCOL_VERSION. |
src/architecture.test.ts | Examples of allowed/forbidden imports; calls scripts/check-architecture.ts. |
web/ | Loopback SPA (React). Bundled into presentation/web/assets.generated.ts. |
scripts/ | Architecture checker, coverage gate, npm/homebrew/web/guide generators. |
tui.json | Default TUI preferences checked in with the app (theme, keybinds, MCP flags). |
knip.jsonc | Dead-code rules. credential-provider.ts and plugin-sdk.ts are ignored on purpose. |
Layers under app/src/ (physical folders)
app/src/
bin.ts bootstrap (special-cased)
types.ts, version.ts shared (special-cased)
plugin-sdk.ts adapters (public facade)
bootstrap/ composition roots
presentation/ cli / tui / mcp / web
application/ commands, orchestrator, health-monitor
domain/ config, service, identity, logs, llm, http, telemetry, …
ports/ Clock, ProcessRuntime, LogStore, …
adapters/ daemon, rpc, config, process, google, proxy, …
shared/ Bus, DevctlError, redactionThe architecture checker assigns a layer from the first path segment (or from bin.ts / types.ts / version.ts). *.test.ts and *.test.tsx are layer test and may import anything.
Generated files (do not edit by hand)
| File | Regenerated by | Source of truth |
|---|---|---|
presentation/mcp/docs.generated.ts | bun run sync-guide | docs/*.md (top-level only) |
presentation/mcp/guide.generated.ts | bun run sync-guide | skills/devctl-onboard/, skills/devctl-debug/ |
presentation/web/assets.generated.ts | bun run build:web | app/web/ |
guide.test.ts and docs-search.test.ts fail until sync-guide is re-run after editing those sources.
State on disk (not in git)
Default home is ~/.devctl (DEVCTL_HOME overrides).
| Path | Role |
|---|---|
state/<repoID>/ | state.json, devctl.lock, rpc-token, Unix devctl.sock, bootstrap.log |
logs/ | Optional persisted session logs |
exports/ | devctl logs export output |
credentials/ | Filesystem fallback for secrets (mode 0600) |
tui.json | User TUI overlay |
config.local.yaml | Machine overlay merged into repo config |
repoID is the first 16 hex characters of sha256(absolute repo root) (shared/repo-id.ts). Two checkouts of the same git repo are two sessions.
Docs vs this guide
| Audience | Location | Published to |
|---|---|---|
| People running stacks | docs/*.md | GitHub Wiki + VitePress + MCP search |
| People changing this repo | docs/internals/*.md | VitePress + git; not the wiki, not MCP search |
| Agents onboarding other repos | skills/devctl-onboard/ | Embedded in MCP get_setup_guide (procedure, authoring, discovery) |
| Agents debugging a service devctl is running | skills/devctl-debug/ | Embedded in MCP get_setup_guide section debug |