agentleFS
VforValVforVal/lumberjack/skills/lumberjack/SKILL.md

lumberjack

Skill0 starsChanged 24 days agoMITView on GitHub

Worktree and branch rules delivered by lumberjack at session start. Use as a reference when these rules are absent from context before creating, finishing, cleaning up or recovering worktrees or branches.

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 0 are distinctive, and 5 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.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Do not edit features there.

    line 15
  2. Very specific:

    Put work documents only in a doc_roots folder named <ticket_prefix><n>-<slug> or the branch slug.

    line 23
  3. Very specific:

    When you read or extend a bundle for your ticket, add it to the bundle's Tickets: <ids> line (top file).

    line 24
  4. Very specific:

    When other branches are built on a landed branch, the sweep prints one line per dependent, dependent <b> of <a>: git rebase --onto …

    line 47
  5. Very specific:

    Before forcing a removal by hand, snapshot the branch: git update-ref refs/archive/<branch> <branch>.

    line 79

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Worktrees, cleanup and the Stop gate

lumberjack keeps one clone tidy: the primary checkout stays on primary_branch, each task gets a worktree, and a landed one is removed automatically. Settings live in .lumberjack.toml (or [tool.lumberjack] in pyproject.toml); the README lists the defaults.

Primary checkout

It stays on primary_branch, clean, and only fast-forwards from origin/<primary_branch>. Do not edit features there. Create a worktree from fresh origin/<primary_branch> under one of worktree_roots, one per task, so it inherits nothing uncommitted.

Branch names and documents

One of branch_shapes, where <ticket> is <ticket_prefix><n>; empty means <owner>/<ticket>-<slug> or <owner>/<slug>, <owner> one of owners (empty: any lowercase owner). Throwaway captures use <prototype_prefix><ticket_prefix><n>-<slug>. Other shapes fail the Stop gate. Put work documents only in a doc_roots folder named <ticket_prefix><n>-<slug> or the branch slug. When you read or extend a bundle for your ticket, add it to the bundle's Tickets: <ids> line (top file).

Cleanup rule

Each session start the sweep fetches origin (5 second limit; on failure it says origin stale and carries on), then removes a worktree only when all of these hold:

  1. Its tip is verified landed in origin/<primary_branch>: an ancestor, identical content, or the exact tip of a merged pull request (checked through gh). Squash and rebase merges count; a guessed match or an unreachable gh leaves it unverified.
  2. git status --porcelain is empty. Ignored files do not count; untracked ones do.
  3. The tip is pushed (upstream contains it); waived when a merged pull request had this tip.
  4. evidence_dir is empty or absent; no doc_roots folder holds an untracked or ignored file.
  5. The branch is not a prototype_prefix branch, which is never touched.

A worktree that fails a check stays, and the sweep names the reason: dirty, unpushed, evidence, docs, tip diverged (the pull request merged a different tip), current checkout (the sweep runs inside it), locked (git worktree lock) or fresh (added <24h ago, not moved). The local branch is always kept. Orphan directories in a worktree root holding only caches (node_modules, .venv, __pycache__) are deleted; other orphans are listed. A post-merge run in another worktree cleans nothing; with the primary off primary_branch the sweep still runs and the Stop gate reports it. On dirty, ask the maintainer once per group of stray files (delete, ignore or commit), never file by file; /lumberjack:cleanup has the steps.

When other branches are built on a landed branch, the sweep prints one line per dependent, dependent <b> of <a>: git rebase --onto <primary> <a-tip> <b>. Run it before pushing <b>, or its pull request carries the squashed commits.

Keys that change the behavior

  • cleanup = "prune" (default) removes eligible worktrees and, with a saved doc_strategy, trashes linked ephemeral bundles and purges trash past trash_days. "report" prints landed <branch> <path>: would remove, doc <class> <path>: would trash and trash <stamp>: would purge, and keeps them. "keep" keeps them silently. Asked what a sweep would remove, run python "$(git config lumberjack.script)" --preview (any mode, changes nothing) and summarize it; asked for detail, add --files <bundle path or stamp>... (bare --files: all) to list each file. --tally (same --files) counts what was trashed and purged.
  • stop_gate = false turns the Stop hook off; it then exits 0 without output.
  • A config error is printed at session start; cleanup does nothing and the Stop gate blocks.

What the sweep prints

sweep: cleaned N, landed N, dependents N, blocked N, unverified N, orphans N, docs N, with , origin stale appended when the fetch failed, then one line per event: cleaned, landed, blocked, dependent, orphan, cleared, purged, doc or hint (relay a hint to the maintainer once; report mode adds a sweep would: totals line after the summary). When nothing was swept the only line says why: a config error, or sweep: ...; skipped. The exit code is always 0. Paths are relative to the primary's parent directory, or start with ~. doc <ephemeral|reference> <path>: tickets <ids>; <size> is a linked doc_roots bundle (tickets, none kept live) the sweep leaves, including while it is inside grace_days. cleared <path>: trashed <stamp> is a linked ephemeral bundle moved to the trash (docs N counts them); purged <stamp> is trash past trash_days deleted. unverified counts unproven branches; only the maintainer's /lumberjack:cleanup removes them.

Stop gate

At turn end, the Stop hook blocks with a reason when the current branch breaks naming rules or the primary is off primary_branch: rename with git branch -m, move work to a worktree, return the primary. A second stop in a turn passes. Plain --gate exits 2 via stderr; the plugin's --hook exits 0 with JSON.

Recovery

Removing a worktree deletes nothing committed: git worktree add <path> <branch> brings it back. Uncommitted files are not recoverable, which is why a dirty worktree is never removed. Before forcing a removal by hand, snapshot the branch: git update-ref refs/archive/<branch> <branch>.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.