Skip to content

fix(init): --agent cursor installs Cursor only and creates ~/.cursor - #3000

Merged
KuSh merged 3 commits into
rtk-ai:developfrom
rNoz:fix/init-agent-cursor-directory
Sep 25, 2026
Merged

KuSh merged 3 commits into
rtk-ai:developfrom
rNoz:fix/init-agent-cursor-directory

Conversation

@rNoz

@rNoz rNoz commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Two defects made rtk init -g --agent cursor fail / pollute the home dir:

  1. It fell through to the shared init path with install_claude derived only from !opencode, so it created RTK.md, CLAUDE.md, and patched settings.json under ~/.claude in addition to patching .cursor/hooks.json. On machines without ~/.claude it failed outright: Failed to create temp file in ~/.claude: No such file or directory.
  2. Even after removing the .claude writes, the Cursor path still failed on a fresh machine because install_cursor_hooks never created ~/.cursor before atomic_write placed its temp file there.

Fixes:

Root cause

  • src/main.rs, Commands::Init handler: install_claude = !opencode. Cursor is the only sibling agent that reaches the shared init path (Windsurf/Cline short-circuit earlier in hooks::init::run), so it incorrectly triggered the Claude install branch.
  • src/hooks/init.rs, install_cursor_hooks: wrote hooks.json via atomic_write without ensuring the parent directory exists.

Fix

// src/main.rs
let install_cursor = agent == Some(AgentTarget::Cursor);
let install_windsurf = agent == Some(AgentTarget::Windsurf);
let install_cline = agent == Some(AgentTarget::Cline);
let install_claude =
    !opencode && !install_cursor && !install_windsurf && !install_cline;

// src/hooks/init.rs (install_cursor_hooks)
if !dry_run {
    fs::create_dir_all(&cursor_dir)?;
}

Test plan

  • cargo fmt --all && cargo clippy --all-targets && cargo test --all: pass.
  • New tests/init_agent_cursor_test.rs:
    • agent_cursor_dry_run_never_touches_claude: asserts dry-run output contains no /.claude/ path and does patch /.cursor/.
    • agent_cursor_real_write_creates_no_claude_dir: non-dry-run install in a temp HOME: exits 0, never creates ~/.claude, and writes .cursor/hooks.json.
    • default_dry_run_still_installs_claude: regression: default init still installs Claude Code files.
  • cargo test --bin rtk hooks::init: 169 existing init tests pass (no regression).

E2E Validation

Tested locally and providing proofs (Screenshot). All working as expected:

image

rtk init -g --agent cursor fell through to the shared init path with
install_claude derived only from !opencode, so it created RTK.md,
CLAUDE.md, and patched settings.json under ~/.claude in addition to
patching .cursor/hooks.json. On machines without ~/.claude it failed
outright when creating the temp file.

Two fixes:
- Gate install_claude on the absence of a sibling agent target (Cursor,
  Windsurf, Cline) so only the default or explicit Claude target
  installs Claude Code files.
- Create ~/.cursor before patching hooks.json; atomic_write places its
  temp file in the target's parent, which failed on a fresh machine
  where the directory did not yet exist.

Closes rtk-ai#2097
@rNoz

rNoz commented Jul 15, 2026

Copy link
Copy Markdown
Contributor Author

Tested E2E locally with my local rnoz/integration branch. All working as expected. See the capture. Ready for review/merge.

@rNoz

rNoz commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

@pszymkowiak please, let me know if I have to do anything else here (or it's just waiting), since another PR was closed in favor of my current one. I have also another one reviewed by some independent folk. Have a good one!

@theabhinavdas

Copy link
Copy Markdown

@rNoz Curious if this fixes rtk-ai usage on the Cursor IDE vs. the Cursor CLI tool? Or is rtk-ai meant only for terminal-based coding agents like Claude Code and Cursor CLI?

@rNoz

rNoz commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

@rNoz Curious if this fixes rtk-ai usage on the Cursor IDE vs. the Cursor CLI tool? Or is rtk-ai meant only for terminal-based coding agents like Claude Code and Cursor CLI?

I focused on the cli for testing, but if I have to guess, it will work for both.

@theabhinavdas theabhinavdas left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

I've reviewed this PR and tested on my machine:

Macbook Pro M1 Max - Mac OS 15.5 (24F74) - Sequoia

Cursor Desktop (non CLI):
Version: 3.13.10
VS Code Extension API: 1.128.0
Commit: 4f02290ccd9304f0e6bf8ee85f6e9106f02ac1f0
Date: 2026-07-23T21:41:07.333Z
Layout: IDE
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.256
OS: Darwin arm64 24.5.0

These changes expertly fix the original issue(s) described.

However, these changes alone do not solve the wider rtk usage on Cursor IDE (non CLI).

It seems that the rewrites made by rtk use "permission":"ask" in update_input which doesn't actually show a permission interrupt for users to decide. But it looks like #1173 solves for this issue (untested).

@rNoz

rNoz commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Friendly ping @aeppling. This has been open since July 14 with a community approval (@theabhinavdas tested it on Cursor IDE, MacOS Sequoia) but no maintainer review yet. It closes #2097: rtk init -g --agent cursor was writing RTK.md/CLAUDE.md/settings.json into ~/.claude and failing on fresh machines where ~/.cursor did not exist. Rebased on current develop; fmt/clippy/tests green. Happy to adjust anything if you see something.

@PedroS11

Copy link
Copy Markdown

Is there any ETA on this MR? Cursor users would really appreciate it 😞

@rNoz

rNoz commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

Yeah this is depressing (not only in this repo but others AI-powered as well), ETA hopefully by 2030.

KuSh and others added 2 commits September 26, 2026 01:28
Carries the Cursor hunk into src/hooks/init/cursor.rs after the init.rs
split (rtk-ai#3878).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tests set only HOME, so an exported CLAUDE_CONFIG_DIR made
default_dry_run_still_installs_claude fail, and the non-dry-run install
wrote its tracking database into the caller's XDG_DATA_HOME. Pin
RTK_DB_PATH and XDG_* inside the temp home, drop CLAUDE_CONFIG_DIR,
disable telemetry, and check the exit status of every dry run.

Cover the two remaining inputs of the install_claude decision: an
explicit --agent claude still installs Claude Code, and --agent cursor
with --opencode installs the OpenCode plugin and the Cursor hook only.

Also correct the Cursor comment in init::run: with --agent cursor no
longer installing Claude Code, Cursor hooks go in on their own or next
to the OpenCode plugin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@KuSh KuSh left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Round 1 of 3 — APPROVED, follow-ups filed

Claim: rtk init -g --agent cursor installs the Cursor hook only (no RTK.md, CLAUDE.md or settings.json under ~/.claude) and creates ~/.cursor before writing hooks.json, so it works on a machine that has neither directory (#2097).
Scope: accept, as a Cursor-only fix. Making every installer create its own parent directory is a separate follow-up and is not asked of this PR. (round 1, frozen)
Ran: all 3064 rtk init forms × 6 home seeds (empty, user content, env dirs, empty env, invalid JSON, existing backups) × install / re-run / uninstall, develop 91872ab vs this PR merged onto it. Every one of the 215 differences is an --agent cursor row, 20 of them go from exit 1 to exit 0, there are no crashes, and no other agent changes. On the seeds with user content, develop rewrites the user's ~/.claude/CLAUDE.md and this PR leaves it byte-identical. Also by hand: cursor with --claude-md, --hook-only, --opencode, --no-patch; ~/.cursor as a symlink, a dangling symlink and a regular file; project-scoped refusal; dry-run creates nothing. Five mutations (gate reverted, create_dir_all dropped, dir created in dry-run, gate narrowed to agent.is_none(), Cursor skipped with --opencode) are each caught by a test. Invariants: non-default targets, every decision, user content. No filter involved, so no savings figure.
Matrix: executed this round
CI @f29882be: all green (11/11, incl. macOS, Ubuntu, Windows)

Blocks merge (0, frozen at round 1)

None.

Optional — will not hold merge

  • src/main.rs: install_claude lists what to exclude (!install_cursor && !install_windsurf && !install_cline). The Windsurf and Cline terms never take effect, because hooks::init::run sends both to their own modes before it reads install_claude. An allow-list, !opencode && matches!(agent, None | Some(AgentTarget::Claude)), has the same behaviour today and would stop a future agent that falls through to this branch from picking up Claude files.
  • Users who ran --agent cursor before this fix still have RTK.md, the @RTK.md line and the settings.json hook under ~/.claude. rtk init -g --uninstall removes them. That is worth a line in the release notes, not code here.

Filed as follow-ups

  • #913 (false "No hook installed" warning): the check only looks for the Claude hook. After this PR, a Cursor-only install on a machine that has a ~/.claude directory hits it: rtk ls prints the warning and suggests rtk init -g. Gemini-only installs already get it on develop. Evidence added there.
  • #4248: after this PR, --agent cursor silently ignores --claude-md and --hook-only, as --agent windsurf and --agent cline already do on develop. --no-patch still patches Cursor's hooks.json, also as on develop. These are symptoms of the way rtk init chooses its target, so #4248 proposes one --agent <name> form with a per-agent list of supported options, rather than one more guard per combination.

Checked and correct — no need to re-verify

  • The install_claude = false, install_cursor = true case lands in the (false, false, _, _) arm of run, which develop already keeps from bailing when Cursor is requested. --opencode installs the plugin and then the Cursor hook.
  • create_dir_all runs only outside dry-run and before the legacy-script migration. A symlinked ~/.cursor is followed exactly as develop's atomic_write follows it. A dangling symlink or a regular file at ~/.cursor fails with Failed to create …/.cursor: File exists; develop failed on those too.
  • --agent cursor --uninstall was already Cursor-only on develop, so install and uninstall now match.
  • --agent claude and a plain -g install exactly the same Claude files as before.
  • --agent cursor no longer writes ~/.config/rtk/filters.toml. Only the Claude path generates that template, and --opencode on its own already skips it on develop, so Cursor now behaves like the other non-Claude installs.

Hypotheses built and dropped

  • Reusing #2521's ensure_parent_dir here instead of create_dir_all: this belongs to the follow-up that makes all the installers create their directories the same way, so it is not asked of this PR.

Your questions

  • "please, let me know if I have to do anything else here" → nothing. I pushed the fixup below, which carries the rebase.

Next

Fixup pushed, then approving:

  • a2ab981f merges develop and moves the ~/.cursor hunk into src/hooks/init/cursor.rs after the init.rs split (#3878).
  • f29882be pins the new tests' environment inside the temp home. With CLAUDE_CONFIG_DIR exported, default_dry_run_still_installs_claude failed, and the real install wrote history.db into the caller's XDG_DATA_HOME. The commit also checks the dry runs' exit status, adds tests for --agent claude and --agent cursor --opencode, and corrects the "Cursor hooks (additive, installed alongside Claude Code)" comment in init::run.

Rounds: 1/3. Threads: 0 open, 0 resolved this round.

@KuSh
KuSh merged commit b21c038 into rtk-ai:develop Sep 25, 2026
11 checks passed
@rtk-release-bot rtk-release-bot Bot mentioned this pull request Sep 25, 2026
@KuSh KuSh mentioned this pull request Sep 25, 2026
2 tasks
@rNoz

rNoz commented Sep 26, 2026

Copy link
Copy Markdown
Contributor Author

Not bad: 2 MONTHS AND 11 DAYS to merge it. Good job, what a repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rtk init -g --agent cursor fails bug: "rtk init -g --agent cursor" errors due to expecting $HOME/.claude

4 participants