Skip to content

fix(cli): #2269 honor --dangerously-skip-permissions in hive-mind spawn#2301

Merged
ruvnet merged 3 commits into
ruvnet:mainfrom
JOhnsonKC201:fix/2269-dangerously-skip-permissions
Jun 12, 2026
Merged

fix(cli): #2269 honor --dangerously-skip-permissions in hive-mind spawn#2301
ruvnet merged 3 commits into
ruvnet:mainfrom
JOhnsonKC201:fix/2269-dangerously-skip-permissions

Conversation

@JOhnsonKC201

Copy link
Copy Markdown
Contributor

Fixes #2269.

Summary

hive-mind spawn --claude --non-interactive --dangerously-skip-permissions was silently dropping the flag. The arg parser (parser.ts normalizeKey) converts kebab-case to camelCase and stores only the normalized key, so flags['dangerously-skip-permissions'] was always undefined and the === true check always failed. The headless claude child therefore ran in permissionMode: \"default\", every Edit/Write landed in permission_denials, and the agent finished having changed nothing.

Fix

Mirror the dual-key fallback used a few lines above for isNonInteractive:

```ts
const skipPermissions =
(flags['dangerously-skip-permissions'] === true || flags.dangerouslySkipPermissions === true) &&
!(flags['no-auto-permissions'] || flags.noAutoPermissions);
```

This is the patch the issue reporter (@rvrheenen) proposed verbatim — kept narrow on purpose. Also resolves the documented default: true mismatch the secondary note in #2269 called out, because the parser populates the camelCase key with the option's default value.

Verification

Repro from the issue:

```
npx @claude-flow/cli hive-mind spawn --claude --non-interactive
--dangerously-skip-permissions -o "edit any file in this repo"
```

  • Before: stream-json `init` event shows `"permissionMode":"default"`; every `Edit` lands in `permission_denials`; files unchanged.
  • After: `--dangerously-skip-permissions` is appended to `claudeArgs`; spawned `claude` runs in `bypassPermissions`; edits succeed (matches running `claude -p --dangerously-skip-permissions` directly).

Scope

One file, one logical change. No behavior change for users who don't pass the flag (parser default behavior unchanged); only the previously-broken path is restored.

🤖 Generated with RuFlo

…nd spawn

The arg parser (parser.ts normalizeKey) converts kebab-case to camelCase
and stores ONLY the normalized key, so `flags['dangerously-skip-permissions']`
is always undefined and `=== true` always evaluates false. The flag was
silently dropped: headless `hive-mind spawn --claude --non-interactive
--dangerously-skip-permissions` ran in permissionMode "default", so every
Edit/Write was auto-denied (no TTY to approve) and the agent finished
having changed nothing.

Fix mirrors the dual-key fallback used a few lines above for
`isNonInteractive` (`flags['non-interactive'] || flags.nonInteractive`).
This also honors the documented `default: true` for the option declaration
(line 590), since the parser populates the camelCase key with the default.

Repro from the issue:
  npx @claude-flow/cli hive-mind spawn --claude --non-interactive \
    --dangerously-skip-permissions -o "edit any file in this repo"

Before: init event shows `"permissionMode":"default"`, Edit calls land
in permission_denials, files unchanged.
After:  `--dangerously-skip-permissions` is appended to claudeArgs,
spawned `claude` runs in `bypassPermissions`, edits succeed.

Fixes ruvnet#2269

Co-Authored-By: RuFlo <ruv@ruv.net>
@JOhnsonKC201 JOhnsonKC201 requested a review from ruvnet as a code owner June 6, 2026 03:57
…ip-permissions

Pins down two invariants together:
1. The parser stores ONLY the camelCase form of --dangerously-skip-permissions
   (this is the parser behavior that caused the original drop).
2. The skipPermissions predicate from hive-mind.ts evaluates true when the
   parser-produced flags shape is passed through it.

Also exercises the --no-auto-permissions opt-out and the legacy
hand-constructed-flag-map paths, so a future refactor of either the
parser's normalizeKey or the hive-mind action can't silently regress
the flag-drop bug.

The predicate is kept inline rather than imported, because the hive-mind
spawn action does real side effects (childSpawn) at module load and isn't
trivially importable for a pure unit test. The predicate's source of
truth (hive-mind.ts) and the test mirror are both annotated with ruvnet#2269.

Co-Authored-By: RuFlo <ruv@ruv.net>
@ruvnet

ruvnet commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Thanks @JOhnsonKC201 — the kebab→camel diagnosis is right and the activation half of the fix works. Caught one regression while running the test locally before merging:

× skipPermissions=false when --no-auto-permissions is also passed
   → expected true to be false

Verified with the live parser:

new CommandParser({ allowUnknownFlags: true })
  .parse(['--dangerously-skip-permissions', '--no-auto-permissions']).flags
// →
{
  dangerouslySkipPermissions: true,
  autoPermissions: false,      // ← parser uses yargs-style negation
  ...
}

So neither flags['no-auto-permissions'] nor flags.noAutoPermissions is ever true; the parser stores the negation as autoPermissions: false. The predicate as written:

!(flags['no-auto-permissions'] || flags.noAutoPermissions)

…evaluates to !undefined = true, so the deny-half never fires. After your PR, --dangerously-skip-permissions --no-auto-permissions would skip permissions — strictly more permissive than the pre-fix state.

Suggested one-line fix:

const skipPermissions =
  (flags['dangerously-skip-permissions'] === true || flags.dangerouslySkipPermissions === true) &&
  !(flags['no-auto-permissions'] || flags.noAutoPermissions || flags.autoPermissions === false);

That keeps the dual-key fallback for the hand-built case and also covers the actual CLI form. The existing test on line 47 should then go green, plus please add one for the explicit camelCase: { dangerouslySkipPermissions: true, autoPermissions: false }false.

Holding the merge until that lands. Everything else in the PR — the kebab→camel root-cause writeup, the dual-key idiom mirroring isNonInteractive, the parser-pinning test — is the right shape. Just the deny-half needs the third clause.

ruvnet added a commit that referenced this pull request Jun 12, 2026
Patch release bundling two fixes landed since 3.10.43:

- #2348 (7c63626) — break embedder-rescue mutual recursion that OOM'd
  v3-ci.yml at the V8 heap limit. memory-bridge's rescueAgentdbEmbedder
  now delegates to generateLocalEmbedding (bridge-free leaf), not
  generateEmbedding (bridge-first). Closes #2312. CI gate re-enabled.
- #2366 (a21f680) — Windows plugin install/uninstall/upgrade. npm on
  Windows is a bash shim with no .exe (spawn ENOENT) and Node refuses
  to spawn .cmd directly post-CVE-2024-27980 (spawn EINVAL). Routes
  through cmd.exe /d /s /c npm <args> on Windows; POSIX unchanged.
  Validated via the existing validatePackageName regex gate and Node's
  array-form argument quoting. (community PR by @danielsOink.)

Held from this batch:
- #2301 (hive-mind --dangerously-skip-permissions) — passing 5/6 but the
  --no-auto-permissions deny case fails because the parser uses yargs-
  style negation (autoPermissions: false), which the predicate doesn't
  read. Comment posted with proposed fix.

Published to npm with latest + alpha + v3alpha tags for all three
packages. 9/9 dist-tag combinations verified at 3.10.44.

Co-Authored-By: RuFlo <ruv@ruv.net>
The original PR (ruvnet#2301) correctly diagnosed the kebab→camel parser
normalization that made the activation half of the
--dangerously-skip-permissions flag silently no-op. The deny half had
the same shape of bug but the patch only widened it to kebab|camel —
neither of which is what the parser actually produces for
--no-auto-permissions.

The parser stores yargs-style negation:

  --no-auto-permissions → { autoPermissions: false }

NOT { 'no-auto-permissions': true } or { noAutoPermissions: true }.

So after the original fix, --dangerously-skip-permissions
--no-auto-permissions would have skipped permissions anyway — strictly
more permissive than the pre-fix state, where activation never fired at
all. Caught by running hive-mind-skip-permissions.test.ts case "skip
permissions=false when --no-auto-permissions is also passed", which
went red.

This commit adds the third deny clause (`flags.autoPermissions === false`)
and pins the parser contract with three new tests:
- parser produces autoPermissions:false for --no-auto-permissions
- predicate denies when only the yargs-style negation key is set
- predicate ignores autoPermissions:true (not a deny signal)

Tests: 9/9 pass. Closes ruvnet#2269.

Co-Authored-By: JOhnsonKC201 <johnsonkc201@users.noreply.github.com>
Co-Authored-By: rvrheenen <rvrheenen@users.noreply.github.com>
Co-Authored-By: RuFlo <ruv@ruv.net>
@ruvnet ruvnet merged commit 50bc516 into ruvnet:main Jun 12, 2026
ruvnet added a commit that referenced this pull request Jun 12, 2026
Patch release shipping a single fix landed since 3.10.44:

- #2301 (e7b9eea9f) — hive-mind --dangerously-skip-permissions: complete
  the kebab→camel parser-normalization fix by adding the yargs-style
  negation deny clause (autoPermissions === false). Without this, the
  prior commit's activation half worked but --no-auto-permissions could
  no longer block, leaving the spawn strictly more permissive than the
  pre-fix state. 9/9 regression tests pass — 3 new cases pin the parser
  negation contract. Co-authored with @JOhnsonKC201 (original PR) and
  @rvrheenen (issue reporter who supplied the original patch). Closes #2269.

Published to npm with latest + alpha + v3alpha tags for all three
packages. 9/9 dist-tag combinations verified at 3.10.45.

Co-Authored-By: RuFlo <ruv@ruv.net>
@JOhnsonKC201

Copy link
Copy Markdown
Contributor Author

Thanks for catching the regression and pushing the fix. Good to know the parser stores --no-auto-permissions as autoPermissions: false rather than a camelCase key, and even better that the parser contract is pinned in tests now.

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.

hive-mind spawn --claude: --dangerously-skip-permissions is silently dropped (kebab vs camelCase flag key), so headless runs cannot edit files

2 participants