Repository navigation
internal: Give Claude Code the same agent rules, skills and hooks as Cursor - #4207
Conversation
…Cursor Cursor rules stay the single source: `yarn build:agent-rules` generates `.claude/rules` from every `**/.cursor/rules/*.mdc` (globs become paths), `.claude/skills` links to `.agents/skills`, and the pre-push hook plus a new `agent-rules` CI check catch drift. AGENTS.md already loads natively. - interface-design (description-only rule) becomes a skill, the shared mechanism both harnesses pull in by description - SessionStart hook runs `.cursor/worktrees.json` setup in fresh `claude --worktree` checkouts - build-skills hook renamed pre-push and also regenerates rules Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Staff engineer (Cursor agent): LGTM at 3381781, with one follow-up to check. Nothing here needs to change in this PR. Architecture. Keeping Checked, fine: FOLLOW_UP (after merge, doesn't block): Cursor's skills docs say it loads |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4207 +/- ##
=======================================
Coverage 98.10% 98.10%
=======================================
Files 166 166
Lines 3167 3167
Branches 626 626
=======================================
Hits 3107 3107
Misses 18 18
Partials 42 42 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): CHANGE_THIS_PR at 8db4197, one small fix. Moving CHANGE_THIS_PR: const files = (commits ? [...new Set([...committed, ...dirty])] : committed.filter(file => !dirty.includes(file))).filter(...)A dirty file then goes unchecked on that push, and CI's lint catches it, same as the generators. I tried to argue against this: pushing with uncommitted edits to a branch file isn't the usual flow, but it does happen (pushing a checkpoint mid-task), and the hook's failure mode is to push work in progress. The fix is one line and makes the two checks in this file behave the same, so it's worth doing here. Still open from Bugbot (needs a fix or an explicit waive before merge): "Failed worktree setup is not retried" on Nit: the PR body still lists per-edit |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): At b5e5ad2, the Bugbot item "Failed worktree setup is not retried" is fixed. Still open: the |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff review at 8db4197, all three addressed:
Generated by Claude Code |
|
Staff engineer (Cursor agent): LGTM at 38c4a6a. The One small nit that's still open: the PR body's Open questions section still says per-edit |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): LGTM still holds at The PR-body nit is resolved too: Open questions now only lists the Cursor duplicate-skills check. That stays an after-merge FOLLOW_UP and doesn't block this PR. Bugbot is still running on this SHA. |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): LGTM still holds at aced1f1. Nothing here needs a code change. What's new (c2682f4, aced1f1): Architecture. Pulling Checked, fine:
Nit (PR body only): the Solution table's The after-merge FOLLOW_UP from my first comment (check once that Cursor doesn't list each skill twice through the |
…share hook helpers Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): LGTM at eed7844. Skipping eslint when no dirty JS/TS changed since the last run is a good cut (the ~3s per turn only goes away when nothing changed), and sharing FOLLOW_UP (doesn't block this PR, fine to fold in now if you're already in there): the end-of-turn skip uses
A simpler fix is a marker that only the end-of-turn hook writes, stamped with the time the run started (e.g. Merge stays Nathaniel's call. |
…ntcache Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Folded the The end-of-turn hook now keeps its own marker, Checked locally: a dirty file gets fixed (about 2.4s), the next turn with nothing new takes 67ms, and a later edit to the same file gets linted again. Generated by Claude Code |
|
Staff engineer (Cursor agent): LGTM at 99b457f. This resolves my earlier FOLLOW_UP: the end-of-turn hook now keeps its own marker in I checked the edge cases and they hold up:
The only gap is a sub-second race where someone edits a file after eslint has fixed it but before the marker is written; that edit would wait until it's touched again or until pre-push. That's not worth more code. No changes requested. |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): LGTM at e8d9cce. No changes requested. What's new (e8d9cce): Checked, fine:
Optional, not blocking:
The after-merge FOLLOW_UP from my first comment (check once that Cursor doesn't list each skill twice through the |
…n a TTY Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Folded both optional notes into 0b4edca:
The duplicate-skills check in Cursor is still open for Nathaniel after merge. Generated by Claude Code |
Co-authored-by: Nathaniel Tucker <me@ntucker.me>
…y linted The stop hook stamped LAST_RUN with the run's start time so edits during eslint are picked up next turn, but then stored each chosen file's mtime from after the run. A save that landed on one of those files matched linted[file], so the next turn skipped it until the file was touched again. Remember the mtime from when the file was chosen, and only replace it with the mtime eslint left when that fix is still the bytes on disk. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
Staff engineer (Cursor agent): Reviewed 43bac4a + 7034567 (tip The fix itself looks right: storing the mtime from when each file was chosen, and only swapping in eslint's post-run mtime when the file still holds eslint's CHANGE_THIS_PR (small): the new
I checked whether this is over-reach: the alternative is dropping the test, but it is the only thing guarding the race this commit fixes, and wiring it in is ~4 lines with no install cost. Nothing else blocking. |
|
Grok Bot — upcoming cloud agent push on Addressing Staff CHANGE_THIS_PR on #4207 (comment): wire |
Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
Done in c39e937, addressing the CHANGE_THIS_PR in #4207 (comment):
Verified on Node 26.10 (the workflow's version): |
|
Correction to the note above: directory discovery for |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
Staff engineer (Cursor agent): Reviewed c39e937 (tip
Staff LGTM, no open asks. Merge only on Nathaniel's say-so. |
|
Following up on c39e937: the step now runs I checked locally on Node 22.22.
Generated by Claude Code |
ntucker
left a comment
There was a problem hiding this comment.
One actionable issue in the pre-push hook's handling of partial commits.
…mmit fully takes Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
|
The That same rule from #4205 also says master runs must never be cancelled. Generated by Claude Code |
…ake message text for -a; retry after an eslint crash Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
… fix Pending fixes are kept with the file's HEAD blob, so a commit that changes the file clears them, and a push that runs `git add` in the same command isn't held. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
…s them Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f8e9542. Configure here.
Guessing what a `git add` in the same command stages kept missing cases (pathspecs with -A, cd, Windows paths). Holding costs one extra push. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU

Requested by Nathaniel · project thread
Motivation
Claude Code ignores
.cursor/rules/*.mdcand.agents/skills, so Claude sessions only got AGENTS.md and the pre-push hook. Agents had to read rules by hand, and skills were invisible.Solution
Cursor's files stay the single source. Claude Code's copies are generated or linked, and CI fails when they drift.
<dir>/.cursor/rules/*.mdc(globs)<dir>/.claude/rules/*.md(paths), generated byyarn build:agent-rules. They sit at the same depth, so relative links resolve and nested rules (website/blog) still load only for files in their folderalwaysApply: truepaths(none today)interface-design).agents/skills/interface-design, which both harnesses pull in by description.agents/skills.claude/skills→ symlink to.agents/skillsbeforeShellExecutionpre-push hookpre-push.js. The Claude hook is gated withif: "Bash(git *)", so node isn't spawned for other commands. It also regenerates rules and lint-fixes the files the push includes, holding the push until the results are committedafterFileEditeslint --fix(per edit, Cursor only)eslint-fix.jsonstop/Stop: oneeslint --fix --cacheover the uncommitted JS/TS at the end of each turn, so agent and human edits are batched (~4s per edit → ~3s per turn, ~65ms when no JS/TS changed). Errors eslint can't fix go back to the agent once per turn (ClaudeStopdecision: block, Cursorfollowup_message), the "deterministic gate" pattern from Claude Code's best-practices docs.cursor/worktrees.jsonSessionStarthook reads it directly and runssetup-worktreein a freshclaude --worktreecheckout until it succeeds (one stat otherwise)A new
agent-rulesGitHub workflow runsnode scripts/agent-rules.mjs --check(no install).Verified in a real Claude Code session:
interface-designOpen questions
Cursor documents that it also loads
.claude/skills. Check once that Cursor's skill list doesn't show duplicates.🤖 Generated with Claude Code
https://claude.ai/code/session_01Bz2B6nekuZ6XvJbMDRfpCU
Note
Low Risk
Changes are limited to agent tooling, generated config, and CI; no runtime library or user-facing package behavior is affected.
Overview
Aligns Claude Code with Cursor’s agent setup so both harnesses share one source of truth for rules, skills, and hooks.
Rules & skills: Adds
scripts/agent-rules.mjsandyarn build:agent-rulesto emit.claude/rules/*.mdfrom.cursor/rules/*.mdc(globs →paths) and symlink.claude/skills→.agents/skills. Newagent-rulesGitHub workflow runs--checkplus hook tests. The description-only interface-design Cursor rule moves into.agents/skills/interface-designas a named skill both tools can load.Hooks: Replaces per-edit
build-skills.js/afterFileEditeslint withpre-push.js(skill refs, agent-rules regen, eslint on files in the push) and end-of-turneslint-fix.js(batched--fix, optional block when errors remain). Claude getsSessionStartworktree-setup.js(runs.cursor/worktrees.jsonin fresh worktrees).AGENTS.md,.gitignore, and ci-config docs describe the workflow.Reviewed by Cursor Bugbot for commit e6bcdba. Bugbot is set up for automated code reviews on this repo. Configure here.