Skip to content

The Cursor Harness Surface ​

Cursor exposes more harness machinery than any other mainstream AI editor. This chapter is the map: every artifact, where it lives, and what job it does in the control system.

Note: Harness Score supports multiple tools (Claude Code, Windsurf, Cline, Continue, and others) via OR semantics. This chapter focuses on Cursor as the flagship example. See Multi-Harness Support for how other tools are recognized and scored.

The artifacts at a glance ​

ArtifactPathFamilyLoaded
Agent context fileAGENTS.mdGuideAlways
Rules.cursor/rules/*.mdcGuideAlways / by glob / by relevance
Skills.cursor/skills/*/SKILL.mdGuideOn demand, by description
Commands.cursor/commands/*.mdGuideExplicitly, via /name
Hooks.cursor/hooks.jsonSensor + GuardrailOn agent-loop events
MCP servers.cursor/mcp.jsonGuide (tools)Per session
Subagentsagent definitionsGuideDelegated tasks
PluginsMarketplace / .cursor-plugin/All bundledInstalled

Everything lives in the repository, which is the point: the harness ships with the code, is versioned with the code, and is reviewed like code.

Cursor also supports user-level artifacts (~/.cursor/skills, ~/.cursor/mcp.json, global commands) that never appear in git. They do not affect your maturity score (CI stays reproducible) but can raise your effective score when you enable --scope user — see Multi-Harness — project vs global and Metrics & Codes.

AGENTS.md — the front door ​

AGENTS.md at the repository root is the first thing an agent reads. It is an open convention (Cursor, Claude Code, and most agentic tools honor it) and the highest-leverage single file in your harness. It should answer, briefly:

  • What is this project and how is it laid out?
  • How do I build, run, and test it?
  • What conventions are non-negotiable?
  • What must I never touch?

Keep it under ~150 lines. It is loaded on every session — every line taxes the context window of every task. Details that only matter sometimes belong in scoped rules or skills.

Rules — persistent, declarative guidance ​

Rules are markdown-with-frontmatter files (.mdc) under .cursor/rules/. Each rule declares when it applies:

markdown
---
description: API route conventions
globs: src/api/**
---

- Every route validates input with zod before use.
- Errors return `{ "error": string }` and a correct status code.

Three activation modes:

  • alwaysApply: true — injected into every request. Reserve for true non-negotiables; every always-on rule is a permanent context tax.
  • globs: <pattern> — applied when matching files are in play. This is the workhorse mode: conventions live next to the code they govern.
  • description only — the agent decides relevance from the description.

Nested .cursor/rules/ directories work in monorepos: put package-specific rules inside the package.

The legacy single-file .cursorrules is deprecated. Migrate it: split by concern, scope by glob.

Skills — procedural knowledge on demand ​

A skill is a folder with a SKILL.md (open Agent Skills standard):

markdown
---
name: deploy
description: Use when the user asks to deploy or release; covers tagging,
  pipeline, and smoke tests.
---

# Deploying
1. …step-by-step workflow…

Cursor shows the agent every skill's name + description at session start; the body loads only when the agent judges it relevant. That makes skills the right home for long procedural content that would bloat rules: deploy runbooks, migration recipes, release checklists, debugging playbooks.

The rule of thumb: rules are declarative and always-on-ish ("use strict TypeScript"), skills are procedural and on-demand ("here is how we deploy"). The description is the trigger — write it as "Use when…" or it will never fire.

Commands — workflows you invoke deliberately ​

Markdown files under .cursor/commands/ become /slash-commands. Unlike skills (agent-triggered), commands are human-triggered: repeatable workflows you want on a keybinding-like surface — /review, /release, /harness-audit. A command file is simply the prompt that runs when invoked.

Hooks — observe and control the agent loop ​

.cursor/hooks.json registers scripts on agent lifecycle events:

json
{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [{ "command": "node ./.cursor/hooks/guard.js" }],
    "afterFileEdit": [{ "command": "node ./.cursor/hooks/format.js" }]
  }
}

Scripts receive JSON on stdin and answer on stdout — including permission decisions (allow / deny / ask) for the gating events. Key events:

  • Gates (can block): beforeShellExecution, beforeMCPExecution, preToolUse, beforeReadFile
  • Feedback (observe results): afterFileEdit, postToolUse, afterShellExecution, stop
  • Lifecycle: sessionStart (inject context), sessionEnd, preCompact

Hooks are the only Cursor mechanism that is enforced by the harness runtime rather than suggested to the model. A rule saying "never run destructive commands" is a request; a beforeShellExecution hook that denies them is a fact. Chapter 5 builds on this distinction.

MCP — tools and knowledge ​

.cursor/mcp.json connects Model Context Protocol servers: databases, issue trackers, docs, browsers. From a harness perspective MCP is a guide (it determines what the agent can see and do) and a risk surface (servers run with your credentials — never inline secrets; use ${ENV_VAR} interpolation).

Subagents — purpose-built delegates ​

A subagent is a markdown file under .cursor/agents/ (or a plugin's agents/ folder) with the same name + description frontmatter contract as a skill:

markdown
---
name: reviewer
description: Use when asked to review a pull request or diff for conventions
  in AGENTS.md and .cursor/rules; reports findings by severity without
  editing code.
---

# Reviewer subagent

Read the diff, AGENTS.md, and .cursor/rules/*.mdc. Report violations ordered
by severity. Never modify code — that's the parent agent's job.

The distinction from a skill: a skill teaches the primary agent a procedure it runs inline; a subagent is a separate delegate the primary agent hands a task to — often with its own scoped tool access or a narrower job description, so a large task (a full repo audit, a multi-step release) can be split across specialized workers instead of one agent doing everything in one context. Cursor's own docs describe this as delegating "purpose-built" work — a planner, a reviewer, a release runner — each with a tight enough description that the primary agent can decide when to hand off without guessing.

The same rule as skills applies to the description: it is the only signal the parent agent uses to decide whether to delegate, so write it as a trigger condition, not a label.

Plugins — the harness, packaged ​

A Cursor plugin bundles rules, skills, commands, hooks, agents, and MCP config under one installable unit with a .cursor-plugin/plugin.json manifest, distributed through the Cursor Marketplace. Plugins matter for harness engineering because they make harness patterns reusable across repositories — including the Harness Score plugin that audits the very artifacts this chapter described (installable from its repo directory today; its Marketplace listing is pending review).

When you scan a plugin repository (manifest at the scan root), harness-score maps default plugin skills/, commands/, agents/, and hooks/hooks.json to the same checks as .cursor/... layout — see chapter 8 — plugin layouts.

Choosing the right mechanism ​

You want to…Use
State a convention that always holdsRule (alwaysApply) — sparingly
State a convention for part of the codebaseRule with globs
Teach a multi-step procedureSkill
Package a workflow humans triggerCommand
Delegate a job to a separate, purpose-built workerSubagent
Enforce something regardless of what the model thinksHook
Give the agent a tool or data sourceMCP server
Share all of the above across reposPlugin

If a piece of guidance keeps being ignored, move it down this table — from prose the model may skip, toward mechanisms the runtime enforces.