视觉画布设计
canvas-design
基于设计原则创作静态视觉作品,用于海报与品牌图形。
publish-to-github【文档与办公】Use when preparing to publish ~/.claude/skills/, ~/.claude/agents/, and ~/.claude/commands/ to a public github repository. Wraps publish_prep.py to scrub embedded private content, run extended security checks, bundle README and documentation, and produce a clean staging directory ready for git init / commit / push. Also trigger on "publish skills to …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
A focused workflow skill that takes your local ~/.claude/skills/ and ~/.claude/agents/
trees and produces a clean, public-safe staging directory ready to push to a public GitHub
repository.
Most Claude Code users accumulate private context inside their skills over time — business names, internal paths, project-specific examples, customer details. Publishing the skill tree to public github without cleanup is a privacy hazard. This skill is the opposite of that: it produces a vetted, scrubbed copy in a staging directory while never modifying your live ~/.claude/ tree.
~/.claude/skills/ or ~/.claude/agents/~/.claude/publish-config.jsonThe skill is split into two parts:
scripts/publish_prep.py (publishable, contains zero project-specific strings)~/.claude/publish-config.json (user-owned, NEVER published)The engine reads its rules from the config: which directories to exclude, which strings to find/replace, which patterns to grep for, and which README/docs files to bundle into the staging dir.
This split is intentional: the engine can be safely published to a public github repo, while every user maintains their own private rules in their own home directory.
publish — full workflow (most common)Trigger phrases: "publish to github", "deploy public skills", "prepare publish", "create publish staging", "publish skills".
Steps Claude follows:
Locate the config
$PUBLISH_CONFIG env var~/.claude/publish-config.json./publish-config.jsontemplates/publish-config.example.json
to ~/.claude/publish-config.json and customise it.Pre-flight summary
Run publish_prep.py (pass --extended-scan to include the extended checks)
python3 ~/.claude/skills/publish-to-github/scripts/publish_prep.py --extended-scan
--extended-scan it also runs the extended security patterns from
checks/security-patterns.md against the staging directory.Review extended security warnings
--extended-scan phase reports findings at critical / high / medium / low
severity: API key shapes, private key blocks, DB connection strings, real-looking
emails, public IPs, internal TLDs, E.164 phones, large files, dangling symlinks.forbidden_patterns / scrubs / exclusions) or accept as false positive.extended_scan_ignore in your
publish-config.json to suppress known false positives (e.g. networking skills
that legitimately document public DNS IPs, mongodb skill that documents
mongodb://user:pass@ example strings). See the example template at
templates/publish-config.example.json for the schema.Sync metadata — README counts/version + GitHub About (mechanized; see sync-metadata)
scripts/sync_metadata.py to drive ALL THREE drift-prone surfaces from ONE
live source (the source.root+subdirs+exclusions tree). This replaces the old
hand-editing of counts, which silently drifted (the catalog README regressed to
159 skills / 4 agents and the public About to 141+ … Gemini before it was caught
— see the repo-metadata-maintenance memory).# README: rewrite **N skills**/**M agents**/**K workflows** bullets + the
# `**Version:** · **Last published:** · **N skills · …**` header (+ optional --bump).
python3 scripts/sync_metadata.py readme --readme <staging>/README.md [--bump patch|minor|major]
# GitHub About: substitutes {skills}/{agents}/… into the publish-config `about` block.
# Dry-run prints the gh command; add --apply to set it (mirrors "print, don't auto-mutate").
python3 scripts/sync_metadata.py about --repo <owner/repo> [--apply]
## Changelog entry for the release (the one surface that needs prose).Publish gate — 3-tree _meta identity (S043 / #119 C2)
scripts/stage-to-public.sh,
the script now reconciles the safety-critical _meta subset (gates.py,
claims.py, identity_check.py, classify*.py, the arbiter spawners, the
HARD-RULE scan/apply machinery, …) from prod (~/.claude) into the public
repo BEFORE git add, then runs:
python3 ~/.claude/skills/_meta/gates.py G_IDENTITY <public_repo> \
--pair prod-foundry --strict --foundry-root <public_repo>
_meta drifted from prod. This is the authoritative check (it
lives in the script, not a hook, because --no-verify silently bypasses
hooks with no log — C7). The agent-foundry pre-push hook, if installed, is
verify-only defense-in-depth.Print git commands
git init → add → commit → remote add → pushPrint rollback / re-run instructions
check — security scan onlyTrigger phrases: "scan skills for leaks", "security check on skills", "check for secrets".
Run only the verification phase against either:
~/.claude/skills/ and ~/.claude/agents/)--verify <path>)No staging dir is created, no files are modified.
bump-version — README version bump onlyTrigger phrases: "bump skill version", "increment version", "release new version".
Read the current README, increment the version, update counts and date, write back. Does not run scrubs, does not create a staging dir.
sync-metadata — reconcile README counts/version + GitHub About from the live treeTrigger phrases: "sync repo metadata", "update the about section", "fix the skill counts", "the README counts are stale", "update repo description/topics".
The single-source reconciler for the three surfaces that drift because no one tool
owned them (the repo-metadata-maintenance memory). scripts/sync_metadata.py:
counts — print live {skills,agents,workflows,commands} from source.root
applying exclusions (the same set the publisher uses, so it matches the published count).readme --readme P — rewrite the **N skills**/**M agents**/**K workflows**
bullets, the **N skills · M agents · …** header tuple, and **Last published:**;
--bump {patch|minor|major} also bumps **Version:**. Idempotent; reports changes.about --repo R — read the publish-config about block (a
{owner/repo: {description, topics, homepage}} map whose description may use
{skills}/{agents}/{workflows}/{commands} placeholders), substitute live counts,
and print the gh repo edit command — or run it with --apply (the only
mutating path; topics are additive via --add-topic).sync --readme P --repo R [--apply] — both at once.Config: add an about block to ~/.claude/publish-config.json. Read-only on the
source tree; --apply is the sole outward mutation and is opt-in.
stage-public — gated scrub-then-publish to your public repoTrigger phrases: "publish to my public repo", "scrub and push to github", "stage to public".
The generic, gated publish driver (scripts/stage_to_public.sh) — the publishable
companion to publish_prep.py. It takes a scrubbed staging dir, HARD-GATES on the
forbidden-pattern verify (a leak can NEVER reach the public repo — the gate re-runs the
verify and aborts with exit 2 if anything remains), mirrors it into your public repo, shows
the diff, and pushes only after you confirm.
# 1. build your scrub list once (see below) at ~/.claude/publish-config.json
# 2. produce a scrubbed staging dir
python3 scripts/publish_prep.py --extended-scan
# 3. gated publish to YOUR public repo
PUBLIC_REPO_ROOT=/path/to/your/public-clone scripts/stage_to_public.sh # or --repo-root PATH ; --yes for CI
Contains zero project-specific logic and zero private strings (HARD-RULE) — safe to ship
publicly so anyone can reuse the framework. It does NOT do any ecosystem-specific
reconciliation (e.g. a safety-critical _meta identity gate) — that belongs in your own
private wrapper that calls this driver and adds steps on top.
The framework is shared; the scrub list is yours. publish_prep.py +
stage_to_public.sh carry no private data — every rule about what to redact lives in
your own ~/.claude/publish-config.json (user-owned, gitignored, NEVER published).
Start from templates/publish-config.example.json and add:
forbidden_patterns — strings that must NEVER appear publicly (your home path e.g.
/home/<you>, machine/dev paths, employer/customer/business names). The scrub gate
blocks the publish on any match — so list yours up front.scrubs — per-file find→replace to rewrite specific private strings to placeholders.exclusions — paths to drop entirely (runtime caches, private skills, local state).about — your repo's GitHub description/topics (for sync-metadata).This is why the framework is publishable and the config is not: another person installs the same engine + gate, writes their OWN forbidden-pattern/scrub list, and gets the same leak-proof publish for their own tree.
validate-config — sanity check the configTrigger phrases: "validate publish config", "check publish config".
Parse ~/.claude/publish-config.json, verify schema, report what's configured.
init-config — create a starter configTrigger phrases: "set up publish config", "create publish config", "init publish".
If ~/.claude/publish-config.json does not exist, copy
templates/publish-config.example.json to it and walk the user through customising it.
See templates/publish-config.example.json for the full schema. Top-level structure:
{
"version": 1,
"source": {
"root": "~/.claude",
"subdirs": ["skills", "agents"]
},
"exclusions": [
"skills/private-skill-name"
],
"scrubs": [
{
"file": "skills/some-skill/SKILL.md",
"replacements": [
{ "find": "private-string", "replace": "generic-placeholder" }
]
}
],
"forbidden_patterns": [
"private-string",
"/absolute/private/path"
],
"bundle_files": [
{ "source": "~/path/to/REPO_README.md", "dest": "README.md" },
{ "source": "~/path/to/docs/dependencies/", "dest": "docs/dependencies" }
]
}
The source.root is the base directory the script walks. Defaults to ~/.claude.
The source.subdirs are the subdirectories to copy. Defaults to skills and agents.
S055 — workflows subdir (workflow-adoption keystone): the saved-workflow
library at ~/.claude/workflows/ publishes through the generic subdir walk
(zero engine change — it is just another entry in source.subdirs). No scrub
rule may target workflows/ (G-W3): workflow files carry only
ecosystem-relative paths (progress/, .alf/, .ledger/), so prod↔foundry is
byte-identical. Scrubbing workflows/ is exactly the self-watch divergence
that tripped identity_check in the P0c false positive — do not add one.
Note on bundling directories: When bundle_files points source at a directory, the recursive copy SKIPS hidden files (.foo) and underscore-prefixed files (_bar). To include such a file, add a per-file bundle_files entry pointing directly at it instead of its parent directory.
The base publish_prep.py greps for the forbidden_patterns you list in your config.
The skill workflow adds additional heuristic checks (see checks/security-patterns.md):
| Category | Patterns | Severity |
|---|---|---|
| API keys | sk-, ghp_, xoxb-, xoxp-, AIza, eyJ (JWT), pk_live_, sk_live_ | critical |
| Private keys | BEGIN RSA PRIVATE, BEGIN OPENSSH PRIVATE, BEGIN PGP | critical |
| AWS / cloud | AKIA, aws_access_key, arn:aws:, gcp-project- | high |
| Passwords | password=, passwd=, pwd= followed by non-placeholder | high |
| Tokens | token=, bearer followed by non-placeholder | high |
| Real emails | non-RFC-2606 domains (anything not example.com/test/contoso/etc) | medium |
| Public IPs | non-RFC1918, non-TEST-NET | medium |
| Private hostnames | *.internal, *.corp, *.local, *.lan | medium |
| Phone numbers | E.164 format +\d{10,15} | low |
| Large files | >1MB | warning |
| Binary files | non-text content | warning |
| Dangling symlinks | symlinks pointing outside the staging dir | warning |
These checks produce warnings, not errors. The user reviews each finding and decides whether to add an exclusion, add a scrub rule, or accept the finding.
If a bundled README has a version header like:
# My Claude Skills
Version: 1.2.3
Last published: 2026-04-08
The skill can auto-bump the version on each publish:
1.2.3 → 1.2.41.2.3 → 1.3.0 (user opts in: "bump minor")1.2.3 → 2.0.0 (user opts in: "bump major")The skill also updates:
Last published: <today> line<details> blocks)If the README has no version header, the skill prompts to add one on first publish.
~/.claude/skills/publish-to-github/
├── SKILL.md (this file — workflow Claude follows)
├── scripts/
│ └── publish_prep.py (generic engine — no private strings)
├── templates/
│ ├── publish-config.example.json (config template for new users)
│ ├── README.example.md (starter README template)
│ └── CHANGELOG.example.md (changelog template)
├── checks/
│ └── security-patterns.md (extended scan patterns + how to extend)
└── docs/
└── workflow.md (detailed end-to-end walkthrough)
The user's private config lives at ~/.claude/publish-config.json — outside the skill
directory, never published, gitignored at the user level.
| Anti-pattern | Why it fails | Correct approach |
|---|---|---|
Hard-coding scrub rules in publish_prep.py | Couples the engine to one user's data; can't be published without leaking | Keep rules in ~/.claude/publish-config.json (private) |
| Auto-running git push | One bad commit becomes a permanent public mistake | Print commands, let the user run them |
| Modifying the live ~/.claude/ tree | Loses local examples, breaks ongoing sessions | Operate only on the staging copy |
| Trying to detect implicit fingerprints automatically | False sense of security; LLMs can't reliably spot semantic leaks | Surface a manual review checklist |
| Skipping the forbidden-patterns grep | Defeats the purpose | The grep is the final safety net — never skip |
| Treating the example config as the user's config | Example contains placeholders, not real rules | First-run setup must copy → customise |
Edit directlygpg, pass, OS keychain). This skill is for documentation and example data, not credentials.Skill's job: prepare a clean, scrubbed staging dir of ~/.claude/skills/ + ~/.claude/agents/
ready for public github publish.
Engine: scripts/publish_prep.py (generic, reads config)
Config: ~/.claude/publish-config.json (private, user-owned, never published)
Output: /tmp/claude-skills-public-<timestamp>/ (cleaned, scrubbed, verified)
Workflow: config → exclude → scrub → bundle docs → verify → print git commands
What it doesn't do: push, commit, manage credentials, modify live tree, detect implicit fingerprints