Skip to content
Apothem
Harnesses

Cursor

Apothem harness adapter for Cursor (GA).

Vendor: Anysphere Install name: cursor Status: GA Native config: .cursor/rules/ in the project root

Installation

apothem install --harness cursor --project /path/to/project

The adapter renders a single project-scope .mdc rules file from the shared Apothem rules and governance surface, writes Apothem's helpers as Cursor subagents in the project (see Subagents), and adds one hook to the project's hooks.json (see Hooks).

It also writes Apothem's skills, and the rules and templates they cite, to your user home, before it touches the project (see Files outside the project).

Files written:

  • <project>/.cursor/rules/apothem-rules.mdc, the rules file.
  • <project>/.cursor/agents/<name>.md for each Apothem helper, in the project.
  • <project>/.cursor/hooks.json, with one sessionStart entry added to it. Your own entries and keys in it stay.
  • <project>/.apothem/support/cursor/hooks/, the hook scripts, in the project.
  • ~/.agents/skills/<name>/SKILL.md for each Apothem skill and command, in your user home.
  • ~/.config/apothem/rules/ and ~/.config/apothem/templates/, in your user home.

The rules file summarizes the disciplines and names those folders, so the model can open a skill or a rule file when a task calls for it.

Files outside the project

The install also writes Apothem's skills to your user home, before it changes anything in the project:

FolderWhat Apothem writes there
~/.agents/skills/One folder with a SKILL.md for each Apothem skill, and one for each Apothem command (a command becomes a skill of the same name).
~/.config/apothem/rules/, ~/.config/apothem/templates/The rules and templates that the skills and the rules file refer to.

These folders are shared. They are not private to the project:

  • Every project you install cursor into, and every other Apothem install that names the folder, uses the same copy and writes the same files, so the order you install in does not matter. Several other tools read ~/.agents/skills/ too; the harness registry lists them.
  • --project chooses the rules file to write and which project the install belongs to. It does not change where the skills go.
  • The install adds no skill or rule file to your repository. The project gets the rules file, the subagent files in .cursor/agents/, the hook entry in .cursor/hooks.json, plus the .apothem/ folder every project install creates, which also holds the hook scripts.
  • The home folders are written first. If that fails, for example because a folder in the path is a link that leaves your home directory (a link that stays inside it is followed) or cannot be written, the install stops with the error before anything in the project changes.
  • A skill folder with an Apothem skill's name that Apothem did not write is left alone, and the install prints a warning that names it. Rename or move it, then run apothem update. apothem verify fails while that name is held.
  • The files add up to a few megabytes.

The install prints a note that names the folders it writes outside --project, and --dry-run lists them.

Subagents

Cursor reads a subagent from a Markdown file in <project>/.cursor/agents/, per the Cursor subagents documentation. The install writes one file per Apothem helper into that folder. It installs for the project only and writes no ~/.cursor/agents/ folder.

Each file keeps the helper's instructions unchanged and carries these frontmatter keys:

KeyWhat Apothem writes
name, descriptionThe helper's name and description.
readonlytrue for five helpers: citation-auditor, convention-auditor, fact-checker, memory-auditor and research-scout.

Cursor has no key that lists or denies tools: a subagent inherits every tool of its parent. The one limit it can enforce is readonly: true, which allows no file edits and no state-changing shell commands. So the helper's tools and disallowedTools lines are not written, and the limit survives only as that flag:

  • The five helpers above are read-only and have no Bash, so they get readonly: true and keep the read-only wording in their descriptions.
  • Seven helpers are read-only but run commands (codebase-explorer, dependency-auditor, design-critic, prompt-evaluator, quality-gate, security-scanner and test-runner). readonly: true would also stop their test and lint runs, so they get no flag, and their descriptions drop the read-only label that Cursor would not enforce. Only the description changes: the instructions are copied unchanged, so they still call the helper read-only and mention a tool restriction that a Cursor file does not have. The model follows that text, but Cursor does not enforce it, and the helper runs with every tool the parent has.
  • mcp-builder and refactor-surgeon write files and are unchanged.

The install writes no model key, so a helper runs on the model the parent uses, and none of is_background, a turn limit, or Apothem's version, updated and portability keys.

Things to know:

  • The subagent files are ordinary project files. Commit them with the project or list .cursor/agents/ in .gitignore; Apothem does not choose for you.
  • Cursor also loads helper folders written for other tools, among them .claude/agents/ in the project and ~/.claude/agents/ in your home directory (the harness registry lists the rest). On a name clash the project wins over the home folder and .cursor/ wins over the others, so in a project with this install the native files supersede the Claude Code copies Cursor would import from ~/.claude/agents/. Cursor's documentation does not say whether it loads both copies or drops the lower one, nor whether it applies the tools and disallowedTools lines of a Claude Code file it imports.
  • A file of yours with an Apothem helper's name is saved under ~/.apothem/backups/ and then replaced. The uninstall does not put it back. Files with other names are never touched.
  • Apothem has not confirmed whether Cursor reads the TOML files another tool writes to the folders it imports, whether the Third-Party Imports setting turns those imported folders off, or whether it reads extensions other than .md or nested folders in .cursor/agents/.

Hooks

Cursor runs hooks from hooks.json files, per the Cursor hooks documentation. The install adds one entry to <project>/.cursor/hooks.json:

EventWhat runs
sessionStartThe session bootstrap: session metadata, the skill index, the memory and plan summaries and the standing posture, added to the conversation's initial context.

The hook adds context for the model. It does not block anything, and Cursor does not wait for a sessionStart hook.

This first version registers nothing else. Cursor's documentation lists additional_context for postToolUse as well, and Apothem will register the context-size counter there once a probe shows that the context reaches the model. It registers no preToolUse guard: Cursor documents agent_message, the field a guard would speak through, only for an action it denies, and Apothem's guards never deny. The write, edit and shell guards, the AskUserQuestion check and the session-end protocol stay on the tools that deliver them.

Where the files go

FileWhat it holds
<project>/.cursor/hooks.jsonOne sessionStart entry, merged into the file's hooks map.
<project>/.apothem/support/cursor/hooks/The dispatcher script, its helpers and its message files.

hooks.json is your file, and Cursor documents project hooks as checked into version control. The install adds Apothem's entry after yours and leaves your entries and other keys as they were; an update replaces only the entry whose command runs the Apothem dispatcher (.apothem/support/cursor/hooks/dispatch.py with --contract cursor, whichever project path it was written under), and an uninstall removes only that entry. A hook of yours that only shares the name, such as tools/hooks/dispatch.py in your project, or that runs python -m apothem.conformity.gate, is never taken for Apothem's. The uninstall deletes the file when nothing else remains in it, after saving a copy under ~/.apothem/backups/. A file with comments, a trailing comma or a hooks value of the wrong shape cannot be rewritten without losing something, so the install reports a config.unparseable error for that file, leaves it untouched and stops, with the other files it had begun to write removed again: fix the file, or add the entry yourself.

The committed file names your machine. The entry's command holds the interpreter Apothem found when it ran and the absolute path of the project, so a teammate who checks out the file gets a command that points at your machine. Cursor reports a command it cannot find as failed and the session goes on, so nothing breaks, but the hook does nothing there. Commit the file only if your team shares that layout. Cursor documents no uncommitted variant of the project hook file. The .apothem/ folder is where the scripts live, and the project's .gitignore snippet keeps it out of version control.

A command looks like this, with your interpreter and project path in place of the two paths:

"/path/to/python" "/path/to/project/.apothem/support/cursor/hooks/dispatch.py" --contract cursor sessionStart

On a Windows host the command starts with & , PowerShell's call operator, because Cursor's desktop app runs hook commands through PowerShell, where a line that starts with a quoted program path is not a call. sh reads a leading & as a syntax error, so no other host gets it. The documentation names the shell and not the quoting, so this is Apothem's reading of PowerShell's syntax.

--contract cursor reads Cursor's conversation_id and workspace_roots and answers with {"additional_context": ...} and nothing else.

Paths the shell would misread. A project or interpreter path that contains $, a backtick, a double quote or a backslash is refused before anything is written: inside the quoted command it would run a different file, or break the JSON the command is written into. The error names the path; move or rename the project and run the install again. A space or an apostrophe in a path is fine.

Cursor also runs the hooks Claude Code wrote. Cursor loads the hooks in ~/.claude/settings.json, .claude/settings.json and .claude/settings.local.json while "Include Third-Party Plugins, Skills, and Other Configs" is on (in Cursor Settings, under Third-Party Imports), which is the default, and it runs every matching hook from every source. If you also installed Apothem for Claude Code, both sets of hooks can run. The sessionStart command here and the Claude Code copy of it share one marker per session in Apothem's hook state folder, so whichever runs second is silent and the bootstrap reaches the model once; Apothem finds Cursor from the CURSOR_PROJECT_DIR and CURSOR_VERSION variables Cursor sets for its hooks. The marker covers ten seconds, so a later start of the same session, such as a second compaction, still delivers. The Claude Code copy's context-size counter runs in addition, and Apothem does not de-duplicate the counters. To run only the hook here, turn that setting off; it also stops Cursor importing third-party plugins, skills and other configs. The install prints this as a note.

Things to know. Cursor reloads hooks.json when it is saved, so a restart is not needed. Project hooks run in trusted workspaces. Cursor's cloud runs a repository's project hooks but defers sessionStart, so the entry does not fire there. Set APOTHEM_HOOKS_DISABLE=1 in Cursor's environment to silence the Apothem hook.

Profile-to-native-config mapping

The adapter reads Apothem's shared profile and renders the project rules file on every apothem install or apothem update run. The shared profile is the source of truth; project-local edits to the generated file are backed up before the next sync replaces the Apothem-managed content.

The file opens with its YAML frontmatter (description, globs, alwaysApply: true), because Cursor reads a rule's type only from frontmatter at the start of the file. The Apothem-managed block follows it; text you add after the block is kept on every sync.

Compatibility notes

Cursor 0.45+ supports project-level instructions via .cursor/rules/. The adapter writes to the project-scoped .cursor/rules/ directory by default; Cursor has no documented file-based user-global rules path for this adapter to manage.

Cursor loads skills from ~/.agents/skills/, so the skills the install writes appear in Cursor without further setup. Cursor also loads ~/.claude/skills/, so on a machine that also has a Claude Code install it can list the same skill names twice, and its documentation does not say which copy wins. Apothem has not confirmed how Cursor treats a SKILL.md header key it does not list; the skills carry user-invocable, disable-model-invocation, allowed-tools, argument-hint, and a metadata map.

Verification

apothem verify --harness cursor --project /path/to/project

The verify command confirms that:

  1. The native config exists at the expected path.
  2. Each managed target exists, the .cursor/agents/ folder and the hook file .cursor/hooks.json included; managed files are non-empty, and JSON or YAML configs parse. The hook file must hold an entry that runs the Apothem dispatcher (the check does not run it), so a file that was reverted or emptied no longer verifies. Add --profile PATH to also confirm that the installed files match that profile. For .cursor/agents/ the check is that the folder exists, not that each helper file is in it; apothem diff --harness cursor --project /path/to/project lists the helper files that are missing or out of date.
  3. Every Apothem skill folder is in place with a SKILL.md, whichever install wrote it, and no skill folder with an Apothem name belongs to something Apothem did not write. A failed check names the missing or foreign folders.
  4. The adapter-specific verification routine reports success.

Updating

apothem update --harness cursor --project /path/to/project

Re-derives the project rules file from the current shared profile state.

The update also rewrites any skill folder whose files differ from the current ones. If you installed with an earlier release that wrote no skills, the update adds them. It rewrites subagent files that differ from the current ones, and adds any that are missing. It also refreshes the hook scripts and the Apothem entry in .cursor/hooks.json, leaving your own entries alone.

Uninstalling

apothem uninstall --harness cursor --project /path/to/project

Removes the Apothem block, and the frontmatter Apothem wrote above it, from <project>/.cursor/rules/apothem-rules.mdc and keeps any other text in it. The file is deleted only when nothing else remains in it. Before the change, a timestamped copy of the file is saved under ~/.apothem/backups/; no backup file is left in the project. The shared profile YAML and Apothem engine are unaffected.

The uninstall also removes the subagent files it wrote in <project>/.cursor/agents/ and keeps any other file there; the folder is removed when it is left empty. It removes the Apothem entry from <project>/.cursor/hooks.json, recognising it by the dispatcher path in its command, and keeps your own entries and keys. The file is deleted only when nothing else remains in it. The hook scripts in <project>/.apothem/support/cursor/hooks/ go too. If a file has comments that the uninstall cannot read, it leaves that file as it is and reports the entry as skipped, with the reason; remove the Apothem entry by hand. It removes the skill folders it wrote in ~/.agents/skills/ and the rules and templates in ~/.config/apothem/, but only when no other Apothem install still uses them. Another project, or another tool that shares the folder, may. In that case the uninstall keeps the folders, prints which install uses them, and the last uninstall removes them. Files you added to those folders stay, and a folder left empty is removed. Each folder is backed up under ~/.apothem/backups/ before it is removed.

Conformity gate

python -m apothem.conformity.gate --all .

Troubleshooting

SymptomFix
Config file not foundRe-run apothem install --harness cursor --project /path/to/project
Verification failedRun apothem update --harness cursor --project /path/to/project, then verify again
Cursor lists none of the Apothem helpersRun apothem diff --harness cursor --project /path/to/project. A pending line for the .cursor/agents folder means helper files are missing or out of date, so run apothem update --harness cursor --project /path/to/project. apothem verify is not a test of this: it passes when .cursor/agents/ exists, even with no helper file in it. If diff reports no pending changes, check that the project is open in Cursor and start a new chat
The Apothem hook does not runCursor runs project hooks in trusted workspaces only. Open the Hooks tab in Customize, or the Hooks output channel, to see whether the entry loaded and what it reported. A file written on another machine names that machine's interpreter, so Cursor reports the command as failed: run apothem update --harness cursor --project /path/to/project here
An install reports config.unparseable for hooks.jsonThe file has comments, a trailing comma or a hooks value of the wrong shape. Fix the file and install again, or add the sessionStart entry yourself
The Apothem context appears twiceCursor also runs the hooks the Claude Code install wrote. Turn off "Include Third-Party Plugins, Skills, and Other Configs" in Cursor Settings, under Third-Party Imports, to run only the hook in .cursor/hooks.json
apothem verify names a missing skill folderRun apothem install --harness cursor --project /path/to/project; it restores the folder
An install or update warns that it skipped a skill folderA folder with an Apothem skill's name already exists in the skills folder and Apothem did not write it. Rename or move it, then run apothem update
An install stops before it changes the projectA write in your home failed. Read the error, fix the folder it names (a link that leaves your home directory, a file where a folder belongs, or a read-only folder), and install again
Unexpected config contentCheck ~/.config/apothem/profile.yaml or --profile PATH, then re-run apothem update --harness cursor --project /path/to/project

Configuration knobs

FlagDefaultDescription
--dry-runfalsePreview install without writing files.

See also

On this page