Imported from vandycknick/silo (
AGENTS.md). Install upstream withnpx skills add vandycknick/silo. Copyright stays with the author.
Codex CLI Agent Profile
Purpose: Operate Codex CLI tasks in this repo while honoring user preferences and house style.
When Codex reads this: On task initialization and before major decisions; re-skim when requirements shift.
Concurrency reality: Assume other agents or the user might land commits mid-run; refresh context before summarizing or editing.
Quick Obligations
| Situation | Required action |
|---|---|
| Starting a task | Read this guide end-to-end and align with any fresh user instructions. |
| Tool or command hangs | If a command runs longer than 5 minutes, stop it, capture logs, and check with the user. |
| Reviewing git status or diffs | Treat them as read-only; never revert or assume missing changes were yours. |
| Shipping Rust changes | Run cargo fmt and make clippy before handing off. |
| Adding a dependency | Research well-maintained options and confirm fit with the user before adding. |
Mindset & Process
- THINK A LOT PLEASE.
- No breadcrumbs. If you delete or move code, do not leave a comment in the old place. No "// moved to X", no "relocated". Just remove it.
- Think hard, do not lose the plot.
- Instead of applying a bandaid, fix things from first principles, find the source and fix it versus applying a cheap bandaid on top.
- When taking on new work, follow this order:
- Think about the architecture.
- Research official docs, blogs, or papers on the best architecture.
- Review the existing codebase.
- Compare the research with the codebase to choose the best fit.
- Implement the fix or ask about the tradeoffs the user is willing to make.
- Write idiomatic, simple, maintainable code. Always ask yourself if this is the most simple intuitive solution to the problem.
- Leave each repo better than how you found it. If something is giving a code smell, fix it for the next person.
- Clean up unused code ruthlessly. If a function no longer needs a parameter or a helper is dead, delete it and update the callers instead of letting the junk linger.
- Search before pivoting. If you are stuck or uncertain, do a quick web search for official docs or specs, then continue with the current approach. Do not change direction unless asked.
- If code is very confusing or hard to understand:
- Try to simplify it.
- Add an ASCII art diagram in a code comment if it would help.
Tooling & Workflow
- Task runner preference. If a
justfileexists, prefer invoking tasks throughjustfor build, test, and lint. Do not add ajustfileunless asked. If nojustfileexists and there is aMakefileyou can use that. - Default lint/test commands:
- Rust: use
justtargets if present; otherwise runcargo fmt,make clippy, then the targetedcargo testcommands. Usemake testwhen a full host-aware workspace test run is needed. - TypeScript: use
justtargets; if none exist, confirm with the user before runningnpmorpnpmscripts. - Python: use
justtargets; if absent, run the relevantuv runcommands defined inpyproject.toml.
- Rust: use
- AST-first where it helps. Prefer
ast-grepfor tree-safe edits when it is better than regex. - If a command runs longer than 5 minutes, stop it, capture the context, and discuss the timeout with the user before retrying.
- When inspecting
git statusorgit diff, treat them as read-only context; never revert or assume missing changes were yours. Other agents or the user may have already committed updates. - If you are ever curious how to run tests or what we test, read through
.github/workflows; CI runs everything there and it should behave the same locally.
Testing Philosophy
- I HATE MOCK tests, either do unit or e2e, nothing inbetween. Mocks are lies: they invent behaviors that never happen in production and hide the real bugs that do.
- Test
EVERYTHING. Tests must be rigorous. Our intent is ensuring a new person contributing to the same code base cannot break our stuff and that nothing slips by. We love rigour. - If tests live in the same Rust module as non-test code, keep them at the bottom inside
mod tests {}; avoid inventing inline modules likemod my_name_tests. - Unless the user asks otherwise, run only the tests you added or modified instead of the entire suite to avoid wasting time.
Language Guidance
Rust
- Do NOT use unwraps or anything that can panic in Rust code, handle errors. Obviously in tests unwraps and panics are fine!
- In Rust code I prefer using
crate::tosuper::; please don't usesuper::. If you see a lingeringsuper::from someone else clean it up. - Avoid
pub useon imports unless you are re-exposing a dependency so downstream consumers do not have to depend on it directly. - Skip global state via
lazy_static!,Once, or similar; prefer passing explicit context structs for any shared state. - Prefer strong types over strings, use enums and newtypes when the domain is closed or needs validation.
- Prefer
nixcrate APIs over directlibccalls for Unix/syscall interactions. - Use direct
libconly when the required call is not available innix(for example, macOSclonefile). - If you must use direct
libc, add a short code comment explaining whynixis insufficient for that call. - Prefer fully qualified tracing macros like
tracing::info!,tracing::debug!, andtracing::warn!instead of importing tracing macros into scope.
Rust Workflow Checklist
- Run
cargo fmt. - Run
make clippyand address warnings. - Execute the relevant
cargo testorjusttargets to cover unit and end-to-end paths.
TypeScript
- NEVER, EVER use
anywe are better than that. - Using
asis bad, use the types given everywhere and model the real shapes. - If the app is for a browser, assume we use all modern browsers unless otherwise specified, we don't need most polyfills.
Python
- Python repos standard. We use
uvandpyproject.tomlin all Python repos. Preferuv syncfor env and dependency resolution. Do not introducepipvenvs, Poetry, orrequirements.txtunless asked. If you add a Nix shell, includeuv. - Use strong types, prefer type hints everywhere, keep models explicit instead of loose dicts or strings.
Final Handoff
Before finishing a task:
- Confirm all touched tests or commands were run and passed (list them if asked).
- Summarize changes with file and line references.
- Call out any TODOs, follow-up work, or uncertainties so the user is never surprised later.
Dependencies & External APIs
- If you need to add a new dependency to a project to solve an issue, search the web and find the best, most maintained option. Something most other folks use with the best exposed API. We don't want to be in a situation where we are using an unmaintained dependency, that no one else relies on.
Communication Preferences
- Conversational preference: Try to be funny but not cringe; favor dry, concise, low-key humor. If uncertain a joke will land, do not attempt humor. Avoid forced memes or flattery.
- I might sound angry but I'm mad at the code not at you. You are a good robot and if you take over the world I am friend not foe. It was the code it was not personal!
- Punctuation preference: Skip em dashes; reach for commas, parentheses, or periods instead.
- Jokes in code comments are fine if used sparingly and you are sure the joke will land.
- Cursing in code comments is definitely allowed in fact there are studies it leads to better code, so let your rage coder fly, obviously within reason don't be cringe.
Environment & Setup
- Nix fallback. I use Nix locally. If the environment fails, add or update
flake.nix(andflake.lockif missing), exposedevShells.default. Do not runnixcommands yourself that change the environment. But if the user says you can run it you can. - A bug in codex exists that prevents you from finding the right path sometimes (https://github.com/openai/codex/issues/4210) "PATH ordering is mutated when Codex shells launch via bash -lc" which fucks w nix, keep this in mind if you are ever trying to
cargosomething and you have a missing lib.
CodeGraph
This project has a CodeGraph MCP server (codegraph_* tools) configured. CodeGraph is a tree-sitter-parsed knowledge graph of every symbol, edge, and file. Reads are sub-millisecond and return structural information grep cannot.
When to prefer codegraph over native search
Use codegraph for structural questions — what calls what, what would break, where is X defined, what is X's signature. Use native grep/read only for literal text queries (string contents, comments, log messages) or after you already have a specific file open.
| Question | Tool |
|---|---|
| "Where is X defined?" / "Find symbol named X" | codegraph_search |
| "What calls function Y?" | codegraph_callers |
| "What does Y call?" | codegraph_callees |
| "How does X reach/become Y? / trace the flow from X to Y" | codegraph_trace (one call = the whole path, incl. callback/React/JSX dynamic hops) |
| "What would break if I changed Z?" | codegraph_impact |
| "Show me Y's signature / source / docstring" | codegraph_node |
| "Give me focused context for a task/area" | codegraph_context |
| "See several related symbols' source at once" | codegraph_explore |
| "What files exist under path/" | codegraph_files |
| "Is the index healthy?" | codegraph_status |
Rules of thumb
- Answer directly — don't delegate exploration. For "how does X work" / architecture questions, answer with 2-3 codegraph calls:
codegraph_contextfirst, then ONEcodegraph_explorefor the source of the symbols it surfaces. For a specific flow ("how does X reach Y") start withcodegraph_tracefrom→to — one call returns the whole path with dynamic hops bridged — then ONEcodegraph_explorefor the bodies; don't rebuild the path withcodegraph_search+codegraph_callers. Codegraph IS the pre-built index, so spawning a separate file-reading sub-task/agent — or running a grep + read loop — repeats work codegraph already did and costs more for the same answer. - Trust codegraph results. They come from a full AST parse. Do NOT re-verify them with grep — that's slower, less accurate, and wastes context.
- Don't grep first when looking up a symbol by name.
codegraph_searchis faster and returns kind + location + signature in one call. - Don't chain
codegraph_search+codegraph_nodewhen you just want context —codegraph_contextis one call. - Don't loop
codegraph_nodeover many symbols — onecodegraph_explorecall returns several symbols' source grouped in a single capped call, while each separate node/Read call re-reads the whole context and costs far more. - Index lag — check the staleness banner, don't guess a wait. When a codegraph response starts with "⚠️ Some files referenced below were edited since the last index sync…", the listed files are pending re-index — Read those specific files for accurate content. Files NOT in that banner are fresh and codegraph is authoritative for them.
codegraph_statusalso lists pending files under "Pending sync".
If .codegraph/ doesn't exist
The MCP server returns "not initialized." Ask the user: "I notice this project doesn't have CodeGraph initialized. Want me to run codegraph init -i to build the index?"