Skip to main content

comindly_api/
agents.rs

1//! When and how agents should use comindly's tools: one text for MCP, hooks, files and the app.
2
3/// The guidance itself, as markdown whose headings start at `###`.
4pub const GUIDE: &str = r#"comindly indexes all of the team's repositories into one graph and serves it over MCP. It knows
5what this file cannot tell you: who calls code in other repositories, which services talk through
6which HTTP routes, queues, topics, buckets and tables, how each repository writes its code, and what
7the team recorded about the code (decisions, constraints, failed attempts, traps). Its answers come
8from parsing the code, so they are exact for the indexed version.
9
10### When to use it
11
12- Before changing a function, class, route, message or table that anything else might use.
13- When a question reaches beyond the files you have open: "who calls this", "where is this
14  handled", "what consumes this queue", "how does a request get from A to B".
15- Before editing code that looks odd or fragile: someone may have recorded why it is that way, or
16  what already failed.
17- When you need to write code the way this codebase does: naming, structure, logging, tests.
18- When you are new to an area and need to find your way.
19
20Do not use it for questions the open files answer, or for code that is not committed yet: the
21index reflects each repository's default branch as of the last indexing.
22
23### How to work with it
24
25**Before changing code**
261. `find` the symbol by name (or `search` by describing it) to get its `id`.
272. `preflight` with the files and symbols you plan to change: recorded constraints and dead ends,
28   the contracts the code serves, what depends on it, and companion files that usually change with it.
293. `ripple` on each symbol whose behaviour or signature changes: everything that depends on it, in
30   every repository, across service contracts. Mention callers in other repositories to the user.
314. `context_pack` for the smallest set of code to read before editing, within a token budget.
325. `guide` for the repository's conventions, and follow them.
33
34**Understanding behaviour**
35- `zoom` on an `id`: its definition, callers, callees, members and contracts in one answer.
36- `thread` follows the calls from a symbol; `flow` gives a written walkthrough of a whole flow,
37  including hops over HTTP and queues into other services.
38- `contracts` lists routes, queues, topics, buckets and tables with who provides and who uses each;
39  `kind` narrows to `http`, `sqs`, `sns`, `s3` or `table`, `query` filters by name, `dangling` shows
40  ones missing a side.
41
42**Finding your way**
43- `repos` lists the indexed repositories, their size and teams; `suggest` offers questions worth
44  asking about an area (`about`).
45- `search`, `find`, `repos`, `contracts` and `suggest` take `team` (comma-separated names) to stay
46  within one team's repositories.
47
48### The team's records
49
50- `why` on a symbol returns what the team recorded about it, with status and trust. Follow records
51  a person wrote or confirmed (T3) unless the user says otherwise; weigh the others by evidence and
52  by how many people's agents confirmed them.
53- Trust: T3 means a person wrote or confirmed it, T2 an agent with evidence, T1 an agent without.
54  Records marked "from <team>, unconfirmed" come from another team and wait for the owners to confirm.
55- Stale or moved records point at code that changed since they were written: check them against the
56  code before relying on them.
57- When you learn something a later change must know (a decision and its reason, a constraint, an
58  approach that failed and why, a trap), offer to record it with `remember`: one factual title, the
59  symbols it is about (`on`), and evidence such as `commit:<sha>` or `mr:!123` (required for a failed
60  attempt). `review` confirms, archives, invalidates, supersedes or disputes a record by its id.
61  Ask the user before recording, archiving, invalidating or superseding. When you relied on a record
62  and checked it still matches the code, confirm it. Every change needs a reason other agents can read.
63
64### Habits
65
66- Pass the `id` from `find` or `search` to the other tools; names alone can be ambiguous.
67- Name the repository and symbol when an answer relies on comindly, so the user can check it.
68- If a tool finds nothing, say so instead of guessing; the code may not be indexed yet.
69"#;
70
71/// A section for a repository's `AGENTS.md` or `CLAUDE.md`.
72pub fn agents_md() -> String {
73    format!("## comindly\n\n{GUIDE}")
74}
75
76/// A Claude Code skill, for `.claude/skills/comindly/SKILL.md`.
77pub fn skill() -> String {
78    format!(
79        "---\nname: comindly\ndescription: \"How and when to use comindly's MCP tools: before changing shared code, \
80for questions that reach beyond the current file, for service contracts, call chains, conventions and the \
81team's recorded decisions.\"\n---\n\n# comindly\n\n{GUIDE}"
82    )
83}
84
85/// Agents on this machine whose MCP settings already list comindly.
86pub fn agents() -> Vec<&'static str> {
87    let Some(home) = std::env::var_os("HOME").map(std::path::PathBuf::from) else {
88        return Vec::new();
89    };
90    let json = |p: &str| -> serde_json::Value {
91        std::fs::read_to_string(home.join(p))
92            .ok()
93            .and_then(|t| serde_json::from_str(&t).ok())
94            .unwrap_or_default()
95    };
96    let has = |v: &serde_json::Value| {
97        v.get("mcpServers")
98            .and_then(|m| m.get("comindly"))
99            .is_some()
100    };
101    let claude = json(".claude.json");
102    let mut out = Vec::new();
103    if has(&claude)
104        || claude["projects"]
105            .as_object()
106            .is_some_and(|p| p.values().any(has))
107    {
108        out.push("claude");
109    }
110    if has(&json(".cursor/mcp.json")) {
111        out.push("cursor");
112    }
113    if std::fs::read_to_string(home.join(".codex/config.toml"))
114        .is_ok_and(|t| t.contains("[mcp_servers.comindly]"))
115    {
116        out.push("codex");
117    }
118    out
119}