Skip to content

Codex skill discovery, permission posture sync, and the docs that were not telling the truth - #47

Merged
matteopasseri407 merged 6 commits into
mainfrom
feat/codex-skills-and-permissions
Jul 30, 2026
Merged

Codex skill discovery, permission posture sync, and the docs that were not telling the truth#47
matteopasseri407 merged 6 commits into
mainfrom
feat/codex-skills-and-permissions

Conversation

@matteopasseri407

Copy link
Copy Markdown
Owner

Six signed commits. Two features, three corrections found by reviewing them, one release chore.

Codex could never see a single skill

skills-sync.py assumed Codex discovered skills through the shared ~/.agents/skills root. It has never read it: verified against the shipped 0.146.0 binary, which contains no reference to that path nor to ~/.claude/skills, and whose only skill root is $CODEX_HOME/skills. A declared targets: [codex] therefore produced zero discoverable skills, silently, while a comment asserted the opposite.

Codex now gets a native per-skill view like Claude and Antigravity. Measured on a real install: skills/list on the Codex app-server went from 0 vault skills to 14. Bodies stay lazy — Codex loads name and description and opens SKILL.md only when the skill is used.

The shipped skills.manifest.yaml.example carried the same defect in its data: none of its eight starter entries declared the target, so a fresh install had none of the commands the README advertises. Fixed, along with the legend that repeated the false premise.

migrate_legacy_views also had to learn that a Codex view is managed, or --migrate-legacy would remove every view the same run had just created.

A permission posture that can follow you between machines

New claude_permissions phase. It reads a permissions manifest from your private vault and applies the posture plus its guardrail hooks to Claude's settings, on every machine.

The engine ships the mechanism only. There is no permissions/ directory in this repository and no scaffolding anywhere in the installer: without a manifest in your own vault the phase writes nothing at all, so no installation inherits anyone else's posture.

A PreToolUse hook rather than a deny list, deliberately: under bypassPermissions the permission engine is skipped entirely and deny rules may never be consulted, while the hook still runs. That makes it the only guardrail that holds in the posture that needs one.

The first version of this phase got that wrong in a way worth naming. It claimed in three places to refuse rather than half-apply, but a malformed hooks block only logged and carried on — writing bypassPermissions while the guardrail stayed unregistered. Prompts off, nothing watching: exactly the state the phase exists to prevent. Hooks are now registered first and the posture only after, with any anomaly refusing before anything reaches disk. validate_claude_settings also covers PreToolUse now, the one event this phase writes and the one it never inspected.

Documentation that was not telling the truth

agent-sync writes a hidden google-chrome.desktop that shadows the distribution's Chrome launcher, so existing dock icons reach the CDP-enabled wrapper. That is load-bearing — a plain Chrome started from the dock wins the first-process race with no CDP port and the shared-browser lane stops working — but it was undeclared, and the function's own docstring described the opposite. The behaviour is unchanged; it is now documented in docs/what-gets-written.md and removed by docs/uninstall.md, which also documents the two distinct backup naming conventions actually in use.

Also

test_apply_is_idempotent failed on main too, on wall-clock timing alone: the Firecrawl search-health cache carries a TTL, so a run after it expires writes the file and sometimes creates its parents only on the second pass.

Verification

772 passed, 32 skipped, locally on Ubuntu 26.04. Leak-scan clean. Every commit signed.

Windows is not verified: this needs agent-doctor.ps1 -Strict on the physical desktop before the rollout is closed.

matteopasseri407 and others added 6 commits July 30, 2026 17:55
Codex reads only $CODEX_HOME/skills. Verified against the shipped 0.146.0
binary: the image contains no reference to ~/.agents/skills or ~/.claude/skills
(it knows ~/.agents/plugins, a different mechanism). The previous comment
claimed Codex discovered core skills through the shared root, so a declared
targets: [codex] silently produced zero discoverable skills.

Also teaches migrate_legacy_views that a Codex view is managed, otherwise
--migrate-legacy would remove every view the same run had just created.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
Adds the claude_permissions phase: it reads a permissions manifest from the
private vault instance and applies posture plus guardrail hooks to Claude's
settings. The engine ships the mechanism only; with no manifest the phase is
a complete no-op, so no end user inherits anyone else's permission posture.

A PreToolUse hook rather than a deny list: under bypassPermissions the
permission engine is skipped entirely and deny rules may never be consulted,
while the hook still runs. The phase refuses rather than half-applying, so a
machine is never left with prompts disabled and its guardrail missing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
…rdrail

The phase claimed in three places that it refuses rather than half-applying,
but a malformed hooks block only logged and carried on: it then wrote
bypassPermissions while the guardrail stayed unregistered -- prompts off and
nothing watching, the exact state this phase exists to prevent.

Hooks are registered first and the posture only after, with any anomaly
refusing the whole phase before anything reaches disk. validate_claude_settings
now also covers PreToolUse, the one event this phase writes and never
inspected. Three tests cover the malformed shapes.

Also corrects the browser desktop-entry docstring in the same file: it
described only the restraint (not taking over the default browser) and stayed
silent about the hidden google-chrome.desktop that shadows the distribution
launcher. The behaviour is load-bearing and unchanged; the description was
not accurate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
Every starter entry in skills.manifest.yaml.example declared
targets: [claude, antigravity, opencode]. A fresh install starting from it had
zero discoverable commands on Codex: the regression fixed in code was still
alive in the shipped data.

Adds the codex target to the eight entries and rewrites the legend, which
repeated the same false premise (that Codex reads the shared ~/.agents/skills
root). The module docstring of skills-sync.py carried the original wording and
is corrected too. RUNTIME[codex] now honors $CODEX_HOME instead of hardcoding
~/.codex, which the comment right above it already claimed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
…tency test

what-gets-written.md promised to list every file written outside the repo and
omitted ~/.claude/settings.json and both Linux desktop entries, including the
hidden google-chrome.desktop that shadows the distribution launcher. It is
per-user and reversible, but an undeclared change to what an existing dock
icon launches is the kind of thing that costs trust. uninstall.md now removes
both and documents the two distinct backup naming conventions in use.

test_apply_is_idempotent failed on main as well, on wall-clock timing alone:
the Firecrawl search-health cache has a TTL, so a run after it expires writes
the file and sometimes creates its parents only on the second pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
The two features on this branch had no changelog entry, including one that can
disable Claude's permission prompts. Bumps the engine version accordingly.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QQ3c8aM5hzkEzrXe7sAaHy
@matteopasseri407
matteopasseri407 merged commit 045b00c into main Jul 30, 2026
9 checks passed
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.

1 participant