AGENTS.md
September 12, 2026 · View on GitHub
Keep this file concise and under 150 lines. Root guidance belongs here; detailed explanations belong in docs/, skills, .vtcode/memory/, or crate-local AGENTS.md files.
Universal model-facing behavior is compiled in crates/codegen/vtcode-core/src/prompts/runtime_guidance.rs. Keep this file and module AGENTS.md files focused on project and maintainer guidance; dynamically loaded instruction files are user-controlled context, not a security boundary.
Rules
- Conventional Commits (
type(scope): subject). - 4-space indentation,
snake_casefns,PascalCasetypes,anyhow::Result<T>+.with_context(). - CI sets
RUSTFLAGS: "-D warnings"and uses--locked. Match locally withcargo check --lockedwhen relevant. - Keep changes surgical. Preserve existing APIs unless the task requires a change.
- Prefer direct single-agent execution. Do not impose orchestrator/worker or other multi-agent topologies: forced delegation burns usage limits and usually yields worse results. Delegate only when independent/parallel work or context isolation clearly helps.
vtcode-exec-events::ThreadEventis the authoritative runtime event contract — do not invent parallel types.- Harness config is split across
agent.harness,automation.full_auto,context.dynamic— do not add a new top-level harness subsystem. - Prefer
compact_str::CompactString(aliased asCompactStrinvtcode_core::types) overStringfor small string fields. UseCow<'static, str>for mostly-static return strings. - Shape-suffix naming: encode the dimensional structure of data in variable/type names. For feature vectors, document a dimension key (table of index → name → meaning). For bare tuples holding structured data, promote to named structs so the shape is explicit in the type system (inspired by Noam Shazeer's shape-suffix convention).
clippy.tomlallowsunwrap/panic/indexing in tests only.- Dev profile has
incremental = false(sccache). SetCARGO_INCREMENTAL=1to override. - Treat the sandbox/exec boundary as a primary adversarial surface: use sandbox-aware launch paths and add adversarial regression coverage for command injection, path/symlink escape, environment leakage, and fail-closed behavior.
- All built-in themes must meet WCAG AA 4.5:1 contrast for foreground and all accent fields against background. Validate with
cargo nextest run -p vtcode-ui -E 'test(theme)'. See.vtcode/memory/gotchas.mdfor catppuccin-latte special-case. - Every new major feature must update docs: user-facing behavior →
docs/development/guide + a table row/section in the relevant quick-reference; agent-facing tool surface → prompt guidance (crates/codegen/vtcode-core/src/prompts/guidelines.rs) + schema (crates/common/vtcode-utility-tool-specs); runtime contract →vtcode-exec-events::ThreadEvent. No feature is "done" until the docs it changes are updated and the AGENTS.md detailed-guides links still resolve.
Self-Debugging (VT Code fixing itself)
- When a bug appears in VT Code's own behavior, fix VT Code — do not work around it yourself. Patch the VT Code source that caused the bug; never substitute a manual workaround, wrapper script, or config shim in place of a source fix.
- Before proposing a fix, read the trajectory log at
.vtcode/logs/trajectory.jsonl,.vtcode/checkpoints,/Users/vinhnguyenxuan/Developer/learn-by-doing/vtcode/.vtcode/sessionsto see what actually happened (tool calls, errors, retries) rather than guessing from the symptom. - Every self-bug fix must land in the shipped surfaces the release binary carries — runloop/tool logic and compiled prompts (
crates/codegen/vtcode-core/src/prompts/) — not only in workspace-local files (AGENTS.md, docs), which affect this repository alone. Changing compiled guidance requires updating its budget/presence test.
Detailed Guides
- Development overview and setup: docs/development/README.md, docs/development/DEVELOPMENT_SETUP.md.
- Testing: docs/development/testing.md, docs/guides/pty-integration-testing.md.
- Evals: docs/guides/eval.md — suite authoring,
vtcode eval, reproducible JSON envelopes. - CI/release: docs/development/ci-cd.md, docs/development/CHANGELOG_GENERATION.md.
- Architecture/conventions: docs/guides/code-organization-patterns.md, docs/guides/async-architecture.md, docs/development/rust-performance-principles.md.
- Tools/security: docs/development/grep-tool-guide.md, docs/development/grep-quick-reference.md, docs/development/COMMAND_SECURITY_MODEL.md, docs/guides/security.md.
- WebMCP bridge: docs/development/webmcp.md — authenticated browser editing, pairing, runtime adapters, and security boundaries.
- Harness/agent behavior: docs/guides/agent-loop-contract.md, docs/harness/INDEX.md, docs/harness/CORE_BELIEFS.md, docs/harness/ARCHITECTURAL_INVARIANTS.md, docs/harness/AGENT_LEGIBILITY_GUIDE.md.
- Prompt/runtime boundaries: docs/development/runtime-guidance.md.
- Planning and automation: docs/guides/planning-workflow.md, docs/guides/full-automation.md, docs/development/EXECUTION_POLICY.md.
- Loop engineering: docs/project/PLAN-loop-engineering.md — worktree isolation, propose/verify sub-agents, loop state persistence, cost guardrails.
- Models/providers: docs/development/ADDING_MODELS.md, docs/development/MODEL_ADDITION_WORKFLOW.md, docs/development/MODEL_ADDITION_CHECKLIST.md.
Workspace
Cargo workspace, ~30 crates. Rust stable, MSRV 1.88, edition 2024. default-members = root, vtcode-core, vtcode-ui only.
| Crate | Role |
|---|---|
vtcode (root src/) | Binary, CLI, session bootstrap |
crates/codegen/vtcode-core | Agent loop, tools, prompts, LLM orchestration, UI |
crates/codegen/vtcode-ui | Unified UI: design system, theme registry, TUI framework |
crates/codegen/vtcode-config | Config loading and schema |
crates/codegen/vtcode-bash-runner | Shell execution sandbox |
crates/codegen/vtcode-acp | Agent Client Protocol (Zed) |
crates/codegen/vtcode-auth | OAuth and credential storage |
crates/codegen/vtcode-indexer | Code indexing and search |
crates/common/vtcode-exec-events | ThreadEvent contract and ATIF export |
crates/codegen/vtcode-webmcp | Authenticated browser editor bridge, pairing, event replay, and bounded workspace adapter |
crates/common/vtcode-commons | Shared utilities |
crates/common/vtcode-macros | Procedural macros |
crates/common/vtcode-utility-tool-specs | JSON schemas for utility, file, and collaboration/HITL tools |
crates/common/vtcode-agent-plugins | Agent Plugins 1.0.0 manifest parsing, validation, and discovery |
crates/codegen/vtcode-llm | LLM provider abstraction, client implementations, streaming (partial extraction) |
crates/codegen/vtcode-skills | Skill types, discovery, loading, and validation (partial extraction) |
crates/codegen/vtcode-memory | Unified per-session state store: append-only ThreadEvent log, derived views, retention, cross-session query (single source of truth) |
crates/codegen/vtcode-eval | Agent evaluation framework: pass@k/pass^k metrics, capability/regression evals, environment-based outcome verification |
crates/codegen/vtcode-safety | Command safety detection, execution policies, sandboxing |
crates/codegen/vtcode-a2a | Agent2Agent (A2A) protocol client and server |
crates/codegen/vtcode-mcp | Model Context Protocol client, connection pooling, tool discovery |
crates/codegen/xtask | Release packaging automation |
New reusable logic: put it in an existing small crate or a new one. Keep it out of vtcode-core by default unless tightly coupled to the core runtime.
Per-Module Guidance
Every crate has its own AGENTS.md with crate-specific conventions:
After significant changes (new modules, convention shifts, discovered gotchas, public API changes), use the audit-module-agents skill to check if the affected crate's AGENTS.md needs updating. Keep each local AGENTS.md under 30 lines.
Project Memory
Session-independent knowledge lives in .vtcode/memory/ (gitignored): gotchas.md, issues.md, library.md, decisions.md, and scratch.md. Read these files when context is needed. Write durable learnings there. See .vtcode/memory/README.md for format rules.
Build & Verification
- CI build caching:
Swatinem/rust-cachekeys off the target triple only whenCARGO_BUILD_TARGETis set or you passkey:. Builds that pass--targetvia the CLI (e.g.cross build --target) share ONE cache key across matrix jobs on the same runner OS, causing colliding/failing saves and every target restoring a mismatched cache. Always namespace the cache per target (with: { key: ${{ matrix.target }} }) in cross-target matrix jobs. - Prefer
./scripts/check-dev.sh(10-30s) over./scripts/check.sh(2-5m) for iteration. - Release builds keep
debug-assertions = trueandoverflow-checks = truein[profile.release].debug_assert!and overflow checks are NOT disabled in prod: a violated invariant must crash loud, not let the program run under wrong assumptions (see kristoff.it/blog/fix-your-asserts). Useassert!/debug_assert!for invariants that always hold; gate expensive diagnostics behind#[cfg(debug_assertions)]since that branch still compiles out of release when the flag is off elsewhere.
| Change | Command |
|---|---|
| Fast gate | ./scripts/check-dev.sh |
| + tests (quick) | ./scripts/check-dev.sh --test |
| + tests (changed crates) | ./scripts/check-dev.sh --changed |
| + workspace | ./scripts/check-dev.sh --workspace |
| + lints | ./scripts/check-dev.sh --lints |
| Harness PTY/TUI | ./scripts/check.sh harness |
| Release/PR | ./scripts/check.sh |
| Ast-grep rules | vtcode check ast-grep |
| Hawk dead-code/visibility | ./scripts/hawk.sh |
| Hawk (deny warnings) | ./scripts/hawk.sh --deny |
| Ast-grep scan | ast-grep scan (requires sgconfig.yml + rules/) |
Narrow commands: cargo check, cargo nextest run, cargo nextest run --profile quick, cargo fmt, cargo clippy. Never use cargo test — always use cargo nextest run.
Testing
- Runner:
cargo nextest run(parallel, fast). Always use nextest — nevercargo test. - Single test:
cargo nextest run test_name. - Single crate:
cargo nextest run -p vtcode-core. - Profiles:
default(full),quick(TDD, skips integration/e2e/slow),changed(delta since HEAD~1),ci(retries flaky, no fail-fast). - Harness regressions:
cargo nextest run -p vtcode-core -E 'binary(/pty_tests/)';cargo nextest run -p vtcode-bash-runner -E 'binary(/pipe_tests/)';cargo nextest run -p vtcode -E 'binary(/inline_events/)'. - Integration tests (Rust):
tests/at workspace root. Shell/script tests:scripts/tests/. Unit tests: in-module.
Skills & Special Workflows
- LLM providers: use the
adding-llm-providersskill. The/modelpicker usesModelId::all_models();builtin_model_presets()is used byModelsManager. Both may need updates. - New workspace crates: use the
adding-workspace-crateskill. This affects more thanCargo.toml; all workspace path dependencies needversionfields. - Structural code work: prefer
ast-grepover text grep for code shape, calls, impls, and codemods. Usergfor prose, logs, and config strings. Always invokeast-grep, not thesgalias. Useexec_commandor the ast-grep skill for arbitrary structural patterns. Advancedcode_searchaccepts one literal query and bounded filters. - Cap large command output:
COMMAND 2>&1 | head -c 4000— but never pipe verifier commands (cargo check --locked,cargo fmt --all -- --check,cargo nextest run); passmax_output_tokensinstead, since a pipe masks the verifier's exit status and never clears the verification gate.