mill-init
Skill18 starsChanged 4 months agoMITView on GitHub
One-time onboarding of a repo for ticketmill batch processing - verifies the environment with a doctor pass, writes the .claude/ticketmill.json profile, maps the project's agents onto pipeline roles, and generates missing agents. Use before the first mill run in a repo, or to repair/update an existing profile.
- Reads credentials
- Deletes or force-pushes
In this repository4 other files it gives its agents.
- docs/agents.mdAGENTS.md
- forge-agentSkill
- mill-reviewSkill
- millSkill
The file
We split this skill into the rules it gives an agent
10 rules. About 0 are common, 3 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
If <ROOT>/.claude/ticketmill.json already exists, read it and tell the user: this run will UPDATE it (show a diff at the end), not silently …
- Very specific: line 50
If you find no test suite, ASK: "I found no test command.
- Distinctive: line 127
leave it on the built-in charter (fine for v1), or
- Distinctive: line 136
Never trust an unproven profile.
- Very specific: line 140
Run each install_commands entry.
- Very specific: line 141
Every failure here is a finding: fix the profile (missing env file, missing service, wrong command) and re-run, or record the precondition …
- Distinctive: line 143
Only proceed when install + tests pass in the scratch worktree, because this is exactly what the engine will do per issue.
- Very specific: line 148
If browser is configured, also boot serve_command once (any port) and curl it.
- Very specific: line 152
Write the confirmed profile to <ROOT>/.claude/ticketmill.json.
- Very specific: line 157
Ensure .gitignore covers .worktrees/ and the profile's logs_dir.
≈ “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
mill-init: onboard a repo for ticketmill
Produces everything a mill run needs, and refuses to write a profile it hasn't
proven works. Do the steps in order; each gates the next.
Step 1: Preconditions
- Confirm you are in a git repo with a GitHub remote:
git rev-parse --show-toplevelandgh repo view --json nameWithOwner. Record ROOT and theowner/nameslug. - Confirm
gh auth statussucceeds and the token can write issues (gh label listis a cheap probe). - If
<ROOT>/.claude/ticketmill.jsonalready exists, read it and tell the user: this run will UPDATE it (show a diff at the end), not silently replace it.
Step 2: Detect the stack and propose a profile
Inspect the repo (build files, CI config, CLAUDE.md, README) and propose values for every profile field. Show the user the proposal and confirm the load-bearing ones:
{
"repo": "owner/name",
"test_command": "php artisan test",
"test_globs": ["**/*.php", "tests/**"],
"install_commands": ["composer install --no-interaction"],
"env_files": [".env"],
"simplify_globs": ["**/*.php"],
"serialize_globs": [],
"docblock_globs": null,
"docs_dir": null,
"logs_dir": "logs/ticketmill",
"claim_label": "ticketmill",
"verify_notes": [],
"warn_base_branches": [],
"consolidation": true,
"engine_owned_globs": [],
"browser": null,
"models": {},
"roles": { }
}Field rules:
test_commandis REQUIRED and may benullONLY as an explicit human decision. If you find no test suite, ASK: "I found no test command. Ticketmill will merge code that no automated test has exercised, and every batch PR will carry a visible 'Verification Gaps' notice. Confirmtest_command: null?" Never write null on your own initiative.env_files: files the test suite needs that git doesn't track (e.g..env). They are copied root -> worktree at issue setup.verify_notes: environment preconditions agents must know (required containers, seed commands, service dependencies). Anything you needed in Step 4 belongs here.browser: OPT-IN. Only propose it for projects with a servable UI AND if the user wants live browser verification:{ "serve_command": "... --port={port}", "build_command": null, "ui_globs": [...], "port_base": 8100, "notes": "..." }. Optional coordination overrides (each defaults to the value shown; only mention them if the user needs to change one):lock_path(default/tmp/ticketmill-browser-lock, the shared cross-agent browser lock directory),stale_seconds(default1800, how long before a held lock is considered dead and stolen),poll_seconds(default15, wait interval between lock-acquire retries),port_span(default900, the modulusport_baseis spread over per issue number), andartifact_dir(default/tmp/ticketmill-issue-{issue},{issue}-templated likeserve_command's{port}, where browser-verify screenshots/artifacts are written). Caution: this resolved path is deleted withrm -rfon cleanup (both the per-issue browser-verify stage and the final batch cleanup). It must be a dedicated scratch directory, never a project directory, shared mount, or$HOME.lockstep_installed_paths: only needed when the repo being onboarded keeps an installed copy of an engine-owned file in lockstep with a source-of-truth file elsewhere in the same repo, kept in sync by the repo's own tooling. List those installed paths so the engine's post-implement guardrail exempts them from a hard revert instead of undoing genuine engine work. Ticketmill's own profile (this repo, self-hosted) setslockstep_installed_paths: [".claude/workflows/ticketmill.js"], sincescripts/lint-engine.jskeeps that installed copy byte-identical toworkflows/ticketmill.js. Leave it empty for every other repo.serialize_globs: OPTIONAL, default[]. Lane scheduling (issue #1) already predicts likely file overlap per issue and serializes those issues instead of racing them. This field is only for files that heuristic alone can't be trusted to catch: a magnet config, a shared schema/router, anything where two issues touching it concurrently would conflict even if their predicted-file sets don't otherwise overlap. Leave it[]unless the user names such a file; propose it only when the stack detection in Step 2 surfaces an obvious candidate (e.g. a single central routes/config file every feature touches).warn_base_branches: OPTIONAL, default[]. Base branch names that should trigger a Select-phase warning when a batch targets one (a signal the run may be pointed at a branch that auto-deploys on push rather than the intended working branch). Leave it[]unless the user names CI/CD-trigger branches for this repo (e.g. adeploy-prod/deploy-devconvention). Never propose a default on your own.consolidation: OPTIONAL, defaulttrue. Leave ittrueunless the user asks to disable the Select-phase consolidation gate that groups issues cheaper to resolve as one unit; setfalseto skip that gate agent call entirely.engine_owned_globs: OPTIONAL, default[]. Extends the built-in engine-owned path set with repo-specific read-only paths, beyondlockstep_installed_pathsabove. Leave it[]unless the user names additional paths a run must never touch.models: OPTIONAL, default{}. Per-stage model/effort overrides. The valid stage keys are enumerated in the header schema comment ofworkflows/ticketmill.js, adjacent to theMmap that is their source of truth. Do not re-derive or duplicate that list here.
Step 3: Map project agents onto pipeline roles
- List
<ROOT>/.claude/agents/*.md; read each frontmattername+description. - Propose a role map. Roles:
implementers(array: the agents that write code, ideally one per domain),default_implementer,task_reviewer,spec_reviewer,code_reviewer,contrarian,test_validator,simplifier,docblock_writer,doc_writer. - Map by what each agent's description says it does. Do NOT force-fit (a UX
reviewer is not a code reviewer). Leave a role
nullwhen nothing fits; the engine has a built-in charter for every role. - Contrarian resolution (do this before offering forge for it). The plugin
bundles a contrarian template so this role never starts from scratch:
<ROOT>/.claude/agents/contrarian.mdexists -> use it as-is.- Else
~/.claude/agents/contrarian.mdexists -> copy it into<ROOT>/.claude/agents/contrarian.md(the engine only reads the project roster; user-level agents are invisible to it). - Else copy the bundled template:
${CLAUDE_PLUGIN_ROOT}/templates/agents/contrarian.md-><ROOT>/.claude/agents/contrarian.md. Either copy is immediately usable. Offer forge-agent afterward as an optional upgrade that grounds the copy in this repo's specific failure modes.
- Show the map with the remaining gaps, and for each gap offer:
- leave it on the built-in charter (fine for v1), or
- generate a project-specific agent now via the
forge-agentskill (/ticketmill:forge-agent). Generated agents land in<ROOT>/.claude/agents/and work in the very next mill run. The engine has stage subagents read the agent file directly, so no session restart is needed for ENGINE use. (A restart IS needed before the agent shows up for direct Task-tool use.)
Step 4: Doctor pass (environment proof; gates writing the profile)
Never trust an unproven profile. In a scratch worktree:
git worktree add /tmp/ticketmill-doctor-<repo> HEAD- Copy each
env_filesentry from ROOT into it. - Run each
install_commandsentry; then runtest_command(unless null). - Every failure here is a finding: fix the profile (missing env file, missing
service, wrong command) and re-run, or record the precondition in
verify_notes. Only proceed when install + tests pass in the scratch worktree, because this is exactly what the engine will do per issue. A failure here would otherwise recur as N expensive mid-batch failures. - Clean up:
git worktree remove --force /tmp/ticketmill-doctor-<repo>.
If browser is configured, also boot serve_command once (any port) and curl it.
Step 5: Write everything
- Write the confirmed profile to
<ROOT>/.claude/ticketmill.json. - Copy the engine and setup script into the repo so runs don't depend on the
plugin being installed on every machine:
${CLAUDE_PLUGIN_ROOT}/workflows/ticketmill.js-><ROOT>/.claude/workflows/ticketmill.js${CLAUDE_PLUGIN_ROOT}/scripts/setup-worktree.sh-><ROOT>/.claude/scripts/ticketmill/setup-worktree.sh(chmod +x)
- Ensure
.gitignorecovers.worktrees/and the profile'slogs_dir. - Offer to commit the onboarding files (profile, engine copy, setup script, .gitignore): recommended, so teammates and other machines get them.
Step 6: Hand off
Print the ready-to-run invocation, pre-filled with the repo's real base branch:
Workflow({
scriptPath: "<ROOT>/.claude/workflows/ticketmill.js",
args: { branch: "<base>", issues: [<n>], dry_run: true, run_label: "<today>" }
})Recommend the dry_run: true first run, and note that /ticketmill:mill handles
launches from here on.
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.

