Trust dialog never shown when hasCompletedProjectOnboarding is true but projectOnboardingSeenCount is 0 — project-scope plugins silently never load
Summary
A project directory can reach a state where hasCompletedProjectOnboarding: true
but projectOnboardingSeenCount: 0 in ~/.claude.json. Onboarding is flagged
complete without ever having run, so the workspace trust dialog is never
presented for that directory. Because trust can only be granted through that
dialog, hasTrustDialogAccepted is permanently stuck at false.
Impact
Two failures, both silent:
- Project-scope plugins under
./.claude/skills/*never load. The only
signal is a wrapped warning at the very bottom of claude plugin list
("...was not trusted when plugins were scanned"). It is truncated in the
/reload-plugins output, so from the TUI the plugin simply doesn't exist.
.mcp.jsonserver approvals re-prompt on every launch. The answer is
written to .claude/settings.local.json
(enableAllProjectMcpServers: true, enabledMcpjsonServers: [...]), but a
project-scope file can't authorize itself in an untrusted workspace, so it is
re-asked and re-written indefinitely. This reads to the user as "settings
aren't saving."
No amount of relaunching or /reload-plugins recovers it. Reproduced in both
Warp and Ghostty, in fresh terminal windows.
Evidence
Affected directory:
{
"hasTrustDialogAccepted": false,
"hasCompletedProjectOnboarding": true,
"projectOnboardingSeenCount": 0
}
A healthy trusted directory, for contrast: true / true / 231.
A normal not-yet-accepted directory: false / null / 1.
The true + 0 combination is self-contradictory and appears to be the
discriminator. It occurs in 4 of 77 project entries in this one~/.claude.json, so it is not a one-off.
What I could not determine
The trigger that writes hasCompletedProjectOnboarding: true without
incrementing the seen-count. I suspect a non-interactive or child session
(-p, piped stdout, or a bridged/child session) marking onboarding complete on
a path where the trust dialog is skipped by design — but I did not reproduce
that write, so treat it as a hypothesis.
Expected
Either the trust dialog should be presented wheneverhasTrustDialogAccepted is false regardless of the onboarding flag, or a
non-interactive session should not be able to mark onboarding complete for a
directory it never showed the dialog for.
Workaround
Quit all Claude sessions first (several rewrite ~/.claude.json on exit and
clobber the edit), then:
jq '.projects["/path/to/project"].hasTrustDialogAccepted = true
| .projects["/path/to/project"].hasCompletedProjectOnboarding = false' \
~/.claude.json > ~/.claude.json.new && mv ~/.claude.json.new ~/.claude.json
After this, the project plugin loaded correctly
(/reload-plugins went from 11 plugins · 1 plugin LSP server to12 plugins · 4 plugin LSP servers).
Suggested diagnostic
claude doctor could flag hasTrustDialogAccepted: false combined withprojectOnboardingSeenCount: 0 — the state is invisible today unless you know
to read ~/.claude.json directly.
Environment
- Claude Code 2.1.217, native install (
~/.local/bin/claude) - macOS 15 (Darwin 25.5.0), arm64
- Terminals: Warp, Ghostty (both reproduce)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗