This file is for coding agents working in this repository. It summarizes the commands, workflows, and code conventions that are visible in the current codebase.
This repository uses the Shared Context Engineering (SCE) approach for AI-assisted software delivery with explicit, versioned context: https://sce.crocoder.dev/
- Root repo contains three main working areas:
cli/- Rust CLI (sce)config/- generated agent config, skills, and Pkl sourcescontext/- shared context docs, plans, decisions, and handovers
- No root
AGENTS.mdexisted before this file. - No
.cursor/rules/directory was found. - No
.cursorrulesfile was found. - No
.github/copilot-instructions.mdfile was found. - If any of those files are added later, update this document to fold their instructions in.
- Nix is the primary reproducible entrypoint at repo root.
- Root
flake.nixprovides Bun, TypeScript, Pkl, jq, and the Rust toolchain. - Root
flake.nixdefines Crane-based Rust packaging and check derivations for the CLI. - Run Cargo via Nix, not directly from the host shell. Prefer
nix develop -c sh -c 'cd cli && <cargo command>'. - For validation, prefer
nix flake checkand avoid runningcargo testdirectly unless a user explicitly requests it. - Optional local Nix tuning can live in user-level
~/.config/nix/nix.conf; recommended values aremax-jobs = autoandcores = 0. auto-optimise-store = trueis intentionally treated as a system-level/etc/nix/nix.confsetting, not a repo-managed user setting.- Bun is used for repo-owned config/plugin workflows; prefer Bun rather than npm or pnpm scripts when working in those areas.
- Rust edition is
2021. - TypeScript is still used in repo-owned config/plugin sources and should remain strict-mode friendly.
- Enter dev shell:
nix develop - Run all flake checks visible at root:
nix flake check - Run generated-output parity check:
nix run .#pkl-check-generated - Regenerate and sync
.opencodeconfig:nix run .#sync-opencode-config
Run these through Nix from repo root unless noted otherwise.
- Build CLI:
nix develop -c sh -c 'cd cli && cargo build' - Run CLI:
nix develop -c sh -c 'cd cli && cargo run -- --help' - Build packaged CLI output:
nix build .#default - Run packaged CLI app:
nix run .#sce -- --help - Preferred repo-level verification:
nix flake check - Run a single Rust test by exact name when explicitly needed:
nix develop -c sh -c 'cd cli && cargo test parser_routes_mcp -- --exact' - Run Rust tests in one module/file pattern when explicitly needed:
nix develop -c sh -c 'cd cli && cargo test setup' - Run ignored? none were found; do not assume ignored-test flows exist.
- Rust format verification is covered by
nix flake check - Auto-format:
nix develop -c sh -c 'cd cli && cargo fmt' - Rust lint verification is covered by
nix flake check
Run these from config/lib/bash-policy-plugin/ when working on the Bun-owned bash-policy runtime.
- Run plugin/runtime test suite:
bun test - Run a single Bun test by name:
bun test -t "<test name>"
- Preferred repo validation from repo root:
nix flake check - Config/plugin validation from repo root:
nix develop -c sh -c 'cd config/lib/bash-policy-plugin && bun test' - Generated-config validation from repo root:
nix run .#pkl-check-generated
- Rust tests live inline in source files and in module test files such as
cli/src/services/setup/tests.rs. - Rust/Cargo commands should be executed through
nix develop, even for one-off builds, tests, fmt, and clippy runs. - Prefer
nix flake checkfor routine verification and avoidcargo testunless the user explicitly asks for it. - Rust single-test selection uses standard Cargo substring matching; add
-- --exactfor deterministic one-test runs. - Bun tests use
bun:testand support-tname filtering. - Bun/plugin tests under
config/lib/bash-policy-plugin/are lighter-weight repo validation and remain part of the flake check surface.
- GitHub Actions publish Tessl tiles from
config/.opencode/skills/**andconfig/.claude/skills/**. - Release workflow packages agent files from
config/.opencode/agent/Shared Context.mdandconfig/.claude/agents/shared-context.md. - Root
flake.nixpackagesscethrough Crane'sbuildDepsOnly+buildPackagepipeline and runscli-tests,cli-clippy, andcli-fmtthrough Crane-backed checks. - Changes under generated config trees may need a Pkl regeneration or parity check.
- Follow existing local patterns before introducing new abstractions.
- Keep changes scoped and incremental.
- Prefer deterministic behavior and stable output text; this matters in CLI tests.
- Use explicit constants for repeated strings, timeouts, intervals, exit codes, and numeric formatting.
- Prefer small helper functions when they improve readability of branching or setup code.
- Avoid introducing framework-heavy patterns; this repo is mostly plain Rust, Bun, shell, and config assets.
- Group imports in this order: standard library, third-party crates, then
crate::...imports. - Use grouped
stdimports such asuse std::path::{Path, PathBuf};. - Prefer explicit imported items over wildcard imports.
- Keep import lists stable and reasonably compact.
- Use ESM
importsyntax only. - Keep imports grouped: Node builtins, external packages, then local files.
- Use
typeimports inline where appropriate, for exampleimport { foo, type Bar } from "pkg";. - Use explicit relative file paths like
./test-setup.
- Rust formatting is delegated to
rustfmt; do not hand-format against it. - Rust uses 4-space indentation.
- TypeScript uses 2-space indentation, semicolons, trailing commas where multiline, and double-quoted strings in the repo's remaining TS-owned areas.
- Shell scripts use
#!/usr/bin/env bashandset -euo pipefail. - Quote shell expansions unless you intentionally need word splitting.
- Prefer readable multi-line expressions over dense one-liners.
- In Rust, prefer strong enums and structs for command requests, runtime state, and result payloads.
- Derive common traits explicitly; common order in this repo is
Clone, Copy, Debug, Eq, PartialEqwhen applicable. - In TypeScript, prefer named
typealiases for payloads and test result structures. - Keep strict-mode friendliness: handle
undefined, use narrow unions, and avoid implicit any. - Prefer explicit return types on exported TypeScript helpers.
- Keep data structures serialization-friendly when they are written to JSON or surfaced by CLI output.
- Rust types and enums:
UpperCamelCase. - Rust functions, modules, and variables:
snake_case. - Rust constants:
SCREAMING_SNAKE_CASE. - TypeScript types:
PascalCase. - TypeScript variables and functions:
camelCase. - Test names are descriptive, behavior-oriented, and usually sentence-like with underscores in Rust.
- Prefer names that encode intent, not implementation trivia.
- Rust uses
anyhow::Resultbroadly for service-layer operations. - Add context to I/O and process failures with
Context/with_context. - Use
bail!andanyhow!for concise early exits when appropriate. - Preserve user-facing diagnostics as stable strings when tests assert on them.
- Separate machine classification from rendered messages when the CLI contract cares about exit codes.
- In TypeScript, throw
Errorwith direct, actionable messages. - Convert unknown thrown values with helper functions like
getErrorMessagebefore logging or persisting.
- Keep stdout reserved for intended command payloads.
- Keep errors on stderr and preserve stable prefixes/codes when existing code does so.
- Do not casually rewrite help text, error phrasing, or JSON field names; tests may depend on exact wording.
- Prefer deterministic ordering in rendered collections, embedded asset lists, and discovered file paths.
- Add unit tests close to the code they exercise.
- Match the repo's current pattern of focused behavioral test names.
- Assert on exact output when the CLI contract is supposed to be stable.
- For filesystem or manifest checks, sort collected paths before asserting.
- Keep tests isolated; clean up temporary state and abort long-running resources in teardown.
- Shell scripts should fail fast, validate prerequisites early, and print concrete remediation steps.
- Prefer staging-and-swap workflows for generated config updates instead of in-place mutation.
- Treat
config/.opencode,config/.claude, and repository-root.opencode/as sensitive generated trees. - If you edit generated outputs manually, verify whether the corresponding Pkl source should be updated instead.
- Check for unrelated worktree changes before broad edits.
- Avoid destructive git commands unless the user explicitly asks for them.
- When touching both
config/and.opencode/, verify whether sync/regeneration is expected. - When verifying changes, prefer
nix flake checkinstead of runningcargo testdirectly. - When changing Bun-owned config/plugin code, run the narrowest Bun test or script that covers the change.
- Default verification for code changes:
nix flake check - Bun/TypeScript config-plugin change:
cd config/lib/bash-policy-plugin && bun test -t "<test name>" - Generated config or Pkl change:
nix run .#pkl-check-generated - Cross-cutting repo change:
nix flake check
README.mdflake.nixcontext/context-map.mdcontext/overview.mdcli/Cargo.tomlcli/src/app.rscli/src/services/setup/tests.rsconfig/lib/bash-policy-plugin/package.jsonconfig/lib/bash-policy-plugin/bash-policy-runtime.test.tsconfig/lib/bash-policy-plugin/opencode-bash-policy-plugin.tsscripts/sync-opencode-config.sh