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_case fns, PascalCase types, anyhow::Result<T> + .with_context().
  • CI sets RUSTFLAGS: "-D warnings" and uses --locked. Match locally with cargo check --locked when 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::ThreadEvent is 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 as CompactStr in vtcode_core::types) over String for small string fields. Use Cow<'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.toml allows unwrap/panic/indexing in tests only.
  • Dev profile has incremental = false (sccache). Set CARGO_INCREMENTAL=1 to 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.md for 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/sessions to 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

Workspace

Cargo workspace, ~30 crates. Rust stable, MSRV 1.88, edition 2024. default-members = root, vtcode-core, vtcode-ui only.

CrateRole
vtcode (root src/)Binary, CLI, session bootstrap
crates/codegen/vtcode-coreAgent loop, tools, prompts, LLM orchestration, UI
crates/codegen/vtcode-uiUnified UI: design system, theme registry, TUI framework
crates/codegen/vtcode-configConfig loading and schema
crates/codegen/vtcode-bash-runnerShell execution sandbox
crates/codegen/vtcode-acpAgent Client Protocol (Zed)
crates/codegen/vtcode-authOAuth and credential storage
crates/codegen/vtcode-indexerCode indexing and search
crates/common/vtcode-exec-eventsThreadEvent contract and ATIF export
crates/codegen/vtcode-webmcpAuthenticated browser editor bridge, pairing, event replay, and bounded workspace adapter
crates/common/vtcode-commonsShared utilities
crates/common/vtcode-macrosProcedural macros
crates/common/vtcode-utility-tool-specsJSON schemas for utility, file, and collaboration/HITL tools
crates/common/vtcode-agent-pluginsAgent Plugins 1.0.0 manifest parsing, validation, and discovery
crates/codegen/vtcode-llmLLM provider abstraction, client implementations, streaming (partial extraction)
crates/codegen/vtcode-skillsSkill types, discovery, loading, and validation (partial extraction)
crates/codegen/vtcode-memoryUnified per-session state store: append-only ThreadEvent log, derived views, retention, cross-session query (single source of truth)
crates/codegen/vtcode-evalAgent evaluation framework: pass@k/pass^k metrics, capability/regression evals, environment-based outcome verification
crates/codegen/vtcode-safetyCommand safety detection, execution policies, sandboxing
crates/codegen/vtcode-a2aAgent2Agent (A2A) protocol client and server
crates/codegen/vtcode-mcpModel Context Protocol client, connection pooling, tool discovery
crates/codegen/xtaskRelease 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:

CrateAGENTS.md
vtcode (binary)src/AGENTS.md
vtcode-corecrates/codegen/vtcode-core/AGENTS.md
vtcode-uicrates/codegen/vtcode-ui/AGENTS.md
vtcode-configcrates/codegen/vtcode-config/AGENTS.md
vtcode-bash-runnercrates/codegen/vtcode-bash-runner/AGENTS.md
vtcode-acpcrates/codegen/vtcode-acp/AGENTS.md
vtcode-authcrates/codegen/vtcode-auth/AGENTS.md
vtcode-indexercrates/codegen/vtcode-indexer/AGENTS.md
vtcode-exec-eventscrates/common/vtcode-exec-events/AGENTS.md
vtcode-webmcpcrates/codegen/vtcode-webmcp/AGENTS.md
vtcode-commonscrates/common/vtcode-commons/AGENTS.md
vtcode-macroscrates/common/vtcode-macros/AGENTS.md
vtcode-utility-tool-specscrates/common/vtcode-utility-tool-specs/AGENTS.md
vtcode-agent-pluginscrates/common/vtcode-agent-plugins/AGENTS.md
vtcode-llmcrates/codegen/vtcode-llm/AGENTS.md
vtcode-skillscrates/codegen/vtcode-skills/AGENTS.md
vtcode-memorycrates/codegen/vtcode-memory/AGENTS.md
vtcode-evalcrates/codegen/vtcode-eval/AGENTS.md
vtcode-safetycrates/codegen/vtcode-safety/AGENTS.md
vtcode-a2acrates/codegen/vtcode-a2a/AGENTS.md
vtcode-mcpcrates/codegen/vtcode-mcp/AGENTS.md
xtaskcrates/codegen/xtask/AGENTS.md

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-cache keys off the target triple only when CARGO_BUILD_TARGET is set or you pass key:. Builds that pass --target via 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 = true and overflow-checks = true in [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). Use assert!/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.
ChangeCommand
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 rulesvtcode check ast-grep
Hawk dead-code/visibility./scripts/hawk.sh
Hawk (deny warnings)./scripts/hawk.sh --deny
Ast-grep scanast-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 — never cargo 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-providers skill. The /model picker uses ModelId::all_models(); builtin_model_presets() is used by ModelsManager. Both may need updates.
  • New workspace crates: use the adding-workspace-crate skill. This affects more than Cargo.toml; all workspace path dependencies need version fields.
  • Structural code work: prefer ast-grep over text grep for code shape, calls, impls, and codemods. Use rg for prose, logs, and config strings. Always invoke ast-grep, not the sg alias. Use exec_command or the ast-grep skill for arbitrary structural patterns. Advanced code_search accepts 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); pass max_output_tokens instead, since a pipe masks the verifier's exit status and never clears the verification gate.