Skip to content

fix(init): fail closed on missing .claude dir and hoist OpenCode install (fixes #4046) - #4323

Merged
KuSh merged 6 commits into
rtk-ai:developfrom
TechWizard9999:fix/4046-opencode-additive-v2
Oct 3, 2026
Merged

KuSh merged 6 commits into
rtk-ai:developfrom
TechWizard9999:fix/4046-opencode-additive-v2

Conversation

@TechWizard9999

Copy link
Copy Markdown
Contributor

Summary

Fixes #4046 regressions where --opencode was riding the Claude install path, so every Claude-path failure or early-exit took the OpenCode plugin down with it.

Changes

  1. src/hooks/init/claude.rs:

Fixes Three Regressions

Command Before (regression) After (fixed)
init -g --opencode --auto-patch exit 1, nothing installed exit 0, both installed
init -g --opencode --hook-only --auto-patch exit 1 exit 0, both installed
init -g --opencode --claude-md, re-run exit 0, "already up to date", plugin missing exit 0, both installed

Test Coverage

Existing test test_global_opencode_installs_when_claude_dir_missing (already #[cfg(unix)]) verifies the missing-dir fix. The hoisted OpenCode install ensures plugin installs even on re-run with unchanged CLAUDE.md block.

- Add fs::create_dir_all for .claude dir in patch_settings_json_command and run_default_mode (fixes rtk-ai#2519, rtk-ai#4046 Windows regression)
- Hoist OpenCode plugin installation before Unchanged early return in run_claude_md_mode_with
- Fixes rtk-ai#4046 regressions.
@rtk-wshm-sync-bot rtk-wshm-sync-bot Bot added bug Something isn't working init opencode windows labels Sep 28, 2026
@rtk-wshm-sync-bot

Copy link
Copy Markdown

wshm · Automated triage by AI

📊 Automated PR Analysis

🐛 Type bug-fix
🟡 Risk medium

Summary

Fixes three regressions around global init --opencode: creates the .claude config directory if missing before writing settings/CLAUDE.md, and hoists the OpenCode plugin installation before the early return that fires when the CLAUDE.md block is already up to date. This ensures OpenCode installs correctly regardless of directory existence or whether the rtk block changed.

Review Checklist

  • Tests present
  • Breaking change
  • Docs updated

Linked issues: #4046, #2519


Analyzed automatically by wshm · This is an automated analysis, not a human review.

The previous fix created the .claude directory unconditionally, but dry-run
mode must not create directories. Only create the directory when not in
dry-run mode.

Fixes test: test_run_default_mode_dry_run_does_not_create_missing_claude_dir
@TechWizard9999

TechWizard9999 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

@KuSh review pls , This fixes #4046 regressions 1) fs::create_dir_all only in non-dry-run mode (fixes #2519, #4046 Windows regression), 2) Hoist OpenCode install before Unchanged early return. All three regressions fixed.

- README.md: change --opencode description to 'Claude setup + OpenCode plugin'
- supported-agents.md: clarify OpenCode installs Claude setup + plugin
- troubleshooting.md: change --opencode label to 'Claude Code + OpenCode plugin'
- main.rs: install Claude even when --opencode is passed (additive)
- mod.rs: update help text to 'Claude setup + OpenCode plugin'

Ports docs edits from rtk-ai#4052 to rtk-ai#4323.
TechWizard9999 and others added 3 commits September 28, 2026 21:56
…reation

`rtk init -g --opencode` installs the Claude setup and the OpenCode plugin
together. Cover a fresh home, --hook-only, a re-run with an unchanged
CLAUDE.md block, and --dry-run.

write_if_changed and the settings patch already create ~/.claude, so the
extra create_dir_all calls only replaced the contextual error with a bare
"File exists (os error 17)" and left an empty ~/.claude behind on
--no-patch runs. An unchanged CLAUDE.md block stays silent after the
plugin install, as on every other `rtk init` re-run.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
core::test_isolation fails the suite on a test file that names
CARGO_BIN_EXE_rtk itself, since the child then writes to the
contributor's real rtk data directory.

Co-Authored-By: Claude Sonnet 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 2 of 3 — APPROVED (round 1 was posted on #4052, which this PR carries forward)

Claim: rtk init -g --opencode installs the Claude hook and the OpenCode plugin together (Fixes #4046).
Scope: accept (frozen at #4052 round 1). #4052 is closed in favour of this PR; no other open PR claims #4046.
Ran: 3 binaries (merge-base 7efbaef46, head 523b86e0, head merged onto current develop 083a9c5d), one CARGO_TARGET_DIR each, md5s distinct; 16-row rtk init matrix per binary under an isolated HOME, LC_ALL=C, stdin /dev/null, plus 8 probes (malformed CLAUDE.md block, read-only ~/.claude, --hook-only --no-patch, re-run output of every non-opencode mode, sibling agents, declined prompt); mutations: routing revert, hoist revert, redundant-line removal. Invariants: every decision branch of the new routing (default, --hook-only, --claude-md, --dry-run, local rejection, --agent cursor), idempotence, user settings.json/CLAUDE.md content preserved. Savings floor N/A (init change, no filtered output).
Matrix: executed this round on this head (never run on #4323 before; #4052's matrix ran on a different head).
CI @56a2c33da: 11/11 pass. Local gate on the fixup merged onto current develop: fmt, clippy, cargo test --all (4097) green.

Blocks merge (0)

The two #4052 mechanisms are fixed on this head: a fresh HOME with --opencode (default and --hook-only) exits 0 with hook + RTK.md + plugin, and re-running --claude-md --opencode restores a deleted plugin.

Fixed by my fixup (b95e5b755, 56a2c33da; low-hanging; threads closed by it)

  • The two create_dir_all(&claude_dir)? lines are redundant. write_if_changed and the settings patch already create ~/.claude (#2521, merged 2026-09-26, after #4052's base — my "verified fix" part (a) in that review is superseded by it). With both lines removed, 14 of 16 matrix rows are byte-identical; the two that differ are ~/.claude as a file or dangling symlink, where the error now reads Failed to create directory: <path>: File exists instead of a bare File exists (os error 17). They also left an empty ~/.claude behind on --hook-only --no-patch (develop leaves nothing).
  • Every no-op rtk init re-run printed an extra Claude Code will now use rtk… line (plain local rtk init, init -g --claude-md, and the --opencode variants); develop is silent. The Unchanged return keeps its silence now; the OpenCode install stays hoisted above it.
  • No test pinned the change. Reverting the main.rs routing or the hoist left 310 init unit tests and 5 init integration suites green. tests/init_opencode_test.rs (spawning rtk through common::rtk_command(), as core::test_isolation requires) adds 5 tests (fresh home, --hook-only, unchanged-block re-run restores the plugin and stays silent, --hook-only --no-patch creates no ~/.claude, --dry-run writes nothing); the routing revert fails 5/5, the hoist revert fails the re-run test, head as authored fails exactly the two tests that pin its defects.
  • Comment rewrite: no issue numbers or history, says why the install sits above the early return.

Filed as follow-ups

  • NEW: a broken Claude side now aborts --opencode before the plugin is installed. --claude-md --opencode with a malformed <!-- rtk-instructions block, or --opencode with an unwritable ~/.claude, exits 1 with a clear message and no plugin (develop exits 0 and installs it). Loud rather than silent, and the class is the one named in #4052 round 1; filed as #4413, not blocking. Pre-existing: the same input already fails plain rtk init -g that way.

Checked and correct — no need to re-verify

Local --opencode rejected (exit 1); --agent cursor --opencode installs OpenCode + Cursor and never creates ~/.claude; dry-run output lists all six actions and writes nothing; existing settings.json keys and CLAUDE.md content survive byte for byte; second --opencode --auto-patch leaves settings.json identical; CLAUDE_CONFIG_DIR pointing at a missing nested dir works; --uninstall --opencode after an install removes both; docs wording (README, supported-agents, troubleshooting, --show text) matches behaviour; clean merge with #4343 and #4269.

Your questions

None open. Note for the description: the "before" column in the PR body describes #4052's head, not develop (develop installs only the plugin), and test_global_opencode_installs_when_claude_dir_missing is #2521's test; it passes without this PR's create_dir_all lines.

Next

Nothing from you: the fixup (tests, two removed lines, restored re-run silence) is pushed on top of your head, code-reviewed twice, CI 11/11 on 56a2c33da. Approving.
Rounds: 2/3. Threads: 0 open, 0 resolved this round.

@KuSh
KuSh merged commit b931928 into rtk-ai:develop Oct 3, 2026
11 checks passed
@rtk-release-bot rtk-release-bot Bot mentioned this pull request Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working init opencode windows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rtk init --opencode appears to skip Claude hook installation bug(init): global Claude init fails when ~/.claude is missing

2 participants