feat(claude): trust the project of a permission_policy "allow" task - #5
feat(claude): trust the project of a permission_policy "allow" task#5Antisophy wants to merge 1 commit into
Conversation
Run non-interactively (cydo's -p mode), Claude leaves a directory untrusted and silently ignores its settings.local.json permissions.allow entries (and project hooks), warning "Ignoring N permissions.allow entries ... this workspace has not been trusted". Trust is keyed per-directory in ~/.claude.json (projects[<dir>].hasTrustDialogAccepted), so each project a task runs in needs its own flag, not just the workspace root. A workspace configured to auto-allow every tool call is already a statement of trust, so before launching a claude session whose workspace permission_policy is "allow", mark that task's working directory as a trusted project. Idempotent and atomic (merge into existing config, temp-file + rename, only when the flag is missing); never throws into session launch. Covered by a hermetic unit test (temp paths) asserting the target project is trusted, existing config is preserved, and the write is idempotent.
|
To be honest I don't have a good feeling about this. It crosses a line that we probably shouldn't cross. This:
so it's effectively a "shut up it's fine" lying auto-responder. More importantly, I'm curious why I've not encountered this problem myself. Is there a specific condition or local configuration in which it manifests? |
|
The configuration with which this manifests is when My Cydo instance did not work at all after the Claude CLI added this change, and the commit in this pull request allowed my Cydo instance to continue to work. Without it, it was no longer functional because there was no way for Cydo to interactively respond to the trust dialog. |
I understand, but as explained elsewhere, this is a very bad argument for merging patches just on the merit of that they fixed an observed problem. It's one step forward, a hundred steps back; untangling the lies from the truths becomes almost infinitely more difficult if they're allowed to solidify.
I don't understand the causality here. |
Problem
A recent Claude Code version added a per-workspace "trust" gate. When
clauderuns non-interactively (the-p/ stream-json mode cydo uses) it can't show the interactive trust dialog, so it treats the working directory as untrusted and silently drops that project'ssettings.local.jsonpermissions.allowentries (and its project hooks), printing:This affects every cydo task, because cydo always runs non-interactively. Three things make it awkward to handle from outside cydo:
--dangerously-skip-permissions(which cydo already passes) bypasses the permission checks, but not the trust layer, so tools still run while the allow-list and hooks stay ignored.projects[<dir>].hasTrustDialogAccepted: truekey in~/.claude.jsonnamed in the message above.Approach
When launching a claude session whose workspace
permission_policyis"allow", mark that task's working directory as a trusted project in~/.claude.json.Keying this off
permission_policy: "allow"is deliberate: a workspace configured to auto-allow every tool call is already an explicit statement that the operator trusts it, so reflecting that intent into Claude's trust store is consistent with the existing configuration rather than a separate trust knob. Firing at session launch against the exact directory the session runs in trusts precisely the projects tasks actually enter (including project-discovery subdirectories) and nothing speculative.Safety
The write is idempotent and atomic. It reads the existing config, returns immediately if the directory is already trusted, and otherwise merges the single flag in and writes via a temp file plus rename so the file is never left half-written. Because it only writes when the flag is genuinely missing, it becomes a no-op read after the first launch in a given project, which keeps the unavoidable window where it races Claude's own writes to
~/.claude.jsonas small as possible. Any failure is caught and logged; it never throws into session launch.Limitations
permission_policy == "allow"; a Djinja-expression policy that resolves to allow per-call won't trigger it, since the policy isn't reduced to a single value at the session level.workDirpath may not match what the sandboxedclaudesees. This targets the common case of unsandboxed allow/trusted workspaces.Test
A hermetic unit test (temp paths) covers the merge: the target directory becomes trusted, an unrelated key and an already-trusted sibling project both survive (merge, not clobber), and a second run is idempotent.