feat(claude): trust the project of a permission_policy "allow" task#5
Open
Antisophy wants to merge 1 commit into
Open
feat(claude): trust the project of a permission_policy "allow" task#5Antisophy wants to merge 1 commit into
Antisophy 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.