# Connect Archcore to your agent

> Configure MCP, lifecycle hooks, and instruction hints for a supported coding agent or your own harness.

Archcore connects to your agent through MCP tools, lifecycle hooks, and an instruction hint. Use [Install Archcore](/start/install/) for initial setup; this page covers host differences and custom connections.

## Supported hosts

[Section titled “Supported hosts”](#supported-hosts)

| Host               | Agent ID      | MCP configuration             | Lifecycle hooks                                           | Archcore commands               |
| ------------------ | ------------- | ----------------------------- | --------------------------------------------------------- | ------------------------------- |
| Claude Code        | `claude-code` | Automatic                     | Supported                                                 | Plugin                          |
| Cursor             | `cursor`      | Project setup or manual entry | Supported, with host limits                               | Plugin installed in UI          |
| Codex CLI          | `codex-cli`   | Automatic                     | Feature flag; trusted project; no Windows hooks           | Plugin                          |
| GitHub Copilot CLI | `copilot`     | Project setup required        | Write guard; no pre-edit context injection                | Plugin                          |
| Gemini CLI         | `gemini-cli`  | Automatic                     | Wiring provided; runtime verification remains unconfirmed | No plugin                       |
| OpenCode           | `opencode`    | Automatic                     | Supported through the plugin                              | Plugin, with `/archcore-` names |
| Roo Code           | `roo-code`    | Automatic                     | No lifecycle hooks                                        | No plugin                       |
| Cline              | `cline`       | Manual through its MCP UI     | No lifecycle hooks                                        | No plugin                       |

MCP availability means the agent can use document tools. It does not imply slash-command or hook support. Copilot support here refers to GitHub Copilot CLI, not VS Code agent mode or cloud-agent sandboxes.

## MCP

[Section titled “MCP”](#mcp)

The Archcore CLI runs the local MCP server as `archcore mcp`. Your agent launches it as a subprocess and communicates over stdin/stdout. For a custom harness, configure the executable and project root explicitly:

```json
{
  "mcpServers": {
    "archcore": {
      "command": "archcore",
      "args": ["mcp", "--project", "/absolute/path/to/your-project"]
    }
  }
}
```

Replace the path with the repository you want to serve. Your host can use a different configuration shape; the executable, arguments, and stdio transport remain the connection inputs.

The project root resolves in this order: `--project`, `ARCHCORE_PROJECT_ROOT`, then the working directory. An explicit flag or environment value pins the root for the server’s lifetime. Without either, the server can follow valid client-reported roots. See [root diagnostics](/guides/troubleshooting/#wrong-working-directory).

An empty repository can connect: the agent can call `init_project` to create `.archcore/`. That tool does not configure the host. The separately gated `install_host_config` tool requires a user-approved host-wiring plan. See the [MCP tools reference](/reference/mcp-tools/).

### Install the connection separately

[Section titled “Install the connection separately”](#install-the-connection-separately)

```bash
archcore mcp install --agent claude-code
```

Replace the ID for your host. Cline requires its own UI rather than a project config written by this command.

| Host                            | Project MCP config                                 |
| ------------------------------- | -------------------------------------------------- |
| Claude Code, GitHub Copilot CLI | `.mcp.json`                                        |
| Cursor                          | `.cursor/mcp.json`                                 |
| Codex CLI                       | `.codex/config.toml`                               |
| Gemini CLI                      | `.gemini/settings.json`                            |
| OpenCode                        | `opencode.json`                                    |
| Roo Code                        | `.roo/mcp.json`                                    |
| Cline                           | VS Code globalStorage, managed through the host UI |

After configuration, restart the session and request `list_documents`. An empty list is valid; a missing tool or connection error is not.

## Lifecycle hooks

[Section titled “Lifecycle hooks”](#lifecycle-hooks)

Hooks connect Archcore to host events. [What to expect](/start/what-to-expect/) explains their user-visible effects.

| Event          | Effect                                                       | Can block an action? |
| -------------- | ------------------------------------------------------------ | -------------------- |
| `SessionStart` | Bounded project recap                                        | No                   |
| `PreToolUse`   | Direct-write guard and supported pre-edit context injection  | The write guard can  |
| `PostToolUse`  | Document structure, relation-cascade, and precision findings | No                   |

```bash
archcore hooks install --agent claude-code
```

Use the host’s supported event names and payload format when writing a custom adapter. The command leaves `archcore hooks <agent-id> <event>` translate those protocols; simply adding a generic hook name does not make a new harness compatible.

Run `archcore doctor` to inspect the setup. A written configuration does not prove that the host delivered an event. Check an actual session before relying on automatic behavior.

### Codex CLI

[Section titled “Codex CLI”](#codex-cli)

Enable hooks with `codex --enable hooks`, or add this to your existing `~/.codex/config.toml`:

```toml
[features]
hooks = true
```

Before Codex 0.129.0, the key is `codex_hooks`. Project-local hooks require a trusted `.codex/` layer. The documented integration does not run hooks on Windows. MCP tools and skills can still work without hooks.

### GitHub Copilot CLI

[Section titled “GitHub Copilot CLI”](#github-copilot-cli)

Run `archcore init --agent copilot` in the project. Its plugin does not register an MCP server, so project setup supplies the connection.

The pre-write event accepts a permission decision but cannot receive context. The direct-write guard works; pre-edit context injection does not. Copilot also reads Claude Code settings, so a repository configured for both can produce duplicate hooks. See [duplicate-context troubleshooting](/guides/troubleshooting/#context-appears-twice).

### Cursor

[Section titled “Cursor”](#cursor)

Cursor manages plugins through its UI. Add `https://github.com/archcore-ai/archcore` in the Plugins panel, then confirm MCP is registered for your project. Project setup with `archcore init --agent cursor` can write the MCP entry; a plugin-only installation does not supply it.

For a user-scoped entry, use the [Cursor MCP template](https://github.com/archcore-ai/archcore/blob/main/docs/cursor.mcp.example.json) and retain `--project` with `${workspaceFolder}`. This prevents different windows from sharing the wrong project root.

### OpenCode

[Section titled “OpenCode”](#opencode)

OpenCode loads Archcore as the npm package `@archcore/opencode-plugin`. The plugin is global: you install it once, and it works in every project that has `.archcore/`. It needs OpenCode 1.18.34 or later (1.x or 2.x) and the Archcore CLI 0.10.0 or later on `PATH`.

The [platform installer](/start/install/) adds the plugin when the `opencode` command is already on `PATH`. To add it later, run this from any directory:

```bash
archcore plugin install --agent opencode
```

`archcore init --agent opencode` in a project also installs it. You can also use the OpenCode command for your version:

```bash
opencode plugin add @archcore/opencode-plugin   # OpenCode 2.x
opencode plugin -g @archcore/opencode-plugin    # OpenCode 1.x
```

All these ways add the package to `~/.config/opencode/opencode.json`. OpenCode 2.x writes it under the `plugins` key, and OpenCode 1.x under `plugin`. OpenCode 2.x reads both keys, so you do not need to rename an older entry. Restart OpenCode after the install.

To check the install, type `/archcore-` in a project that has `.archcore/`. The list shows `/archcore-init`, `/archcore-plan`, `/archcore-document`, and `/archcore-review`. The commands carry the `archcore-` prefix because OpenCode has its own `/init` and `/review`. The subagents are `@archcore-assistant` and `@archcore-auditor`.

The plugin registers the `archcore` MCP server as `archcore mcp`, but only when the config has no `mcp.archcore` entry. If an existing `mcp.archcore` entry points at another command, the plugin keeps it, and document tools go to that command. Remove the old entry, or run `archcore init --agent opencode` in the project to write the standard one.

In OpenCode, the plugin runs the three lifecycle hooks. The write guard covers the `write`, `edit`, `apply_patch`, and `patch` tools. Code-alignment context arrives with the result of the edit, not before it.

| Task   | OpenCode 2.x                                       | OpenCode 1.x                                                                             |
| ------ | -------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| Update | `opencode plugin update @archcore/opencode-plugin` | Delete `~/.cache/opencode/node_modules/@archcore/opencode-plugin`, then restart OpenCode |
| Remove | `opencode plugin remove @archcore/opencode-plugin` | Delete the package from the `plugin` array of `~/.config/opencode/opencode.json`         |

### Other hosts

[Section titled “Other hosts”](#other-hosts)

Gemini CLI has hook wiring, but an executed host session has not confirmed the integration’s tool-event behavior. Roo Code and Cline use document tools without Archcore lifecycle hooks.

## Instruction hint

[Section titled “Instruction hint”](#instruction-hint)

An instruction hint tells the model that Archcore tools exist and when to consult project context. It is distinct from the server’s tool instructions and from lifecycle events.

```bash
archcore instructions install --agent claude-code
```

Claude Code receives the hint in `CLAUDE.md` and `AGENTS.md`; Gemini CLI uses `GEMINI.md`; the other listed hosts use `AGENTS.md`. Interactive `archcore init` asks before writing the hint. A named `--agent` authorizes it; noninteractive initialization without a named agent skips it.

Archcore manages only the text between these markers:

```markdown
<!-- archcore:start -->
...
<!-- archcore:end -->
```

Keep your own instructions outside the managed block. For a custom harness, place equivalent guidance in the system or project instructions your host actually loads: ask the agent to discover applicable Archcore documents, read them before the relevant work, and use MCP for document changes. Prompt guidance informs model behavior; it does not enforce it.

Use `archcore instructions remove` to remove managed hints. The [CLI reference](/cli/commands/#archcore-instructions) covers targeted removal and older layouts.

## Install per host

[Section titled “Install per host”](#install-per-host)

The [platform installer](/start/install/) adds the plugin automatically when the Claude Code, Codex CLI, GitHub Copilot CLI, or OpenCode command is already on `PATH`. Use the steps below if you install a host later or need to retry. The plugin invokes `archcore` from `PATH`; it does not download the executable.

| Host               | Plugin installation                                                                            |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| Claude Code        | `archcore plugin install --agent claude-code`                                                  |
| Cursor             | Add the repository URL through the Plugins panel                                               |
| Codex CLI          | `archcore plugin install --agent codex-cli`                                                    |
| GitHub Copilot CLI | `archcore plugin install --agent copilot`, then `archcore init --agent copilot` in the project |
| OpenCode           | `archcore plugin install --agent opencode`, or [the OpenCode command](#opencode)               |

Codex CLI, Copilot CLI, and OpenCode plugin installations are machine-level. Restart the agent after changes. Use `archcore plugin status` to inspect installation state and the [CLI reference](/cli/commands/#archcore-plugin) for updates and removal.

## Hook output and limits

[Section titled “Hook output and limits”](#hook-output-and-limits)

Event payloads, recap limits, and installed wiring

### The three events

[Section titled “The three events”](#the-three-events)

| Event          | What runs                                                         | Can block                |
| -------------- | ----------------------------------------------------------------- | ------------------------ |
| `SessionStart` | project recap, staleness advisory                                 | No                       |
| `PreToolUse`   | write guard, code-alignment injection                             | **Yes**, the write guard |
| `PostToolUse`  | structure validation, relation cascade notice, precision findings | No                       |

Each host spells these events its own way. See [Installed wiring](#installed-wiring). Archcore installs one hook entry per (host, event) pair, and the process picks the check to run from the tool name in the payload.

Everything except the write guard is **advisory**: it adds text to the agent’s context and never changes what the agent is allowed to do.

### Session start

[Section titled “Session start”](#session-start)

The recap goes into the agent’s working context before you type anything. Its sections, in order:

1. Header and the MCP tool line.
2. The invalid-settings warning, when `.archcore/settings.json` is present but cannot be parsed or validated.
3. `CORPUS`: document counts by category and by status, including rejected.
4. `BRANCH`: the checked-out branch, when it resolves.
5. `GLOBALS`: one line per declared [global source](/cli/configuration/#global-sources), when at least one source is declared.
6. `IN PROGRESS`: drafts, newest first.
7. `RECENTLY ACCEPTED`: documents accepted in the last 30 days, newest first.
8. The staleness advisory, when due.
9. `EXISTING TAGS`: the top 20 tags by frequency.
10. `DOCUMENT RELATIONS`: the relation count and the tools that manage it.
11. A closing pointer to the MCP server instructions.

Example output:

```text
[Archcore — Git-native context for AI coding agents]
You have MCP tools available: list_documents, get_document, search_documents, create_document, update_document, remove_document, add_relation, remove_relation, list_relations.


CORPUS: 42 documents — knowledge 30, vision 9, experience 3 · draft 11, accepted 30, rejected 1
BRANCH: feature/payments


IN PROGRESS (draft, newest first):
  - .archcore/payments/stripe-webhooks.adr.md — "Stripe Webhook Retry Policy"
  … and 7 more — list_documents(status="draft")


RECENTLY ACCEPTED (last 30 days):
  - .archcore/auth/jwt-strategy.adr.md — "JWT Session Strategy"


EXISTING TAGS: payments, auth, api, security, cli


DOCUMENT RELATIONS: 18 relation(s) stored.
  Use list_relations, add_relation, remove_relation MCP tools to manage.


Refer to MCP server instructions for document types, workflow rules, and usage guidance.
```

#### The `GLOBALS` block

[Section titled “The GLOBALS block”](#the-globals-block)

When `.archcore/settings.json` declares at least one [global source](/cli/configuration/#global-sources), the recap carries a `GLOBALS` block after `BRANCH`, or after `CORPUS` when the branch does not resolve. It tells the agent that a global exists, how large it is, and what it covers:

```text
GLOBALS (read-only, query via MCP read tools):
  - archcore — 42 docs (knowledge 40, vision 1, experience 1) · product/ 14, concepts/ 14, architecture/ 7, market/ 4, web/ 3
  ⚠ global source "company" not found at "../company/.archcore" — skipped until it is cloned; local documents are unaffected
  Local documents take precedence over same-topic globals.
```

One line renders per declared source, in declaration order. A healthy source’s line carries the declared `id`, its document count, its per-category counts, and its top-level directories with document counts, ordered by count descending and alphabetically on a tie. The directory list is the source’s vocabulary: enough for an agent to phrase a query against a corpus it has never read.

What the block does and does not do:

* **Every count comes from filenames and directory names.** The block reads no global document’s content, and it adds no corpus scan to session start. The numbers come from the walk that already classifies each declared source.
* **No global document path, title, or tag appears in it.** Global content stays behind the MCP read tools.
* **A declared source’s warning renders inside the block**, prefixed with `⚠`, and the remaining sources still render. An invalid `settings.json` is the one case that behaves differently: it produces a standalone warning and no `GLOBALS` block at all.
* **The precedence sentence closes the block** when at least one healthy source rendered a count line.
* **`CORPUS` switches its label.** While the block renders, the corpus count reads `local documents`, and the connected banner gains the total global document count: `… · 102 docs + 42 global`.

When no global source is declared, neither the block nor its heading appears, and `CORPUS` keeps its plain `documents` label.

#### The recap is bounded

[Section titled “The recap is bounded”](#the-recap-is-bounded)

The recap is a budgeted summary, not an index of your knowledge base:

* **At most 24 document lines** across `IN PROGRESS` and `RECENTLY ACCEPTED` combined. A truncated block says how many documents were omitted and names the `list_documents` filter that returns them.
* **`EXISTING TAGS` caps at 20**, ranked by frequency. The ranking draws on every local document, rejected ones included, so the agent reuses your vocabulary instead of inventing synonyms.
* **Rejected documents never appear in either block**, but they are counted in `CORPUS`.
* **`GLOBALS` caps at 8 source lines and 6 directories per line.** When either cap drops entries, the block names how many it dropped. The banner total still counts every healthy source, including one the block truncated away.
* Every document line carries the full `.archcore/`-prefixed path, so you can pass it to `get_document` unchanged.

Output length follows that budget, not corpus size. A 300-document project and a 3000-document project produce recaps that differ only by the width of the `CORPUS` counters. The `GLOBALS` block carries its own ceilings for the same reason: its size follows those ceilings, never the size of the mounted corpus.

No global document line appears in the recap. The `GLOBALS` block reports per-source counts only, and global documents themselves are surfaced through the MCP read tools and the code-alignment injection.

Note

The recap degrades rather than fails. A global source that is missing, empty, or in a fatal state renders its warning inside the `GLOBALS` block, and the scan continues over the sources that are usable, so your local documents are never dropped. An invalid `settings.json` warns with `invalid .archcore/settings.json: … — global sources not loaded` and continues without the block. Outside a git tree, or on a detached `HEAD`, the `BRANCH` line is omitted rather than filled with a placeholder.

#### Staleness advisory

[Section titled “Staleness advisory”](#staleness-advisory)

When the session starts, Archcore compares the last commit that touched `.archcore/` against everything committed since, and names the documents that mention the directories that moved. Archcore rate-limits the advisory to **once per 24 hours per project**, and it does not consume that budget when it finds nothing to report.

### Before a write

[Section titled “Before a write”](#before-a-write)

`PreToolUse` fires when the agent is about to write a file. Two things happen, in a fixed order.

#### The write guard

[Section titled “The write guard”](#the-write-guard)

This is the only guard in the whole system that can deny. It runs **first and alone**, and the deny decision is computed before any advisory work starts. A failure anywhere in the advisory path cannot change the verdict on your edit.

It blocks a direct write to a document in `.archcore/`, and refuses exactly what the MCP write tools refuse: both consult the same predicate, so a path the tools reject cannot be reached by going around them. It also refuses a document inside a global source mounted from outside the store. The MCP tools cannot address that path at all, so the guard checks it separately.

The guard does not block non-document files under `.archcore/`: `settings.json`, `.sync-state.json`, and anything non-Markdown.

The reason the agent receives:

```text
Direct writes to .archcore/ documents are not allowed. Use Archcore MCP tools instead:
- create_document: create a new document
- update_document: modify an existing document
- remove_document: delete a document
This ensures validation, templates, and the sync manifest stay consistent.
```

On most hosts the deny goes to stderr with exit code 2. On GitHub Copilot it is a `permissionDecision` JSON document on stdout with exit code 0. Copilot reads any non-zero exit as a deny and discards the reason with it, so the zero exit carries the explanation to the user.

#### Code-alignment injection

[Section titled “Code-alignment injection”](#code-alignment-injection)

An agent about to edit a source file has no reason to know a rule constrains it. This advisory finds the documents that mention the file’s directory and puts the most specific ones in front of the edit:

```text
[Archcore Context] Read these before editing src/api/handlers/users.ts:
- rule: API Error Envelope [.archcore/api/error-envelope.rule.md]
- adr: Handler Layering [.archcore/api/handler-layering.adr.md]
Rules that name no path apply to every file:
- rule: Commit Message Format [.archcore/commit-format.rule.md]
```

What it does and does not do:

* **Source roots.** The file must sit under a source root. The defaults are `src`, `lib`, `app`, `pkg`, `cmd`, `internal`, `apps`, `packages`, `modules`, `components`. Setting `codeAlignment.sourceRoots` in `.archcore/settings.json` **replaces** that list. It does not extend it.
* **Only seven document types are injected**, ranked in this order: `rule`, `cpat`, `adr`, `spec`, `scenario`, `guide`, `doc`. A `scenario` is included from CLI v0.8.4; a `journey` is not. A plan, an idea, or a journey is context for a discussion, not a constraint on a line of code.
* **Two lists.** The first list holds documents that name the file, its file kind, or one of its directories. A document that names the file itself ranks above one that names a directory, and a deeper directory ranks above a shallower one. The second list holds accepted rules and `cpat` documents that name no path in the project; they apply to every file.
* **Caps.** At most 5 matched documents, 10 general rules, and 2048 runes reach the host. When a cap drops rows, the message says how many more exist and names the MCP call that lists them. The rune budget drops general rows first.
* **Drafts are marked `[draft]`**, so the reader knows the document is not yet accepted.
* **Globals are included** and marked `[global]`, so the reader does not try to update what they cannot write.
* **`.archcore/` paths are skipped.** Editing a document is the write guard’s business.
* **`ARCHCORE_DISABLE_INJECTION=1`** turns the injection off entirely.

```json
{
  "sync": "none",
  "codeAlignment": {
    "sourceRoots": ["services", "libs"]
  }
}
```

Caution

Archcore does not deliver code-alignment context on GitHub Copilot. Its pre-write event carries only a permission decision, so the write guard runs there and the injection does not. See [Host limitations](#host-limitations).

### After a write

[Section titled “After a write”](#after-a-write)

`PostToolUse` fires after one of five Archcore MCP tools changed something: `create_document`, `update_document`, `remove_document`, `add_relation`, or `remove_relation`. It only reports; the tool has already run, so nothing here can deny.

Three checks run, and a failure in one does not silence the others.

**Structure validation** reports the same problems `archcore doctor` finds, capped at 5 per run:

```text
[Archcore Validation] Issues found after the write:
  - .archcore/auth/jwt-strategy.adr.md: missing required field "status"
  … and 3 more — run archcore doctor
```

**Relation cascade notice** fires only on `update_document`, and only for incoming `implements`, `depends_on`, and `extends` relations. A `related` edge is an association, not a dependency, so it is excluded:

```text
[Archcore Cascade] auth/jwt-strategy.adr.md changed. Documents that may need review:
  - auth/session-refresh.spec.md (implements this document)
```

**Precision findings** measure the written document against the document contract. They fire on `create_document` and `update_document` only. The checks fall into four groups:

| Group                                        | Examples                                                                                                                                                                            |
| -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Every document type                          | Vague wording, missing section, foreign section, frontmatter, placeholder body, cross-document links, long code block, restatement                                                  |
| Types with graded clauses or procedure steps | Requirement over 25 words, step over 20 words, compound requirement, condition after the obligation, open-ended list, ambiguous alternative, misplaced BCP 14 modal                 |
| One type only                                | `SHALL` in a `spec`, oversized `spec`, subjectless passive, EARS clause in a `prd` requirement, `rule` with no file target, `adr` with one alternative, `cpat` without a code block |
| Content ownership                            | A heading whose content another type owns, and a statement copied word for word from a linked document                                                                              |

One report carries at most 12 findings and ends with a count of what the cap dropped:

```text
[Archcore Precision] .archcore/auth/jwt-strategy.adr.md (advisory):
  - vague wording (robust) — replace with a concrete fact, version, threshold, or measurement
  - missing section: ## Alternatives Considered
  - +2 more finding(s) not shown (report cap 12)
```

[Precision checks](/reference/document-format/#precision-checks) lists every check, the types it grades, and the threshold behind it.

The advisory validates the document path through the containment-safe read guard before opening the file, so a symlink out of `.archcore/` produces no findings at all. The restatement check reads the sync manifest to find linked documents, and returns nothing when the manifest will not load.

### Installing

[Section titled “Installing”](#installing)

Hooks are installed automatically during `archcore init`. To install them by hand:

```bash
archcore hooks install                    # every detected agent
archcore hooks install --agent cursor     # one agent
archcore hooks install --project /path    # a project root other than the cwd
```

`hooks install` also writes the MCP config for the same agents.

Re-installing updates the Archcore entry in place and keeps every field Archcore does not own. A `timeout` you added on a host where Archcore writes none, or a key written by a newer Archcore, survives; a timeout Archcore does own (Gemini CLI, GitHub Copilot) is reset to Archcore’s value. An entry that differs only by a field Archcore does not own stays untouched, and the file keeps its bytes and its mtime.

#### Installed wiring

[Section titled “Installed wiring”](#installed-wiring)

Five hosts receive install wiring:

| Host           | Config file                   | Session event  | Pre-write event and matcher                                   | Post-write event and matcher      |
| -------------- | ----------------------------- | -------------- | ------------------------------------------------------------- | --------------------------------- |
| Claude Code    | `.claude/settings.json`       | `SessionStart` | `PreToolUse`, `Write\|Edit`                                   | `PostToolUse`, MCP document tools |
| Codex CLI      | `.codex/hooks.json`           | `SessionStart` | `PreToolUse`, `Write\|Edit\|apply_patch`                      | `PostToolUse`, MCP document tools |
| Cursor         | `.cursor/hooks.json`          | `sessionStart` | `preToolUse`, `Write`                                         | `afterMCPExecution`, no matcher   |
| Gemini CLI     | `.gemini/settings.json`       | `SessionStart` | `BeforeTool`, `write_file`                                    | `AfterTool`, MCP document tools   |
| GitHub Copilot | `.github/hooks/archcore.json` | `sessionStart` | `preToolUse`, `create\|edit\|str_replace_editor\|apply_patch` | `postToolUse`, MCP document tools |

The MCP document-tool matcher covers `create_document`, `update_document`, `remove_document`, `add_relation`, and `remove_relation` under every name spelling a host may deliver.

Archcore writes a 1-second timeout on the pre-write event and a 3-second timeout on the session and post-write events. GitHub Copilot takes those values in seconds (`timeoutSec`) and Gemini CLI takes them in milliseconds (`timeout`); Claude Code, Codex CLI, and Cursor entries carry no timeout field.

**OpenCode** gets no hook config file. Its hooks are JavaScript plugins, so the [Archcore plugin for OpenCode](#opencode) runs them, and `archcore hooks install` writes nothing for OpenCode. **Roo Code** and **Cline** get no hooks at all. Roo Code supports `onSave` only, which is not a lifecycle event. Both still work through [MCP](/guides/connect-your-agent/#mcp).

Example Claude Code entry, written by `archcore hooks install`:

```json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          { "type": "command", "command": "archcore hooks claude-code session-start" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          { "type": "command", "command": "archcore hooks claude-code pre-tool-use" }
        ]
      }
    ]
  }
}
```

#### Host limitations

[Section titled “Host limitations”](#host-limitations)

A host can accept a hook config and still not run it. After a successful install, `archcore hooks install` prints what stands between the file and a hook that fires. **Silence means the wiring works.**

* **Codex CLI** hooks are experimental and off by default (enable with `codex --enable hooks`, or `[features]` with `hooks = true`; `codex_hooks = true` before Codex 0.129.0). They do not run on Windows at all, and project-local hooks load only when the project’s `.codex/` layer is trusted.
* **GitHub Copilot** carries only a permission decision in its `preToolUse` event, so the write guard runs and the code-alignment injection does not. Copilot also reads `.claude/settings.json`, so a project wired for both hosts produces duplicate output. The verdict stays correct.
* **Gemini CLI** tool events (`BeforeTool` / `AfterTool`) come from the published reference and are not confirmed against a running host.

`archcore doctor` prints the same notes, but only for a host whose config holds an Archcore hook command. A detected host that was never wired is not reported on, and with nothing wired `doctor` says nothing about hooks rather than claiming they are healthy.

Note

If an older Archcore plugin is installed, its hooks and the CLI’s may both fire. `hooks install` and `doctor` report it. The cost is duplicated output, never a wrong verdict. Updating the plugin resolves it.

### Running a hook by hand

[Section titled “Running a hook by hand”](#running-a-hook-by-hand)

Each host invokes one hidden leaf per event:

```bash
archcore hooks <host> <event>
```

Hosts: `claude-code`, `cursor`, `gemini-cli`, `copilot`, `codex-cli`, `opencode`. Events: `session-start`, `pre-tool-use`, `post-tool-use`.

The payload arrives as one JSON object on stdin, so pipe something in when you run a leaf yourself:

```bash
echo '{}' | archcore hooks claude-code session-start
```

An unrecognized host or event writes **empty stdout and exits 0**. On a hook, stdout is the protocol channel. A usage message there would land several hundred bytes of help text in the model’s context, so silence is the correct answer.

The same reasoning drives the rest of the failure behavior: empty, truncated, or non-JSON stdin allows; an unresolvable project root allows; an internal panic is recovered, reported on stderr, and allows. A hook that cannot read its input never blocks your work.

### Removed hooks

[Section titled “Removed hooks”](#removed-hooks)

Archcore removed the `Stop` and prompt-time hook families, and they have not returned. The prompt-time family covered the `UserPromptSubmit`, `BeforeSubmitPrompt`, and `BeforeAgent` event spellings. They matched keywords against natural language: phrases like “step 1:”, “always”, and “root cause” fired in ordinary conversation, and agents were blocked or handed instructions they did not need.

`PreToolUse` and `PostToolUse` match on tool names and file paths, not on message text.

Caution

A config written by an older Archcore may still carry `Stop`, `UserPromptSubmit`, `BeforeSubmitPrompt`, or `BeforeAgent` entries pointing at commands that no longer exist. Re-running `archcore hooks install` will not add them back, but it will not remove them either. Delete them by hand.

## Next steps

[Section titled “Next steps”](#next-steps)

* [Quick start](/start/quick-start/) verifies document creation and retrieval.
* [Integrations](/guides/integrations/) covers cooperation with other tools.
* [Troubleshooting](/guides/troubleshooting/) covers connection and lifecycle failures.
