agentsclimarketplace

Sync claude permissions

Skill ada-ggf25/AI-Tools/global/claude/skills/sync-claude-permissions

A cross-device synced catalog for Claude and Codex skills, agents, and workflows.

Install
npx -y skills add ada-ggf25/AI-Tools --skill sync-claude-permissions

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Translates current-project Codex permission rules (.codex/rules/default.rules prefix_rule blocks only, not personal ~/.codex rules) into Claude Code permission entries (.claude/settings.local.json), computes the gap against already-present rules, and presents portable rules for per-rule approval grouped by category before writing. Global and project-agnostic. Trigger when the user says "sync claude permissions", "sync-claude-permissions", "port project codex rules to claude", "translate project codex permissions", "replicate project codex allow rules", or "bring project codex permissions into claude".

SKILL.md

7.1 KB, as published. Nobody here has run it

Sync Project Codex Permissions To Claude Code

Global, project-agnostic skill. Reads only the current project's .codex/rules/default.rules, translates prefix_rule(...) entries to Claude Code Bash(...) permission syntax, diffs against .claude/settings.local.json, and writes only the user-approved new entries. Every proposed rule requires explicit per-rule approval before any write.

This skill intentionally syncs project-local rules only. Do not read or fall back to ${CODEX_HOME:-~/.codex}/rules/default.rules: personal/global Codex rules may affect the active Codex session, but they are outside this project-local sync workflow.

Complements setup-permissions (which predicts rules from the stack) by operating on already-written project-local Codex rules rather than generating from scratch. Treat .codex/rules/default.rules as the source for this operation even when its rules were originally adapted from Claude Code settings.


Translation reference

Pattern → Claude rule

Reconstruct the longest unambiguous prefix from the pattern array:

Codex patternClaude rule(s)
["git", "status"]Bash(git status:*)
["git", ["status", "diff", "log"]]Bash(git status:*), Bash(git diff:*), Bash(git log:*)
["git", "-C", "/repo", ["status", "log"]]Bash(git -C /repo status:*), Bash(git -C /repo log:*)
["npm", "run", "test"]Bash(npm run test:*)
["./install.sh"]Bash(./install.sh:*)

When a pattern contains nested lists (one-of alternatives), expand each alternative into one Claude rule. If expansion would produce more than 8 rules from a single source entry, collapse to the common prefix and warn the user that the translation is broader.

Decision mapping

Codex decisionClaude target
"allow"permissions.allow
"deny"permissions.deny
"prompt"NOT ported — Claude Code's default for uncovered commands is already to prompt; no rule needed

Not portable

  • decision = "prompt" → list in "Deliberately NOT ported"; never add to allow or deny.
  • Absolute-path patterns (e.g. ["cp", "/home/user/...", "..."]) → flag as "manually review — contains absolute paths"; never auto-port.

Output notation

Always use Bash(prefix:*) colon notation (e.g. Bash(git status:*), never Bash(git status *)).


Procedure

1. Read source

Read .codex/rules/default.rules relative to the current working directory. If the file does not exist, report it and stop - do not create it and do not fall back to ${CODEX_HOME:-~/.codex}/rules/default.rules.

Parse all prefix_rule(...) blocks. A block spans from prefix_rule( to its matching ). Within each block extract:

  • pattern — the inline TOML array (may span multiple lines); parse it as a whole unit.
  • decision"allow", "deny", or "prompt".
  • justification — informational string; surface it in the approval prompt.

2. Read target

Read .claude/settings.local.json if it exists; if not, treat permissions.allow and permissions.deny as empty (the file will be created in step 5). Also peek at .claude/settings.json for already-present entries to avoid duplicates across both files, but write exclusively to .claude/settings.local.json.

Parse permissions.allow and permissions.deny arrays.

3. Compute gap

For each prefix_rule block:

  • Apply the translation rules above to get one or more candidate Claude rule strings.
  • Check if each candidate is already present in the target's allow/deny list.
  • Classify it as one of:
    • New — candidate not in target; will be proposed.
    • Already synced — candidate already present; skip silently.
    • Not portabledecision = "prompt", absolute-path pattern, or expansion > 8 entries (collapse case).

If every rule is either already synced or not portable, report "Already in sync — nothing to add." and stop.

4. Show the gap summary

Before asking for approval, display:

Rules to add      (N new)
  allow:
    - Bash(git status:*)     ← allows git status; does NOT allow git push or git reset
    ...
  deny:
    - Bash(rm:*)

Already synced    (M rules, skipped)
  - Bash(./install.sh:*)
  ...

Deliberately NOT ported
  - [git reset / checkout / push]   decision = "prompt" — already Claude Code default behavior
  - [cp /home/user/...]              absolute paths — flag for manual review

5. Propose per-rule approval

Use AskUserQuestion with multiSelect: true, grouping proposed rules by category (git / build-test / package-manager / project-scripts / other). For each rule show:

  • The proposed rule string (e.g. Bash(git status:*))
  • A one-line note from justification: "allows X; does NOT allow Y"

Also display the "Deliberately NOT ported" section as informational (not a question), so the user sees what was withheld and why.

If there is only one category, a single multiSelect question is fine.

6. Write approved rules

For each approved rule:

  • Append to permissions.allow or permissions.deny in .claude/settings.local.json.
  • If the file does not exist, create it with the structure:
    {
      "permissions": {
        "allow": [],
        "deny": []
      }
    }
    
  • If the file exists but lacks the permissions key, add it.
  • Deduplicate: never write a rule already present.
  • Preserve all existing entries and formatting as closely as possible.

Echo back exactly what was written and to which file.


Guardrails

  • Source is project-local and read-only. Read only the current project's .codex/rules/default.rules; never read personal ${CODEX_HOME:-~/.codex}/rules/default.rules as a fallback, and never modify the project-local source file.
  • Propose first, write after approval. Never auto-write any rule.
  • decision = "prompt" is always NOT ported. Surface it in "Deliberately NOT ported" with the note "already Claude Code default behavior (prompt); no rule needed." Never add it to allow or deny.
  • Absolute-path patterns are never auto-ported. Flag them for manual review; let the user decide whether a portable equivalent makes sense.
  • Write only to .claude/settings.local.json. Never touch .claude/settings.json, global ~/.claude/settings.json, or any Codex file.
  • Narrow notation only. Every Bash(...) rule must use prefix:* colon notation.
  • Merge, never clobber. Preserve existing entries; deduplicate; never overwrite the file from scratch.
  • Stop gracefully if the source file is missing or the gap is empty.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.