Cursor integration

Shipmoor Team
June 27, 2026
7 min read

Shipmoor plugs into Cursor on the same three levels it does for Claude: the CLI is the scan engine, Agent Skills tell the agent to scan and triage, and the Agent Harness closes the loop, re-scanning on each edit and gating before the agent finishes. Since 0.5.1, Cursor is a first-class native adapter: the harness writes a real .cursor/hooks.json backed by Cursor’s own lifecycle hooks, at parity with the Claude Stop hook. This page covers the supported single-repo install first, then a clearly-labeled advanced pattern for multi-root workspaces.

The native single-repo adapter is the primary, supported path. Multi-root is an advanced setup you assemble yourself because of a Cursor limitation described below.

Prerequisites

Same as the Claude Code page:

  • CLI shipmoor version0.5.1. The harness is bundled into the binary; you invoke it as shipmoor harness <cmd>.
  • Entitlements. shipmoor capabilities should show agent_harness enabled (the IC plan). Check identity with shipmoor whoami; sign in with shipmoor login.
  • git in the repo: scan --changed needs a repo to diff.
  • Cursor recent enough to ship the .cursor/hooks.json lifecycle-hook surface.
shipmoor version
shipmoor capabilities
shipmoor whoami

Install the skills

Install the five skills into Cursor’s rule surface:

shipmoor skills install cursor

This writes .cursor/rules/shipmoor.md, an always-applied managed rule (re-running the install overwrites it byte-for-byte). It teaches the agent the five Shipmoor behaviors:

SkillWhat it makes the agent do
shipmoor-reviewRun scan --changed, triage, explain blockers, gate before “done”.
shipmoor-agent-guardInspect manifests first; never invent imports or APIs; no placeholder logic.
shipmoor-intent-contractProvide the change’s intent and check the result against it (Claim Check).
shipmoor-fixRepair only introduced findings, re-scan until the gate passes, report the delta.
shipmoor-pr-preflightDiff-scoped “am I ready to open this PR?” with a copyable PR note.

Skills make the agent want to scan; the harness makes the scan happen and gates the result. Run both. See Agent Skills for the full surface.

Advisory code review with Cursor

Cursor is also a built-in reviewer for Shipmoor Code Review, the advisory AI review that sits next to the deterministic scan above:

shipmoor review --agent cursor --from main --to HEAD

This drives your own cursor-agent CLI in read-only mode (--mode ask, no file edits) over the change and reports advisory findings. It is Pro (cli_pro), it never gates the build, and your source never leaves the machine. Override the underlying command with SHIPMOOR_REVIEW_CURSOR_CMD. See Bring your own agent for the wire contract and the claude, codex, and cursor presets.

Install the harness (single repo)

When you open a single repo as its own Cursor workspace, the native adapter is the whole setup:

shipmoor harness install cursor

This writes a real .cursor/hooks.json with two managed entries beside any hooks you already have (yours are never touched). The shape:

{
  "version": 1,
  "// shipmoor:harness": {
    "note": "Managed by shipmoor-harness (Cursor adapter). Uninstall removes these entries."
  },
  "hooks": {
    "afterFileEdit": {
      "command": "shipmoor harness hook cursor after-file-edit"
    },
    "stop": {
      "command": "shipmoor harness hook cursor stop"
    }
  }
}

The top-level "version": 1 is required for Cursor to load the hooks. The sibling "// shipmoor:harness" key records provenance so shipmoor harness uninstall cursor removes exactly what was added and a reinstall stays byte-idempotent.

What each hook does

  • afterFileEdit runs after the agent edits a file. Cursor gives this event no channel back to the agent, so the handler only records: it runs one scan --changed pass and refreshes .shipmoor/last-watch.json. The skills/adapter rule then tells the agent to read that report; Shipmoor surfaces the report rather than pushing it back inline.
  • stop runs when the agent tries to finish. This is the gating event. It scans the repo’s Git changes; in feedback or block mode, on routable findings it returns {"followup_message": "..."}, which Cursor auto-submits as the next user turn so the agent keeps fixing. In feedback mode the loop is bounded by max_feedback_cycles (Cursor passes its loop_count, and Cursor independently enforces its own loop_limit); in block mode a breach always gates, the direct analogue of the Claude Stop hook returning a non-zero exit every time.

Soft fallback

If you decline native hooks, install the rules-only fallback:

shipmoor harness install cursor --soft

This writes only .cursor/rules/shipmoor-harness.md, a fully managed adapter rule, no native hooks. The agent gets feedback through that rule instead, off a last-watch.json report. The --soft install never touches .cursor/rules/shipmoor.md (the skills file); they are separate surfaces. Installing one harness mode migrates away from the other; uninstall removes both.

Choose a mode and verify

Start in feedback so blockers loop back to the agent without hard-failing:

shipmoor harness mode feedback
shipmoor harness status
ModeBehavior
observeReports only; never changes the outcome (safest start).
feedbackLoops blockers back to the agent, bounded by max_feedback_cycles (the default).
blockNon-zero verdict on a gate breach (firmest; pair with CI).

Why one-shot scans, not a daemon? Native Cursor hooks running a one-shot (shipmoor harness scan or shipmoor scan --changed) are deterministic and tied to the agent lifecycle, the same shape as the Claude Stop hook, with no long-lived process to babysit. Through 0.5.1 a detached watch daemon was not reliably keep-alive-able for hook use, so the one-shot supersedes it for the loop.

Advanced: multi-root workspaces

This section is an advanced, self-assembled pattern. If you open one repo as its own workspace, use the native adapter above and skip this.

The catch. Cursor executes only the workspace-root .cursor/hooks.json. It does not discover nested per-repo hooks.json the way it discovers nested rules. So a per-repo shipmoor harness install cursor run inside a subfolder writes <repo>/.cursor/hooks.json that never fires from a multi-root root.

The pattern. Keep one root-level, self-extending hook set that fans out to every opted-in repo, with each hook calling the CLI one-shot. A compact root .cursor/hooks.json:

{
  "version": 1,
  "hooks": {
    "afterFileEdit": [
      { "command": ".cursor/hooks/shipmoor-scan-edit.sh", "timeout": 30 }
    ],
    "stop": [
      { "command": ".cursor/hooks/shipmoor-gate.sh", "timeout": 90, "loop_limit": 3 }
    ]
  }
}

Two small scripts back it, both one-shot:

  • shipmoor-scan-edit.sh (afterFileEdit): reads the edited file, maps it to its opted-in repo, and refreshes that repo’s <repo>/.shipmoor/last-watch.json. Pure side effect: afterFileEdit has no channel back to the agent, so the adapter rule surfaces the report.
  • shipmoor-gate.sh (stop): for each opted-in repo, runs shipmoor scan --changed --fail-on high; if blocking findings exist, it prints {"followup_message": "..."} so the agent keeps fixing. The loop_limit bounds the loop.

Opt a repo into the loop:

cd <repo>
shipmoor init                            # writes .shipmoor.yaml
shipmoor harness install cursor --soft   # writes .cursor/rules/shipmoor-harness.md (the opt-in marker)
shipmoor harness mode feedback

--soft is deliberate here: the root-level hooks do the enforcement, and the adapter rule file doubles as the opt-in marker the root scripts look for. Ensure <repo>/.gitignore contains .shipmoor/ so local reports are never committed. The root hooks act on any immediate subdir that has both .shipmoor.yaml and .cursor/rules/shipmoor-harness.md; adding a repo is just the setup above, with no hook edits.

Troubleshooting

SymptomLikely cause / fix
Agent finishes despite issuesRepo is in observe mode (shipmoor harness mode feedback), or the repo isn’t opted into the loop.
Gate never firesMissing <repo>/.shipmoor.yaml, or the marker rule .cursor/rules/shipmoor-harness.md is absent. Re-run the opt-in steps.
A correct import is flaggedDeclare it in the manifest (requirements.txt / pyproject.toml / package.json), or waive it narrowly in .shipmoor.yaml if it’s a vendored package the scanner can’t resolve.
A scan in an && chain killed the rest of the lineThe scan exited 1 by design at a blocker; append a guard (|| true) so it doesn’t abort the line.

Next

Last updated on June 27, 2026

Was this article helpful?

Your response is saved on this device.