sync-live-config
Judge and propagate drift between this repo's .claude/.codex/hermes content and live agent-config directories (this machine's ~/.claude, ~/.codex, ~/.hermes, and optionally remote hosts over SSH). Use when a fix may have been committed to this repo but not reached the live harness, or vice versa.
- License 许可
- MIT
- 最近更新
- 2026-11-11
- Stars
- ★ 6
- Forks
- 0
01 前言 Front Matter
- name
- sync-live-config
- description
- Judge and propagate drift between this repo's .claude/.codex/hermes content and live agent-config directories (this machine's ~/.claude, ~/.codex, ~/.hermes, and optionally remote hosts over SSH). Use when a fix may have been committed to this repo but not reached the live harness, or vice versa.
03 SKILL.md 正文
Sync live config
This repo is normally a downstream export of live agent config — usually
~/.claude/ is the source of truth and the export script
(~/.claude/commands/exportcommands.sh) pushes it here. But
that direction isn't guaranteed: a fix can land straight in this repo and
never flow back, or the live side can move on independently after the last
export. When both contain useful work, reconcile semantics in the canonical
source before choosing a propagation direction.
The script never decides direction. You do. scripts/sync_live_config.py
has two subcommands:
report [--full] [--remote HOST]... [--json] [--remote-only]— gathers evidence only, writes nothing. For every scoped file:new(missing live),modified, orok, plus the repo's last commit touching that path, and — if the live path turns out to live inside its own distinct git repo (e.g.~/.hermesis its own checkout of a separate harness repository) — that repo's last commit on the same path, plus a capped unified diff for small text files. The snippet is a discovery aid, not complete review evidence: read both full files and create a complete diff before deciding. It also reports alive_onlystatus: files present live but absent from the repo's tracked scope, which a repo-only file scan would otherwise never see (this is the exact shape of thehermes/skillsrename/delete drift below). Remote targets get the same per-file commit/diff enrichment as local and the samelive_onlydirectory walk. A remote path with a symlinked component anywhere in it (leaf or parent directory) reports statussymlinkinstead, with hash/size/ commit/diff all withheld — see "Remote targets" for why.apply --direction {repo-to-live,live-to-repo} --paths PATH [PATH ...] [--remote HOST] [--dry-run]— mechanically copies exactly the paths you name, in exactly the direction you name.--dry-runpreviews the whole decision without writing anything: per path it prints the exact source and destination absolutes, whether the destination would beCREATEd,OVERWRITEn, is alreadySAME, or why it wouldFAIL, with full hashes when available (dst=missingfor creates) — and exits non-zero if any path would fail validation, so it doubles as a preflight. Reach for it before everyapply, especially a multi-path one. It refuses--remoterather than silently previewing only the local half. No inference, no batch-wide default. Every path is validated to resolve inside one of the allowed roots (.claude/,.codex/hooks/,hermes/skills/and their live counterparts) before anything is touched — traversal, absolute paths, and symlink escapes are rejected, since the paths applied here come from your own judgment calls and should be checked like any other trust boundary.
Default vs full scope
- Default: the README's
### Highlighted skills · left/right shift strategytable (currentlysuperpowers-quick,advice,web-advice,redgreen,4layer,evidence-review,harness-engineering), parsed live from README.md — not a hardcoded, driftable list — plus any command dispatcher.mdthat references one of those skills. --full: every tracked file under.claude/,.codex/hooks/,hermes/skills/. Expect this to surface a lot more — go per-directory first (see below), don't try to judge thousands of individual files. Runtime/state subtrees (projects/,state/,venvs/,node_modules/,plugins/, session and history dirs — seeRUNTIME_DIRS) are pruned during the walk: they are not syncable config, and~/.claude/projectsalone is ~72k files. Commit lookups are batched once per enclosing repo, so a full report is minutes, not a hang. A run over ~3.5k tracked files yields ~5klive_onlyrows; judge those per-directory, never row by row.
Protocol — this is where the judgment happens
-
Gather evidence, not conclusions.
python3 scripts/sync_live_config.py report --json [--full] [--remote HOST]Read the JSON yourself. Do not skip straight to
apply. -
Read the complete scoped source before judging drift.
diff_snippetis capped and cannot establish that omitted parts agree. Re-pin the repository commit and live target, read the full contents of each changed file, compare complete diffs, and inspect linked companion files and live-only files in the same scope. Use hashes as well as text; report filters and greps are only prefilters. -
Reconcile meaning before choosing direction. For each file or tightly related group, record which semantic units to keep, adapt or reject and why. Preserve useful valid requirements from both copies. Do not default to the repository or live copy, concatenate conflicting prose, or infer authority from mtime or commit recency. Resolve conflicts through the active instruction hierarchy and each rule’s declared scope and owner; preserve repository-specific requirements within their domain. A canonical location establishes edit ownership, not that useful installed changes are obsolete. Commit history and
live_repo_rootare freshness evidence, never authority by themselves. Inspect scoped live-only files before deciding whether they are intentional, renamed or disposable. When the hierarchy resolves a conflict, make the smallest coherent best-of-both edit in the canonical repository source before propagating it. Escalate only a genuine unresolved owner, access or scope decision; state the exact conflict and attempted routes. Asymlinkrow is not a direction decision: inspect its target owner, bytes and history read-only, retaining the automatic apply refusal unless a separately verified canonical target is handled through an authorized diff-first decision. -
Account for report states per path.
okneeds no action. Fornewormodified, inspect the full contents and relevant history. A missing live path usually favors repo→live only after checking that the feature belongs on that host. An independentlive_repo_rootcalls for particular care but does not decide direction. Alive_onlyfile has no repository history; determine whether it is intentional, a rename or residue from its contents and owner. Test caches and.pytest_cache/artifacts are prefiltered, but inspect other scoped files. -
hermes/skills/and.claude/skills_archive/are known inversion risks (confirmed 2026-09-06: this repo'shermes/skills/snapshot traced entirely to a single stale 2026-08-01exportcommands.shpush, while live~/.hermes— its own actively-committed repo — had moved on for 5+ weeks; a blind repo→live--fullthere would have resurrected already-renamed/deleted content). For any diff under these paths: checklive_repo_root/live_last_commitfirst, and default to recommending a freshexportcommands.shrun (live→repo) over silently pushing the old snapshot down, unless the evidence clearly says otherwise. -
Re-pin and prepare before every write. Refresh the source commit and hashes, destination hashes and working-tree state immediately before applying. If any input changed, repeat the full comparison and judgment. For each overwrite, preserve the exact destination bytes in configured Scratch and record the backup path/hash; record an explicit missing destination for a create. Run
apply --dry-runfor local writes and resolve every result. For remote writes, where dry-run is refused, verify the destination and reviewed backup through an authorized read-only route first. -
Apply per decision, not per batch. Once you've judged a file (or a small consistent group of files with the same, clearly-justified direction), apply exactly those paths:
python3 scripts/sync_live_config.py apply --direction repo-to-live --paths <path> [<path> ...] python3 scripts/sync_live_config.py apply --direction live-to-repo --paths <path> [<path> ...] --remote <ssh-host>Never run
applyover an entire report's file list without having individually judged each one. -
Verify and report. Read every destination back from its target host, compute its SHA256 and compare it with the reconciled source bytes. Report each path's keep/adapt/reject decisions, source and destination hashes, direction (or "skipped — unresolved conflict"), reason and whether it was applied. A successful copy command alone does not prove synchronization.
-
Never delete. Applying in either direction only adds/overwrites the destination file; it never removes anything that exists only on one side.
Remote targets
report --remote HOST resolves the remote $HOME once, then runs a single
batched script over SSH that returns, per path, its hash, enclosing-repo last
commit, and (for files under the diff-snippet size cap) base64 content so a
real unified diff can be computed locally — the per-file judgment inputs
match local, including the live_only directory walk (files present live but
never repo-tracked), which now runs against the remote host too — so a
remote-side rename/delete drift (the hermes/skills incident shape) is
visible on a remote target, not just locally. The remote walk honours the same
noise filters and reports a symlinked path as symlink with all metadata
withheld, exactly like the tracked-file pass.
If that walk fails on a host, report prints a warning: remote live_only scan incomplete on <host> line to stderr and still returns the tracked-file
results. A bare clean remote result therefore means "no drift in the
tracked-file scope"; check for that warning before reading it as "no drift at
all." apply --remote HOST transfers only the files you named:
tar+scp+remote-extract for repo-to-live, or a guard-checked remote cat
for live-to-repo (see below — this is not a bare ssh ... cat).
Destination paths are always fully resolved in Python before being sent to
the remote shell — never left for the remote side to expand a $HOME-style
variable itself. The remote batch script uses portable primitives: a
sha256sum-with-shasum -a 256-fallback for hashing, and git -C "$dir" log -- "$p" (letting git resolve the pathspec itself against the absolute path)
for the commit lookup instead of manually reconstructing a relative path —
both an earlier realpath --relative-to version (GNU-only) and its
replacement prefix-strip silently dropped commit metadata whenever $HOME or
any path component was a symlink.
Symlink handling is asymmetric between local and remote, by design and verified in review, not accidentally uniform:
- Remote (both
report's evidence gathering and bothapplydirections) walks every path component between the mapped root and the target through a shared bash function and refuses the operation entirely if any component is a symlink — including the leaf. A symlinked remote path shows up inreportas statussymlink, with hash/size/commit/diff all withheld (an earlier version withheld only file content, which still let a symlinked path's exact hash and size leak as a confirmation oracle for an arbitrary file elsewhere on the host). - Local (
live_abs_for/repo_abs_for) resolves the full path and checks that the result stays within the specific mapped root (e.g.home/.claude), which blocks escaping that root but does not walk component-by-component — a symlink whose target is still inside the same mapped root (e.g..claude/skills/foo/SKILL.md -> .claude/settings.json) is allowed through. This is intentionally less strict locally than remotely; see "Accepted residual risks" below.
Bootstrapping on a machine that has never run this before
/sync-live-config is a thin dispatcher pointing at
${CLAUDE_HOME:-$HOME/.claude}/skills/sync-live-config/SKILL.md — on a
machine where this skill has never been synced, that path doesn't exist yet
and the slash command can't resolve. The first sync on a new machine must be
done by running the script directly from a repo checkout:
python3 scripts/sync_live_config.py report — once this skill itself is
included in whatever scope you sync, the slash command becomes available for
every subsequent run.
Accepted residual risks
This tool operates on the caller's own $HOME under their own account — it
is not designed to defend against an adversary who already has local write
access to that account. Two known gaps are accepted rather than chased
further, both discussed and agreed in review:
- A symlinked check-then-write TOCTOU window. Every containment check
resolves symlinks and then performs a normal
open/cp; a symlink swapped in between the check and the write would be followed. Closing this properly needsO_NOFOLLOW/dir_fd-relative opens, which is disproportionate for a single-user tool that only ever targets its own account. - The top-level mapped root itself being a symlink. Containment is
checked against
home/.claude(etc.) as resolved — if~/.claudeitself is a symlink to some other location (a real, common dotfiles pattern), everything computed relative to it is still "relative to" that resolved root, so operations transparently follow it. This is indistinguishable from the legitimate case without asking the operator, and this repo explicitly wants to support "my~/.claudeis symlinked to my dotfiles repo" as normal, not broken.
04 同仓库更多 Skills
instinct
Use when the user invokes /instinct or /in, or asks to "message Instinct", "ask Instinct", "tell Instinct", "check Instinct", or read replies from the configured peer assistant. iMessage first, WhatsApp Web as fallback.
hr
Compatibility alias for history-resume; produce the same fresh-state, provenance-aware resume briefing.
history-resume
Resume briefing for the current repository branch or worktree using fresh state and admitted history sources.
grok
Alias for the canonical grokbot browser conversation workflow; /grok talks to the Grok bot the same way /dot talks to Dot.
codexa-bench
Compare `codexa` and normal `codex` on a fair split of comparable work by default; use `--strict` for duplicate runs of the exact same task.
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.