deploy-list
Skill2 starsChanged 6 days agoMITView on GitHub
Generate a deterministic deploy file-list (schema=v1) from git history. Use when: building a deploy/release checklist, 部署清單, or listing files to ship via --anchor, --deploy-commits, or base..head. Not for: commit lookup, raw diffs, or running the deploy. Output: a deploy checklist.
In this repository39 other files it gives its agents.
- AGENTS.mdAGENTS.md
- change-verdictSkill
- code-simplifySkill
- code-traceSkill
- create-prSkill
- doc-maintainSkill
- feature-verifySkill
- flow-driveSkill
- flow-guideSkill
- git-smart-commitSkill
- git-worktreeSkill
- harness-setupSkill
- issue-analyzeSkill
- js-static-checksSkill
- laravelSkill
- legacy-characterization-testsSkill
- library-authorSkill
- merge-prepSkill
- module-designSkill
- nextjsSkill
- openspec-artifact-guardSkill
- opsx-apply-resumeSkill
- phpSkill
- phpunitSkill
- precommitSkill
- project-auditSkill
- project-briefSkill
- proposal-analyzeSkill
- pr-summarySkill
- pythonSkill
- reactSkill
- release-creatorSkill
- repo-intakeSkill
- repo-verifySkill
- swiftSkill
- tdd-workflowSkill
- ui-ux-verifySkill
- vue-2-notesSkill
- yii1Skill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 0 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 146
NEVER: use Write/Edit to hand-construct schema=v1 output.
- Very specific: line 151
NEVER: use git log --grep="[tag]" to derive deploy scope — tag is operational metadata, not stored in commit messages.
- Very specific: line 163
NEVER: add project-specific paths to a generic preset — project rules belong in a named preset (e.g.
≈ “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
deploy-list
Generates a deploy file list from git history. All logic lives in the script — the current Host and Model parse arguments, invokes the script, and emits stdout verbatim. No post-processing.
Package surfaces
The package keeps the immutable generator in scripts/deploy-list.sh, its golden
runner in scripts/check-golden.sh, ecosystem rules in presets/, structural labels
in i18n/, and preset guidance in references/. Copy config.sh.example to a
project-local config.sh when defaults need to be pinned. The evals/ fixtures are
the regression surface for schema changes.
Arguments
| Flag | Required | Default | Notes |
--tag | ✅ | — | ^\[.+\]$, pure metadata, NOT used for grouping |
--description | ✅ | — | freeform text |
--deploy-commits | ⛳ | (none) | CSV of commit SHAs → union diff = main group; rest of base..head = warn group |
--anchor | ⛳ | (none) | source-code inline anchor string → rg -l --fixed-strings finds matching source files; mutually exclusive with --deploy-commits / --auto-detect-tag |
--date | ⛳ | today | YYYY/MM/DD |
--author | ⛳ | $DEFAULT_AUTHOR → $USER → user | |
--project | ⛳ | git toplevel basename | |
--base | ⛳ | $DEFAULT_BASE → main | git ref (ignored in anchor mode) |
--head | ⛳ | HEAD | git ref (ignored in anchor mode) |
--preset | ⛳ | $DEFAULT_PRESET → auto-detect → generic | see Preset selection |
--lang | ⛳ | $DEFAULT_LANG → en | zh-TW or en |
--auto-detect-tag | ⛳ | off | grep -i -F $TAG in commit messages, fill --deploy-commits if empty |
Defaults marked $DEFAULT_* are read from config.sh if present. CLI
flags always win.
Preset selection
Resolution order (first non-empty wins):
--preset <name>CLI flag$DEFAULT_PRESETfromconfig.sh- Auto-detect (probe order, first match wins):
protected/yii.phporprotected/config/main.php+protected/views/→php-yiiartisanat root →laravelpackage.json+ nocomposer.json→nodepyproject.tomlorsetup.py→python- fallback →
generic(stderr note emitted)
Projects with DDD layering on top of Yii (or any other non-trivial
project-specific layering) should not rely on auto-detect — write a
custom preset (see references/presets.md and the worked example at
references/extended-presets.example/php-yii-acmeshop.sh) and pin it via
config.sh's DEFAULT_PRESET.
Note on stderr suppression: the auto-detect fallback note goes to
stderr. check-golden.sh and the fixture scripts use 2>/dev/null to
keep golden diffs clean, so the hint is invisible in CI. When manually
running deploy-list and unsure which preset was picked, omit 2>/dev/null
or pass --preset <name> explicitly.
Full preset catalog → references/presets.md.
Output
| # | Marker | Required | When |
| 1 | # deploy-list schema=v1 | ✅ | line 1 |
| 2 | ⚠️ BASE 與 HEAD 相同… line | ⛳ | only if base==head triggered auto-switch |
| 3 | Update time / Tag / Project (3 lines) | ✅ | always |
| 4 | Update files line + main group | ✅ | always (main group can be empty → "no deploy files" note) |
| 5 | --- + ⚠️ Out of scope (…) + warn group | ⛳ | only when --deploy-commits given and base..head has extras |
| 6 | --- + 📊 Stats header + preset-defined body | ✅ | always |
| 7 | 🚫 Filtered out (not deployed) header + preset body | ✅ | always |
| 8 | 🔁 Rollback hints header + preset body | ⛳ | only when preset rollback trigger matches main group |
| 9 | # end deploy-list schema=v1 | ✅ | last line |
Locked across presets / langs: header marker, footer marker, section ordering, the emoji prefixes (⚠️ 📊 🚫 🔁).
Variable per preset/lang: the human labels (e.g. 更新時間/Update
time), the 📊 Stats body lines (per-preset stat breakdown), the
🚫 Filtered out body lines (per-preset filter category labels), the
🔁 Rollback hints body. Stock presets emit nothing for rollback;
projects that need it (e.g. a legacy monolith with a feature flag for
fallback) wire it via a custom preset's PRESET_ROLLBACK_TRIGGER.
Changing the locked markers requires bumping schema=v1 → v2 + ADR + golden refresh.
Scope resolution modes
Three mutually-exclusive ways the script derives the deploy file list. Order of preference (best to worst):
- Anchor mode (
--anchor "<full anchor string>") — preferred for retrospective deploys where in-code anchor comments are the source of truth. Source files are found byrg -l --fixed-strings "$ANCHOR"against the working tree. Built-in excludes:.claude/,.git/,node_modules/,protected/tests/coverage/html/. Preset filter still applies. No git diff, no base/head needed. - Pinned mode (
--deploy-commits SHA1,SHA2,...) — when feature commits are known. Union of those commits' diffs becomes the main group; remaining base..head diff goes to the⚠️ Out of scopewarn group. - Fallback mode (no
--deploy-commits, no--anchor) — whole base..head as one main group, no warn group. Easy to over-collect; only use when the entire range really is the feature scope.
The anchor string is a literal in-code marker convention. Two common shapes:
// 2026/02/09 paul [DemoTag]Description0205 start
// 2026/02/09 paul [DemoTag]Description0205 endor PHPDoc:
/**
* 2026/02/09 paul [DemoTag]Description0205
*/Pass the full anchor string (date + author + [tag] + description)
to --anchor. The script treats it as a literal --fixed-strings
pattern — no regex escaping needed.
When NOT to Use
- Pure commit history lookup →
git log --oneline. - Diff outside base..head → plain
git diff. - Full commit message →
git log --grep. - Actually executing deploy → this skill only generates a checklist.
NEVER
- NEVER use Write/Edit to hand-construct schema=v1 output. schema=v1
is the script contract — the only allowed path is "invoke
deploy-list.sh, forward stdout verbatim". Ifrgprobe or the script fails (zero hits, timeout, encoding), stop and report; do not simulate the output (token cost ~5× and schema-contract drift risk). - NEVER use
git log --grep="[tag]"to derive deploy scope — tag is operational metadata, not stored in commit messages. - NEVER post-process the script's stdout — schema=v1 is the contract, every byte matters.
- NEVER modify
--descriptiontext (even if obviously typo'd) — that's input data. - NEVER auto
git add/commit/push— deploy-list is read-only. - NEVER skip
--deploy-commitsto auto-group commits — that's an explicit "single main group, full base..head" mode (correct by design). - NEVER translate the schema markers (
# deploy-list schema=v1, section emoji prefixes) — they are byte-stable identifiers, not human-facing labels. - NEVER add project-specific paths to a generic preset — project
rules belong in a named preset (e.g.
presets/<your-project>.sh) or inconfig.sh.
Adopting this skill in a project
The skill is self-contained. To use in another repo:
- Copy the whole
skills/deploy-list/directory into the Host's skill discovery location, then resolve the installed directory to invoke its bundled scripts. - Copy
config.sh.exampletoconfig.shand edit:DEFAULT_PRESET=pick the matching preset (php-yii,laravel,node,python,generic) or leave empty for auto-detect.DEFAULT_BASE=your integration branch (oftenmainordevelop).DEFAULT_LANG=zh-TWoren.DEFAULT_AUTHOR=optional team-wide author pin.
- Optional: add a custom preset at
presets/<your-name>.shfollowing the worked example atreferences/extended-presets.example/. - Smoke test:
bash scripts/check-golden.sh— all generic fixtures should pass.
Verification
# Run the bundled fixture suite
bash skills/deploy-list/scripts/check-golden.sh
# Update goldens after an intentional schema change
bash skills/deploy-list/scripts/check-golden.sh --updateManual checks after running deploy-list:
- Line 1 =
# deploy-list schema=v1. - Last line =
# end deploy-list schema=v1. - Main group ≥ 1 file (else "no deploy files" note present).
- Stats filter counts ≈ git diff total (rename rows may differ by ±2).
- Rollback hint present iff the preset's
PRESET_ROLLBACK_TRIGGERactually matched a file in the main group.
Platform compatibility
Tested on Linux (bash 4+), macOS (bash 3.2 default), WSL2. Requires POSIX
git awk sort comm grep sed wc tr mktemp basename printf in PATH. Fails
fast on bash < 3.0 or missing tools.
Key BSD/GNU compat fixes:
git -c core.quotepath=false(macOS git path quoting).sort -t"$TAB"(BSD sort doesn't accept$'\t'in some contexts).LC_ALL=Cthroughout (deterministic byte ordering across locales).mktempportable form (mktemp || mktemp -t prefix).
Why these decisions
Detailed history → references/why-this-grouping.md.
Preset catalog + custom-preset guide → references/presets.md.
Headlines:
--deploy-commits(not--tag-driven): tag is ops metadata (store-code, version, batch); commit is dev artifact. Coupling them viagit log --grepbecomes a dead path in practice — fallback rate approaches 100%.- Per-preset category sort: deploy order should reflect dependency direction (domain → infra → presentation → assets → entry bundle) so partial deploys don't break loading.
- Per-ecosystem filter sets:
protected/tests/only makes sense in Yii;dist/only in Node;__pycache__/only in Python. A universal filter would either over- or under-filter. - i18n only for structural headers: per-preset stat bodies vary in vocabulary (PHP/JS vs TS/JS/CSS vs Python/templates), so they're owned by presets, not i18n.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
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.

