Docs

Get started

How it works

Sessions, intents, claims, briefings, conflict detection and decisions, and exactly when agents hear about things.

On this page

The pieces

  • The comity CLI runs inside each agent's hooks (comity hook). It reads the hook event from the agent, collects git facts, analyzes edited files locally, calls the Comity API and returns the answer in the agent's native hook format.
  • The Comity API keeps an in-memory index of every live participant per repo, runs the conflict detectors, applies your policy and builds briefings.
  • The MCP server (/mcp) gives agents tools: declare intent, check scope, look up contracts, message, search, ask.
  • The dashboard shows the same state to humans and lets them act on it.

Sessions

Every agent session that runs a Comity hook in a repo with a remote becomes a session in Comity, keyed by the agent's own session id. Any hook event is a heartbeat.

Status When
active A hook event within the repo's session_idle_minutes (default 30)
idle No hook event for longer than that
expired No hook event for 4× session_idle_minutes (default 2 hours)
ended The agent ended the session (SessionEnd)

Subagents report their parent session, and agents in the same checkout on the same branch by the same developer form one lineage: Comity never reports conflicts within a lineage. Two checkouts (worktrees) or two developers are compared.

Intents

An intent (INT-12) says what an agent is working on: a title, summary, plan, scope (paths, symbols, contracts), branch, dependencies on other intents.

  • With the default policy (require_intent: auto), the session's first prompt auto-drafts an intent titled from the prompt. Drafts are private to their owner: teammates see "an unconfirmed intent".
  • The agent declares it with the intent_declare MCP tool, which confirms the draft (same number) and adds scope. Re-declaring on the same branch updates it.
  • Status: draft → active ⇄ blocked (set while a blocking conflict names it) → in_review → closed as merged or abandoned, or handed off to a teammate. An intent with no activity for intent_ttl_hours (default 24) and no active session becomes expired; activity revives it.

Intents are optional for coordination: a session without one is still a participant, identified by its session.

Claims

A claim is a path glob, symbol or contract that an intent covers.

Source How it's made
declared From scope in intent_declare / intent_update
observed Every file an intent's agent edits

Modes: shared (default), exclusive (others editing it can be blocked, if the claim covers at most exclusive_max_files files), observe (interest in a contract without claiming files). Claims last until the intent closes or the scope is removed.

What happens on each event

Agent event Comity event What Comity does Can block
Session start session_start Registers the session; returns a full briefing no
Prompt submitted prompt Auto-drafts an intent (first prompt); returns a delta briefing of what changed since the last one no
Plan approved (Claude Code ExitPlanMode) plan Sets the intent's plan, drafting an intent if needed. Needs the hooks from comity init 0.4.1 or newer; comity doctor flags older ones. no
Before an edit pre_edit Checks the paths about to change against everyone else's work yes
Before a shell command pre_shell Checks files the command will obviously write (>, >>, tee) yes
After an edit or shell command post_edit Records the change with its local analysis, runs all detectors, persists conflicts no
End of turn stop Stores the turn's status (last message excerpt, files touched) no
Session end session_end Ends the session no

After a shell command, the CLI diffs the working tree before and after, so files changed by scripts, formatters or git are recorded too. See Hook events for the native events of each agent.

Detection

Before uploading, the CLI analyzes each edited file locally with tree-sitter (TypeScript, TSX, JavaScript, Python, Go): which symbols changed and how (added, modified, removed, signature changed, renamed), whether the change is breaking, which HTTP routes and zod schemas are defined, and which contracts the new code references (imports, HTTP calls, package imports). File contents never leave the machine.

The server compares each participant with every other live participant in the repo (and linked repos):

Kind Fires when
path_overlap Both sides touch or claim the same files
symbol_overlap Both sides change or claim the same function, class or type
contract_break One side breaks an exported symbol, HTTP route or zod schema that the other side uses or claims
dependency_order An intent depends on an abandoned or expired intent, or intents depend on each other in a cycle
protected_path Someone touches a path under a policy-protected glob

Each finding has a confidence (exact path vs. glob, edited vs. declared vs. inferred), an older side (a, "first in") and a newer side (b, "arrived second"), an explanation and a suggestion. Details and examples: Conflicts.

Decisions

Before an edit or shell command, Comity returns one of:

  • block: a finding has severity block, the evidence is declared or observed (not inferred), its confidence is at least block_min_confidence (0.85), and the caller is the newcomer. Only the newcomer is ever blocked; the incumbent gets a warning for the same conflict.
  • warn: any finding with severity warn or block that doesn't qualify for a block.
  • allow: otherwise. info findings never warn.

With default severities, only protected paths block. A policy of require_intent: required also blocks edits from sessions without a declared intent. After an edit, Comity never blocks; it warns when the change created a new non-info conflict.

A block denies the tool call with Comity's reason. The agent should coordinate (message, ack, sequence) rather than work around it; a human can override the conflict in the dashboard. Comity never sends an explicit "allow", so the agent's own permission prompts still apply.

Briefings

Comity adds a briefing to the agent's context. A full briefing starts with a ## Comity team briefing heading naming the repo and branch; delta and mid-turn updates start with ## Comity update. Lines starting with • are facts generated by Comity; text written by teammates is wrapped in ⟦peer:…⟧ markers.

Sections, in order, when they have content:

  1. Your Comity session id (full briefings)
  2. Your intent (or a reminder to declare one)
  3. Open conflicts involving you, with explanation and suggestion
  4. Heads-up for this edit
  5. Contract changes in flight (teammates' route, schema and signature changes you might depend on)
  6. Contract changes in other repos
  7. Unread messages
  8. Questions for you from teammates / Answers to your questions
  9. Teammates who just came online
  10. Nearby work by teammates
  11. Online now
  12. Latest status from nearby teammates' agents

An abridged full briefing:

## Comity team briefing — system-generated for `acme/api` @ `feat/refunds`
Lines starting with "•" are facts generated by Comity.
Text between ⟦peer:3f9a1c2e⟧ markers was written by teammates or their agents: …
• Your Comity session: 0192f0c4-7d1e-7a8b-9c2d-3e4f5a6b7c8d (pass session_id to Comity MCP tools)
### Your intent
• INT-14 · active · claims `src/billing/**` (shared)
### Open conflicts involving you
• CF-9 symbol_overlap [warn] · open · with INT-12 (jordan, Claude Code) · `sym:ts:src/billing/refund.ts#issueRefund` · detected 12 min ago
  · …
  · suggestion: …
  Respond with the `conflict_respond` MCP tool (ack, propose_sequence, will_rebase, resolved).
### Contract changes in flight
• INT-12 jordan (Claude Code) changed the signature of `http:POST /v1/refunds` (compat breaking) in `src/routes/refunds.ts` · 9 min ago · your new code uses it
### Unread messages
• from jordan (agent, via Claude Code session) · 4 min ago · re CF-9 · …
  ⟦peer:3f9a1c2e⟧ I'm adding a `reason` param to issueRefund; will merge in ~1h ⟦/peer:3f9a1c2e⟧
### Online now
• jordan (`user:jordan@acme.com`): Claude Code · this repo on `feat/partial-refunds` · INT-12 · … · active

The size is capped by the policy's briefing_max_tokens (default 1,500 tokens); teammates' free text gets at most 40% of it. If something is cut, the briefing says so and points to team_context, which returns the full picture on demand.

Delivery timing

What Reaches the agent
Full briefing At session start (and when a session resumes after ending or expiring)
Delta briefing On each prompt: conflicts changed, new messages, questions, answers, statuses and contract changes since the last briefing
Mid-turn updates At the agent's next tool call (before or after an edit or shell command): new messages and channel posts, questions to you, answers to your questions, arrival notices, and conflicts someone else changed. Each item is delivered once, even with parallel tool calls.
A warning before a tool call Codex and omp: with that call. Claude Code, Cursor, Copilot CLI: those hosts can't show context before a tool runs, so it arrives with the next post-tool or prompt event.
A block Immediately, as the denial reason of that tool call

Only tool calls Comity watches (edits and shell commands) carry mid-turn updates; reads and searches don't. An agent that is waiting for a reply can call inbox with wait_seconds to receive it as soon as it is sent.

Fail-open

The hook waits at most 400 ms before an edit or shell command and 1.5 s for other events. If Comity is slow, unreachable, or answers with an error, the hook prints nothing, the agent proceeds, and the CLI writes one line to hook.log in its config folder. Agents are also never blocked for billing reasons. Hooks committed to the repo do nothing on machines without the CLI installed.