This guide is for contributors building CodeDecay from source.
CodeDecay is a TypeScript/pnpm monorepo. It does not require a local database, seed data, Docker stack, cloud account, API key, LLM key, or model call to run the current OSS toolchain.
| Tool | Purpose |
|---|---|
| Node.js 20+ | Runtime and build tooling |
| pnpm 11.8.0 | Package manager |
| Git | Diff and fixture integration tests |
| gh | Recommended for issue and PR workflow |
./.codedecay/setup.local.shThe setup script:
- checks prerequisites,
- runs
pnpm install, - runs lint, typecheck, tests, and build,
- writes
.codedecay/local/state.json.
Re-run it after pulling large dependency or package changes.
./.codedecay/status.local.sh
./.codedecay/teardown.local.shteardown.local.sh only removes generated CodeDecay local state. There are no
containers, database volumes, or seed services to remove.
pnpm run lint
pnpm typecheck
pnpm test
pnpm build
pnpm --filter @submuxhq/codedecay pack --dry-runRun the built CLI:
node packages/cli/dist/index.js --help
node packages/cli/dist/index.js analyze --format markdown
node packages/cli/dist/index.js config --format markdownRun the local end-user demo harness before changing broad CLI behavior:
pnpm demo:end-userYou can pass a stable run id with or without pnpm's argument separator:
pnpm demo:end-user --run-id local-dogfood
pnpm demo:end-user -- --run-id local-dogfoodThe harness builds the local CLI, creates isolated demo git repositories, runs the user-facing commands, starts a real MCP client smoke, simulates the GitHub Action runtime, and writes command logs to:
.codedecay/local/end-user-demo/<run-id>/run.json
.codedecay/local/end-user-demo/<run-id>/summary.md
run.json includes commands, cwd, exit code, duration, stdout, stderr, parsed
JSON when available, and output file metadata. Use it as the first reproduction
artifact when filing follow-up bugs from dogfood runs.
The end-user harness also creates a separate loop fixture. A deterministic local agent command edits a weak test, CodeDecay re-runs the repository's real test command, and the harness requires the weak-test count and merge risk to drop before accepting a merge-safe verdict.
Run the published-package demo when you need to test CodeDecay like a new user would install it from npm or from a local tarball:
pnpm demo:published-package --package @submuxhq/codedecay@latest
pnpm demo:published-package --tarball ./submuxhq-codedecay-<version>.tgzThis smoke creates a fresh tool install, materializes the Next.js and Node API
example repos, runs the installed codedecay binary, and writes logs to:
.codedecay/local/published-package-demo/<run-id>/run.json
.codedecay/local/published-package-demo/<run-id>/summary.md
Run the strongest local acceptance path before releases or broad orchestration, execution, MCP, Action, loop, or product-testing changes:
pnpm test:child-repo-e2e -- --run-id local-child-repoThis is intentionally stronger and slower than pnpm test. It:
- packs the built npm package,
- installs that tarball and Playwright in an independent git repository,
- executes the child repository's configured test command through CodeDecay,
- starts a real local web application,
- launches Chromium, crawls two pages, records PNG screenshots, and runs the generated Playwright regression suite,
- runs the installed CLI through analyze, redteam, agent, execute, differential, MCP, Action simulation, and deterministic repair-loop paths.
The command downloads @playwright/test and Chromium explicitly. It does not
call a model, require an API key, send telemetry, or access a production
service. Evidence is written under:
.codedecay/local/child-repo-e2e/<run-id>/run.json
.codedecay/local/child-repo-e2e/<run-id>/summary.md
Test levels are deliberately separate:
pnpm test: fast unit, integration, and built-CLI contracts.pnpm demo:published-package: fresh package-install smoke.pnpm test:child-repo-e2e: installed-package acceptance in child repos with real execution and Chromium.pnpm test:real-oss-adapters: opt-in upstream adapter verification for Playwright, StrykerJS, Schemathesis, Pact, Semgrep, and coverage.
Examples live in:
.codedecay/config.example.yml.codedecay/memory.example.json
Copy them only when you intentionally want repo-local config or memory:
cp .codedecay/config.example.yml .codedecay/config.yml
cp .codedecay/memory.example.json .codedecay/memory.jsonKeep safety.allowCommands: false unless you are explicitly testing
codedecay execute or codedecay differential.
Shared agent resources live in .agents/.
- Commands:
.agents/commands/ - Skills:
.agents/skills/ - Codex MCP config:
.codex/config.toml - Cursor rules:
.cursor/rules/codedecay.mdc - Cursor MCP config:
.cursor/mcp.json - Claude pointer:
CLAUDE.md - Claude command/skill links:
.claude/commands,.claude/skills - OpenCode config:
opencode.json - Shared MCP config:
.mcp.json
Build before using the local MCP server:
pnpm build
node packages/cli/dist/index.js mcpThe agent-agnostic redteam harness roadmap is documented in RFC 0001.
- Create or use a GitHub issue.
- Branch from latest
main. - Keep the PR focused.
- Run
.agents/commands/ci-check.md. - Include
Closes #<issue-number>in the PR body.
Do not push directly to main.