cc
Skill52 starsChanged 49 days agoMITView on GitHub
Sync cc-settings with Claude Code and Codex upstreams, update a local install, or migrate a project's CLAUDE.md to AGENTS.md. Triggers "sync with claude code", "update cc-settings", "migrate to agents.md".
- Commits and pushes
In this repository27 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .claude/AGENTS.mdAGENTS.md
- auditSkill
- autoresearchSkill
- buildSkill
- case-studySkill
- codexSkill
- componentSkill
- context-docSkill
- dr-initSkill
- dr-reviewSkill
- fixSkill
- freezeSkill
- handoffSkill
- harvestSkill
- hookSkill
- orchestrateSkill
- poke-holesSkill
- proof-of-workSkill
- refactorSkill
- retroSkill
- review-batchSkill
- share-learningSkill
- shipSkill
- storiesSkill
- triageSkill
- zero-tech-debtSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
16 rules. About 0 are common, 8 are distinctive, and 8 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
8
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 26
Always run from the cc-settings repo root.
- Distinctive: line 34
If the tree is dirty, ask the user to commit or stash first.
- Distinctive: line 57
If nothing drifts, tell the user "already in sync at Claude Code v<X>, Codex v<Y>, Codex app changelog through <date>" and end.
- Distinctive: line 72
Do not paraphrase. Quote the upstream bullets verbatim — the user needs to see exactly what was said upstream to validate your …
- Distinctive: line 158
Write a markdown table to the chat:
- Distinctive: line 186
Do not edit before approval.
- Very specific: line 195
After each schema edit, also update upstream/claude-code-manifest.json (knownSettingsKeys, knownHookTypes, knownEnvVars) — the scanner uses …
- Distinctive: line 235
If any fail: fix before moving on.
- Very specific: line 246
Before the commit, spawn the linear agent with event start, the repo, the branch and a one-line summary of the sync, and wait for its issue …
- Very specific: line 285
Never treat ${CODEX_HOME:-$HOME/.codex}/darkroom/source as a checkout.
- Very specific: line 290
Read repo_path from the selected product sentinel first.
- Distinctive: line 354
If every selected sentinel already matches, report "already up to date" and stop.
- Very specific: line 435
Run it from the project root.
- Distinctive: line 448
Read every file found. Then classify:
- Very specific: line 489
Start a new Claude Code session in the project (or claude -p 'what are your project instructions?') and look for the line no CLAUDE.md …
- Very specific: line 497
Commit as chore: move CLAUDE.md into AGENTS.md on the project's usual branch flow (a PR through /ship.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
cc — cc-settings management
Three-mode skill: sync keeps the repo current with the Claude Code and
Codex CLI upstreams (maintainer task); update refreshes the active Claude
Code, Codex, or combined local install (everyone); migrate moves a
project's CLAUDE.md into AGENTS.md so every coding agent reads one file.
Mode: sync
Audit cc-settings against the Claude Code changelog, the Codex CLI release notes, and the Codex app and IDE extension changelog (schemas, config, hooks, agents, docs, Codex installer surfaces); identify features to adopt and native duplication to remove; stops for approval.
This is run on a weekly cadence. The mechanical parts are scripted; the judgment calls (which features to adopt, what counts as duplication) require human review at the gate.
Before you start
Always run from the cc-settings repo root. If you're not there, ask the user
where it is — don't guess.
pwd # should end in /cc-settings
git status # tree must be clean before startingIf the tree is dirty, ask the user to commit or stash first. Sync work needs a clean baseline so the diff is reviewable.
Phase 1 — Detect drift
bun run upstream:scanThis compares upstream/claude-code-manifest.json against the live
@anthropic-ai/claude-code npm version and upstream/codex-manifest.json
against the live @openai/codex npm version. Each upstream has two outcomes:
- No drift — manifest matches live. Nothing to sync for that upstream.
- Drift detected — capture both versions. Format:
manifest=A → live=B.
The Codex desktop app and IDE extension ship on their own version line
(Codex app 26.x) with no npm package. The scan reads their changelog feed
instead and reports every non-iOS entry dated after appChangelogLastScan as
codex app changelog: N entries after <date>. If the feed is unreachable it
prints <unknown — feed unreachable>; say so in the plan rather than treating
it as no drift.
If nothing drifts, tell the user "already in sync at Claude Code v<X>, Codex
v<Y>, Codex app changelog through <date>" and end. If only some sources drift,
run the remaining phases for those alone and say which in the plan.
Phase 2 — Fetch the upstream changelog
Fetch the official changelog and extract entries between the manifest version (exclusive) and the live version (inclusive):
WebFetch url: https://raw.githubusercontent.com/anthropics/claude-code/main/CHANGELOG.md
prompt: Extract entries for versions <A+1> through <B> verbatim. List each
version's bullet points exactly as written.Do not paraphrase. Quote the upstream bullets verbatim — the user needs to see exactly what was said upstream to validate your categorization.
Codex
Codex publishes release notes per GitHub release, not a changelog file. Stable
releases are tagged rust-v<X>; alpha tags and Python SDK tags are not
tracked. List the stable versions after the manifest version, then read each
release body verbatim:
gh release list -R openai/codex --exclude-pre-releases --limit 20 \
| grep -E '^[0-9]+\.[0-9]+\.[0-9]+\s' | awk '{print $1}'
gh release view rust-v<X> -R openai/codex --json body --jq '.body'Codex app and IDE extension
Members who install cc-settings for Codex may run it in the desktop app or the
IDE extension instead of the CLI. Both read the same AGENTS.md, skills,
plugins, hooks and config.toml, and their release notes live only on the
shared changelog (the CLI's rust-v notes do not repeat them):
bun src/upstream/scan.ts --codex-app-entriesThis prints each entry from the scan's list verbatim, iOS releases already
dropped. Triage them like CLI notes; the ones that matter name AGENTS.md,
skills, plugins, hooks, config.toml, sandboxing, or a model the bridge pins.
A ChatGPT-only entry is a SKIP.
Phase 3 — Cross-reference cc-settings
For each upstream change, decide which bucket it falls into. Read these files to inform the decision (use parallel tool calls):
| Bucket | What to check |
| Settings keys | src/schemas/settings.ts (zod schema, strict — drift fails parse) |
| Hook events / types | src/schemas/hooks.ts (discriminated union) |
| MCP fields | src/schemas/mcp.ts (shared mcpCommon for cross-transport fields) |
| Env vars | upstream/claude-code-manifest.json knownEnvVars, docs/settings-reference.md env table, config/10-core.json env block |
| Hook wiring | config/40-hooks.json, src/hooks/, src/scripts/ |
| Statusline | src/hooks/statusline.ts (Payload type) |
| Agent frontmatter | agents/*.md (currently uses tools, disallowedTools, maxTurns, permissionMode, effort, isolation, hooks, mcpServers, initialPrompt) |
| Slash commands | docs/skills.md, skills/*/SKILL.md triggers |
| User-facing docs | MANUAL.md, CLAUDE-FULL.md, docs/settings-reference.md, docs/hooks-reference.md |
For Codex changes, cross-reference these surfaces instead. There is no zod
schema for any of them; upstream/codex-manifest.json knownConfigSurfaces
lists what the installer writes or reads so a release note that names one is
easy to spot.
| Bucket | What to check |
Native agents (agents/*.toml fields) | src/lib/codex-native-agents.ts, codex/agents/ |
Command policy (rules/*.rules) | codex/rules/darkroom.rules |
| Plugin manifest and hooks | plugin.json, mcp.json, hooks/hooks.json (installed as $CODEX_HOME/hooks.json), src/lib/codex-runtime-manifests.ts |
config.toml keys the installer reads | src/lib/codex-install-state.ts, src/lib/codex-skill-budget.ts |
| Skill loading and budgets | src/lib/lint-skills.ts, docs/codex.md "skill descriptions were shortened" |
Bridge (codex exec, codex review, model pins) | src/lib/claude-bridge.ts, codex-run.ts, docs/codex-bridge.md |
| User-facing docs | docs/codex.md, codex/AGENTS.append.md |
| App or IDE-only behavior (a surface that loads differently outside the CLI) | docs/codex.md (the IDE extension and plugins note) |
Bucket each change as one of:
- ADOPT — new upstream feature worth taking. List the exact files to edit.
- DEDUPE — native feature that now overlaps with cc-settings code. List the files/lines to delete. Look hardest for these — they're the cleanup wins.
- DOCS-ONLY — purely a documentation update (e.g. slash command renamed, table needs refresh).
- SKIP — not relevant (Windows-only, enterprise-only, fixes a bug we didn't have, etc.). Briefly say why.
Common DEDUPE patterns to look for
Watch for these patterns:
- A new built-in hook event subsumes a custom hook script.
- A new tool replaces a wrapper we maintain.
- A new frontmatter field replaces a script-driven workaround.
- A new env var replaces a custom env-var dance.
Phase 4 — Stop. Present the plan.
Write a markdown table to the chat:
## Claude Code v<A> → v<B>, Codex v<C> → v<D>, Codex app changelog <date> → <today> sync plan
### Adopt
| Change | Files | Notes |
|---|---|---|
| ... | ... | ... |
### Dedupe
| Native feature | What to remove | Why redundant |
|---|---|---|
### Docs-only
| Change | File |
|---|---|
### Skip
| Change | Reason |
|---|---|Then ask the user one question: which rows do they approve?
- "Approve all" → continue with everything.
- "Approve subset" → user names rows.
- "Reject" → end the skill, no edits.
Do not edit before approval.
Phase 5 — Execute approved changes
For approved adoptions, edit the files directly. Schemas first (they're the
contract), then config, then docs. Codex adoptions have no schema step: edit
the installer surface, then docs/codex.md. For deduptions, delete the orphaned code
and any tests that asserted on it.
After each schema edit, also update upstream/claude-code-manifest.json
(knownSettingsKeys, knownHookTypes, knownEnvVars) — the scanner uses
this as the source of truth.
Phase 6 — Manifest bump + version bump + CHANGELOG
upstream/claude-code-manifest.json
- claudeCodeVersion: "<B>"
- lastScan: <today ISO>
- notes: append one entry summarizing the window (adopted, docs-only, skipped)
upstream/codex-manifest.json
- codexVersion: "<D>"
- lastScan: <today ISO>
- appChangelogLastScan: <today YYYY-MM-DD>
- notes: append one entry; add any new surface to knownConfigSurfaces
package.json, .claude-plugin/plugin.json, plugin.json (Codex), src/setup.ts (VERSION)
- bump all three together (minor for new features, patch for fixes-only)
CHANGELOG.md
- Prepend new section: "## [<new-version>] — <today YYYY-MM-DD>"CHANGELOG entry structure (mirror the latest sync entries):
- One-line summary.
- Adopted: bullet per feature. State the upstream version, the file(s) touched, and a one-sentence "why this matters".
- Deletions / Native-now-redundant: bullet per removed thing. State what replaced it and the upstream version.
- Files changed: flat list, one per line.
Phase 7 — Validate
bun run typecheck
bun test
bun run upstream:scan # should now show "no drift detected" for all three sources
bun run compose | head # spot-check that new fields surface in settings.jsonIf any fail: fix before moving on. Tests must pass.
Phase 8 — Commit + push
git add <changed paths>
git commit -F "$MSG_FILE" -- <changed paths>
git push -u origin HEAD
gh pr create --base main --title "<commit subject> (<Linear ID>)" --body-file "$BODY_FILE"Before the commit, spawn the linear agent with event start, the repo, the
branch and a one-line summary of the sync, and wait for its issue ID: every
sync PR carries a Linear issue, created without asking when none exists. Put
the ID at the end of the PR title and Fixes <ID> on its own line in the
body. After gh pr create, spawn linear again with event pr-opened and
the PR URL, and do not wait for it. Report the issue link with the PR link.
With no Linear MCP server connected, follow the ship skill's "Linear issue"
step yourself. The linear-gate hook blocks a PR without an issue in a mapped
repo.
$MSG_FILE holds feat(v<new-version>): sync with Claude Code v<B> and Codex v<D>,
a one-paragraph summary, and Adopted / Deletions lists. Commit and PR mechanics
follow ~/.claude/rules/git.md; read it first if present.
Work on a branch: main rejects direct pushes and requires the org
ci-gate workflow, which runs only on a PR, plus one approving review. Merge
the PR once both are in; darky/review is not required. Use conventional commit prefix feat(v<X.Y.Z>): so the
version stands out in git log. Do not push if anything in Phase 7 is failing.
What this mode does NOT do
- It does not edit user-installed
~/.claude/settings.json. cc-settings is the source — users get the changes by re-runningsetup.sh. - It does not run on a schedule. A cron could only bump the version number,
never triage the changelog, so
bun run upstream:scanis the manual drift detector and this skill is the only sync path. - It does not bump dependencies. That's a separate concern.
Mode: update
Pull the latest cc-settings into the active host. Choose the target before looking for a checkout:
- An explicit request for both products selects
both. - A standalone Codex session selects
codex. - Otherwise select
claude.
Never treat ${CODEX_HOME:-$HOME/.codex}/darkroom/source as a checkout. It is
a copied, non-git runtime allowlist and must never be pulled.
Phase 1 — Locate the real working repo
Read repo_path from the selected product sentinel first. For both, try the
Codex sentinel before the Claude sentinel. Then try known checkout paths. Every
candidate must contain .git and have the expected origin.
CODEX_ROOT="${CODEX_HOME:-$HOME/.codex}"
TARGET="codex" # use claude or both according to the host/explicit request above
CODEX_SENTINEL="$CODEX_ROOT/.cc-settings-version"
CLAUDE_SENTINEL="$HOME/.claude/.cc-settings-version"
CODEX_RUNTIME="$CODEX_ROOT/darkroom/source"
candidate_from_sentinel() {
jq -r '.repo_path // empty' "$1" 2>/dev/null
}
CANDIDATES=()
if [ "$TARGET" = "codex" ] || [ "$TARGET" = "both" ]; then
CANDIDATES+=("$(candidate_from_sentinel "$CODEX_SENTINEL")")
fi
if [ "$TARGET" = "claude" ] || [ "$TARGET" = "both" ]; then
CANDIDATES+=("$(candidate_from_sentinel "$CLAUDE_SENTINEL")")
fi
CANDIDATES+=("$CODEX_ROOT/cc-settings" "$HOME/.claude/cc-settings" "$PWD")
CC_REPO=""
for candidate in "${CANDIDATES[@]}"; do
[ -n "$candidate" ] || continue
[ "$candidate" != "$CODEX_RUNTIME" ] || continue
[ -d "$candidate/.git" ] || continue
ORIGIN=$(git -C "$candidate" remote get-url origin 2>/dev/null) || continue
NORMALIZED_ORIGIN=$(printf '%s' "$ORIGIN" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//; s#^git@github[.]com:#https://github.com/#; s#^ssh://git@github[.]com/#https://github.com/#; s:/+$::; s:[.]git$::')
[ "$NORMALIZED_ORIGIN" = "https://github.com/darkroomengineering/cc-settings" ] || continue
CC_REPO="$candidate"
break
done
if [ -z "$CC_REPO" ]; then
echo "No real cc-settings git checkout was found. Provide its path; the Codex runtime copy cannot be updated with git pull."
exit 1
fiFail closed and ask for the real checkout path if none passes. Do not clone or guess a path automatically.
Phase 2 — Detect drift
case "$TARGET" in
codex) INSTALLED=$(jq -r '.version // empty' "$CODEX_SENTINEL" 2>/dev/null) ;;
claude) INSTALLED=$(jq -r '.version // empty' "$CLAUDE_SENTINEL" 2>/dev/null) ;;
both)
CODEX_INSTALLED=$(jq -r '.version // empty' "$CODEX_SENTINEL" 2>/dev/null)
CLAUDE_INSTALLED=$(jq -r '.version // empty' "$CLAUDE_SENTINEL" 2>/dev/null)
INSTALLED="codex=$CODEX_INSTALLED claude=$CLAUDE_INSTALLED"
;;
esac
git -C "$CC_REPO" fetch --quiet origin main
LATEST=$(git -C "$CC_REPO" show origin/main:src/setup.ts | grep -E '^const VERSION' | sed -E 's/.*"([0-9.]+)".*/\1/')
echo "Installed: $INSTALLED"
echo "Latest: $LATEST"If every selected sentinel already matches, report "already up to date" and stop. If an installed version is newer than latest, surface the discrepancy and ask before changing anything.
Phase 3 — Render what changed
git -C "$CC_REPO" log --oneline "HEAD..origin/main" | head -20
git -C "$CC_REPO" show origin/main:CHANGELOG.md | sed -n '1,160p'Display the relevant commits and changelog entries. Stop and wait for confirmation before applying.
Phase 4 — Pre-flight safety
if ! git -C "$CC_REPO" diff --quiet || ! git -C "$CC_REPO" diff --cached --quiet; then
git -C "$CC_REPO" status --short
echo "Commit, stash, or discard the checkout changes before updating."
exit 1
fi
BRANCH=$(git -C "$CC_REPO" branch --show-current)
[ "$BRANCH" = "main" ] || {
echo "The checkout is on '$BRANCH', not main. Switch first or update manually."
exit 1
}Phase 5 — Apply
For Claude, first take the snapshot in references/update-restart.md.
git -C "$CC_REPO" pull --ff-only origin main
bash "$CC_REPO/setup.sh" --target="$TARGET"Claude-only update uses --target=claude; standalone Codex uses
--target=codex; an explicit combined update uses --target=both. Add
--interactive only when the user asks to review the merge.
Phase 6 — Verify, then restart only when needed
[ "$TARGET" = "claude" ] || test "$(jq -r .version "$CODEX_SENTINEL")" = "$LATEST"
[ "$TARGET" = "codex" ] || test "$(jq -r .version "$CLAUDE_SENTINEL")" = "$LATEST"For Codex, tell the user to restart Codex and, if plugin files changed, to
confirm the new hook commands in /hooks. For Claude, finish with
references/update-restart.md: restart only when launch-time files changed,
otherwise carry on. A combined update needs both restarts and sentinel checks.
Rollback
Rollback names the same target explicitly:
bash "$CC_REPO/setup.sh" --target=codex --rollback # Codex
bash "$CC_REPO/setup.sh" --target=claude --rollback # Claude Code
bash "$CC_REPO/setup.sh" --target=both --rollback # explicit combined installTo install an older release, check out that release in the real working repo
first, then run setup.sh with the selected target. Never modify or pull the
Codex runtime copy directly.
Mode: migrate
Move a project's CLAUDE.md into AGENTS.md. Since Claude Code 2.1.277 a
project with no CLAUDE.md gets its AGENTS.md read natively as project
instructions, framed exactly like a CLAUDE.md, with .claude/rules/ still
loading alongside. Codex, Cursor, and Copilot already read AGENTS.md. Keeping
a CLAUDE.md around means Claude Code ignores the AGENTS.md and the two
files drift. The SessionStart banner prints a one-line hint whenever a
CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md exists in the project
root; this mode is the action behind that hint.
Run it from the project root. It touches only that project's files, never
~/.claude/CLAUDE.md, which has no AGENTS.md fallback and stays as installed.
Phase 1 — Inventory
git rev-parse --show-toplevel
for f in CLAUDE.md .claude/CLAUDE.md CLAUDE.local.md AGENTS.md .claude/AGENTS.md; do
[ -f "$f" ] && printf '%s\t%s bytes\n' "$f" "$(wc -c < "$f")"
done
grep -n '^@' CLAUDE.md .claude/CLAUDE.md 2>/dev/nullRead every file found. Then classify:
- Rename — a
CLAUDE.mdand noAGENTS.md. The whole file moves. - Merge — both exist. Read both; the content that is only in
CLAUDE.mdgoes intoAGENTS.mdunder a heading that names its topic (never a heading called "From CLAUDE.md"), duplicated guidance is dropped, and a conflict is listed for the user instead of resolved silently. - Already imported —
CLAUDE.mdis only an@AGENTS.mdline (plus blank lines). Delete it; native reading makes the import redundant. - Leave —
CLAUDE.local.mdis personal and uncommitted. Report it, do not move it, and say that its presence alone blocks the native read; the user can set Project instructions toclaude-md-and-agents-mdin/configor fold the file into their own notes.
Claude-only content (output style, /effort, hook, or subagent notes) still
goes to AGENTS.md: other agents ignore what they do not understand, and one
file is the point. Only when the user objects, keep a CLAUDE.md holding
@AGENTS.md followed by the Claude-only lines.
Phase 2 — Show the plan and stop
Print the classification, the target file, the byte counts, and, for a merge, the sections that will move and any conflicts. Wait for approval. Do not edit before it.
Phase 3 — Apply
git mv CLAUDE.md AGENTS.md # rename case
# merge case: edit AGENTS.md, then
git rm CLAUDE.md
# .claude/CLAUDE.md follows the same two paths into .claude/AGENTS.mdThen fix references: grep -rn 'CLAUDE\.md' --include='*.md' --include='*.json'
--include='*.ts' --include='*.yml' . excluding node_modules. Update paths
that pointed at the moved file (README setup notes, CI steps that cat it,
claudeMdExcludes patterns). Leave mentions of ~/.claude/CLAUDE.md alone.
Phase 4 — Verify
Start a new Claude Code session in the project (or claude -p 'what are your
project instructions?') and look for the line
no CLAUDE.md found; AGENTS.md loaded: <path>. /memory and /context do not
list an AGENTS.md read this way, so that line is the check. If the line is
missing, the session is one that cannot load AGENTS.md (disableAllHooks,
allowManagedHooksOnly, or the first session after the upgrade); say so and
offer the one-line CLAUDE.md that holds @AGENTS.md as the fallback.
Commit as chore: move CLAUDE.md into AGENTS.md on the project's usual branch
flow (a PR through /ship; cc-settings main also takes changes only through a PR).
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

