Skip to content

feat(claude): trust the project of a permission_policy "allow" task - #5

Open
Antisophy wants to merge 1 commit into
CyberShadow:masterfrom
Antisophy:feat/trust-allow-workspaces
Open

feat(claude): trust the project of a permission_policy "allow" task#5
Antisophy wants to merge 1 commit into
CyberShadow:masterfrom
Antisophy:feat/trust-allow-workspaces

Conversation

@Antisophy

Copy link
Copy Markdown
Contributor

Problem

A recent Claude Code version added a per-workspace "trust" gate. When claude runs 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's settings.local.json permissions.allow entries (and its project hooks), printing:

Ignoring 31 permissions.allow entries from .claude/settings.local.json: this workspace has not been trusted. Run Claude Code interactively here once and accept the trust dialog, or set projects["/path/to/workspace"].hasTrustDialogAccepted: true in ~/.claude.json.

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.
  • There is no CLI flag to grant trust. The only non-interactive mechanism Claude documents is the projects[<dir>].hasTrustDialogAccepted: true key in ~/.claude.json named in the message above.
  • Trust is keyed per-directory and is not hierarchical: trusting a parent directory does not trust its children, so a workspace whose tasks run in several project directories needs each of them trusted independently.

Approach

When launching a claude session whose workspace permission_policy is "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.json as small as possible. Any failure is caught and logged; it never throws into session launch.

Limitations

  • It keys off the literal 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.
  • For a sandboxed workspace whose HOME or paths are remapped, the host-side write and the workDir path may not match what the sandboxed claude sees. This targets the common case of unsandboxed allow/trusted workspaces.
  • Claude-only; Codex and Copilot have no equivalent gate.

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.

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.
@CyberShadow

Copy link
Copy Markdown
Owner

To be honest I don't have a good feeling about this. It crosses a line that we probably shouldn't cross. This:

  • edits Claude Code's configuration
  • does so without the user's consent
  • edits security sensitive settings
  • makes a security-relevant statement without actually verifying that it's true

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?

@Antisophy

Antisophy commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

The configuration with which this manifests is when permission_policy is "allow", which is when the user has explicitly granted the agent trust. The user consents by performing that configuration.

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.

@CyberShadow

Copy link
Copy Markdown
Owner

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.

The configuration with which this manifests is when permission_policy is "allow", which is when the user has explicitly granted the agent trust. The user consents by performing that configuration.

I don't understand the causality here. permission_policy is a CyDo setting; how does it affect Claude Code behavior in a way that makes it ask this per-directory permission prompt? Could this change be accompanied by an e2e test which demonstrates the problem?

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.

2 participants