From d9cd61b7509cdb14514633ce383525312ff2abd8 Mon Sep 17 00:00:00 2001 From: Doll Date: Mon, 11 May 2026 12:53:32 -0500 Subject: [PATCH] docs(kickoff): clarify agent permissions live in .claude/settings.json, not config keys (#730, GH#581) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--skip-permissions` is a per-invocation override of Claude's permission prompts; it is not the configuration knob. Persistent agent permissions live in the worktree's `.claude/settings.json` (`allowedTools` array + Claude Code's `permissions.allow` / `permissions.deny` blocks), which crosslink writes via `init` and preserves across `init --force` merges. Documents the contrast in three places per GH#581: - `docs_src/guides/kickoff.qmd` — new "Configuring agent permissions" subsection at the end of "Controlled agent execution", explaining both levers and when to use each. Links to Claude Code's settings reference for the canonical schema. - `docs_src/guides/container-agents.qmd` — extends the existing `--dangerously-skip-permissions` paragraph with a pointer to the persistent mechanism, cross-linked to the new kickoff section. - `crosslink/src/main.rs` — tightens both `--skip-permissions` clap doc-comments (kickoff `run` and kickoff `plan`) so `--help` surfaces the contrast inline. Verified rendered output via `kickoff run --help`. Pure docs/help-text change — no behavioral surface, no new tests. `cargo fmt --check` clean, `cargo check` clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- crosslink/src/main.rs | 13 +++++++++++-- docs_src/guides/container-agents.qmd | 2 ++ docs_src/guides/kickoff.qmd | 11 +++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/crosslink/src/main.rs b/crosslink/src/main.rs index 153c69f41..86f8c91e1 100644 --- a/crosslink/src/main.rs +++ b/crosslink/src/main.rs @@ -1600,7 +1600,12 @@ enum KickoffCommands { /// Path to a design document (markdown) with structured requirements #[arg(long, value_name = "PATH")] doc: Option, - /// Pass --dangerously-skip-permissions to the claude CLI (for sandboxed agents) + /// Per-invocation: pass --dangerously-skip-permissions to claude CLI. + /// + /// One-shot override that bypasses ALL Claude permission prompts for + /// this launch. Persistent policy lives in the worktree's + /// .claude/settings.json (allowedTools / permissions blocks); reach + /// for that instead of this flag for repeatable configuration. #[arg(long)] skip_permissions: bool, }, @@ -1720,7 +1725,11 @@ enum KickoffCommands { /// Print the prompt without launching #[arg(long = "dry-run")] dry_run: bool, - /// Pass --dangerously-skip-permissions to the claude CLI + /// Per-invocation: pass --dangerously-skip-permissions to claude CLI. + /// + /// One-shot override that bypasses ALL Claude permission prompts. + /// Persistent policy lives in the worktree's .claude/settings.json + /// (allowedTools / permissions blocks). #[arg(long)] skip_permissions: bool, }, diff --git a/docs_src/guides/container-agents.qmd b/docs_src/guides/container-agents.qmd index 2c338a3e1..739a4086e 100644 --- a/docs_src/guides/container-agents.qmd +++ b/docs_src/guides/container-agents.qmd @@ -152,6 +152,8 @@ The same crosslink hooks that enforce policy in local sessions also run inside c This means you can use `--dangerously-skip-permissions` for the Claude Code CLI inside the container (to avoid interactive trust prompts) while still maintaining policy enforcement through hooks. +That CLI flag is a **per-invocation override**, not a configuration. Persistent agent permissions are set in the worktree's `.claude/settings.json` -- specifically the `allowedTools` array and Claude Code's `permissions` block -- which crosslink writes via `init` and preserves across `init --force` merges. If you find yourself passing `--skip-permissions` to every container kickoff, the right move is to add the relevant tool patterns to `allowedTools` instead, so the agent runs unattended for that surface while every other tool still prompts. See [Configuring agent permissions](kickoff.qmd#configuring-agent-permissions) in the kickoff guide for the full contrast. +   --- diff --git a/docs_src/guides/kickoff.qmd b/docs_src/guides/kickoff.qmd index 91cc68d4a..bf23feff8 100644 --- a/docs_src/guides/kickoff.qmd +++ b/docs_src/guides/kickoff.qmd @@ -226,6 +226,17 @@ The background agent operates under the same crosslink hook enforcement as inter   +### Configuring agent permissions + +Agent permissions live in the **agent config file** -- `.claude/settings.json` in the worktree, written by `crosslink init` from crosslink's template. They are *not* configured through any `crosslink config` key. There are two levers, and they answer different questions: + +- **Persistent policy (`.claude/settings.json`)** -- the `allowedTools` array (and Claude Code's `permissions.allow` / `permissions.deny` blocks) decide which tools the agent may run without prompting on *every* run. Edit this file to teach a repo "agents may always run `npm test`" or "agents may never run `curl`". Crosslink's `init` merges its defaults with whatever the file already contains, so hand-edits are preserved across `init --force`. +- **Per-invocation override (`--skip-permissions`)** -- the `crosslink kickoff run --skip-permissions` flag passes `--dangerously-skip-permissions` to the Claude CLI for that single launch, bypassing *all* prompts. It is a one-shot dial, not a setting. Reach for it when you have decided the surrounding environment (sandbox, container, isolated worktree, hook policy) makes the agent's blast radius acceptable. Do not reach for it as a substitute for configuring `allowedTools`. + +If you find yourself passing `--skip-permissions` on every kickoff, that's a signal to add the relevant tool patterns to `allowedTools` in `.claude/settings.json` instead -- agents will then run unattended for the allowed surface without giving up the prompt for everything else. See [Claude Code's settings reference](https://docs.claude.com/en/docs/claude-code/settings) for the full schema of `allowedTools` and `permissions`. + +  + --- ## Managing kickoffs