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
comityCLI 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_declareMCP 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 asmergedorabandoned, or handed off to a teammate. An intent with no activity forintent_ttl_hours(default 24) and no active session becomesexpired; 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 leastblock_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
warnorblockthat doesn't qualify for a block. - allow: otherwise.
infofindings 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:
- Your Comity session id (full briefings)
- Your intent (or a reminder to declare one)
- Open conflicts involving you, with explanation and suggestion
- Heads-up for this edit
- Contract changes in flight (teammates' route, schema and signature changes you might depend on)
- Contract changes in other repos
- Unread messages
- Questions for you from teammates / Answers to your questions
- Teammates who just came online
- Nearby work by teammates
- Online now
- Latest status from nearby teammates' agents
An abridged full briefing:
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.