yjuyjuy/treehouse

treehouse

Operate a pool of reusable git worktrees through the treehouse CLI: lease an isolated worktree non-interactively, read pool state, return a lease, and reclaim slots with prune or destroy.

Quelltext ansehen

Verwendung

  1. Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
  2. Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
  3. Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/yjuyjuy/treehouse --skill treehouse

Vor dem Start

  • Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
  • Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Originales Skill-Dokument

Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.

treehouse

Pool manager for reusable git worktrees (and, with the opt-in jj backend, Jujutsu workspaces). A pool slot is a real worktree of the clone that created it, reset and handed back out instead of being recreated.

Every command takes --help, and per-subcommand help is good; this skill only covers what --help cannot know. Set TREEHOUSE_NO_UPDATE_CHECK=1 in scripted use so the update-available banner stays out of captured output.

When to reach for it

  • Need an isolated checkout for a parallel agent, a build, or a risky experiment: lease one with treehouse get --lease. Never git worktree add by hand into a directory a pool manages.
  • Already sitting in a worktree handed to you: use treehouse only to read state. Ordinary git commands (branch, commit, push) are unchanged inside a slot.
  • One-off scratch clone that nothing else shares: plain git clone or git worktree add is simpler. A pool earns its keep when slots are acquired and released repeatedly.
  • Bare treehouse with no arguments is not a status probe. It is an alias for get, so it acquires a slot and opens an interactive subshell. Use treehouse status to look.

Workflows

All command output below was reproduced against treehouse v2.1.0.

Read a pool without touching it. Run from the clone that owns the pool, not from inside a slot (see Fleet conventions).

bash
treehouse status          # human table: name, status, path, holder or processes
treehouse status --json   # machine-readable; the only structured read in the CLI

Lease a worktree non-interactively. This is the agent path: no subshell, path on stdout, banners on stderr.

bash
WT=$(treehouse get --lease --lease-holder my-task-id)   # stdout is the path alone
treehouse get --lease --json --lease-holder my-task-id  # path + lease_id + holder + timestamp

A lease is process-independent: it survives with zero processes in the worktree, and nothing reclaims it automatically. Always pair an acquire with a return.

Return a lease safely. Use the conditional form when another agent might hold the slot by now; it refuses rather than stealing.

bash
LID=$(treehouse status --json | jq -r '.[] | select(.name=="1") | .lease_id')
treehouse return --if-lease-id "$LID" "$WT"   # exit 1 if the lease moved on
treehouse return --force "$WT"                # unconditional; discards uncommitted work

--force resolves the pool that actually contains an absolute path, so it works after a pool has been re-rooted. return is idempotent: returning an already-returned slot exits 0.

Diagnose a full pool. Exhaustion is the common failure, and the error already carries the numbers.

bash
treehouse get --lease
# all 3 worktrees are in use or dirty (max_trees = 3). Run 'treehouse status' to see details, ...
treehouse status   # which slots are leased, dirty, in-use, or damaged

A dirty slot is not reusable and is never auto-cleaned. Either commit and push the work, or reclaim the slot with treehouse return --force <path>, which discards it.

Reclaim slots, dry-run first. Both prune and destroy are dry-run unless --yes, and both refuse anything risky by default.

bash
treehouse prune                              # dry run: stale, clean, merged, unleased slots only
treehouse destroy <pool-dir> --all           # dry run: same disposable set, grouped by skip reason
treehouse destroy <pool-dir> --all --yes     # removes only the disposable set
treehouse destroy <path> --include-leased --yes   # a leased slot, one exact path, never via --all

The skip lines name the exact flag that would include each class (--include-unlanded, --include-in-use, --include-leased), so read the dry run before adding a flag. A bulk skip exits 0; a single named target that gets skipped exits 1.

Exercise a lifecycle command safely. Never rehearse destroy, prune, or a config change on a pool other agents are in. Build a throwaway one:

bash
mkdir -p /tmp/th-scratch/repo && cd /tmp/th-scratch/repo
git init -q -b main . && git commit -q --allow-empty -m init
printf 'max_trees = 3\nroot = "/tmp/th-scratch/pool"\n' > treehouse.toml
WT=$(treehouse get --lease --lease-holder scratch)   # ... exercise here ...
treehouse return --force "$WT"                       # release before destroying: --all skips leased slots
treehouse destroy /tmp/th-scratch/pool/.treehouse/<pool> --all --yes

Clean up only the scratch pool you created.

Fleet conventions

Pools are keyed by origin URL, not by clone. The pool directory is <root>/.treehouse/<repo-basename>-<sha256(origin-url)[0:6]>/<slot>/<repo-basename>, and root defaults to $HOME. Every clone of one remote on the box therefore shares a pool unless a clone pins its own root in treehouse.toml. Firstmate pins each project clone to its home (bin/fm-treehouse-pin.sh), which is what keeps one home's slots out of another's.

Run pool commands from the owning clone. Inside a pooled worktree, the pinned treehouse.toml is usually absent, so treehouse resolves the default $HOME root and reports a different pool. Measured on this box: the same slot reads available in an unpinned pool from inside the worktree, and in-use from the clone that owns it. cd to the clone (git rev-parse --git-common-dir names it) before reading or mutating.

Pools are shared live state. Other agents are working in slots right now. destroy, prune --yes, return --force, and editing a live treehouse.toml are all destructive to someone else's in-flight work. Treat every lifecycle command against a pool you did not create as requiring a human decision.

Crewmates do not provision their own worktrees. Firstmate leases a slot and hands you the path; extra worktrees go through bin/fm-lease-extra-worktree.sh so teardown can return them. Leasing directly leaks a slot that nothing will reclaim, and leaked leases accumulate until the pool hits max_trees and spawns fail.

`TREEHOUSE_DIR` is an output, not a setting. Treehouse exports it into the subshell it opens to name the acquired worktree. Setting it does not steer pool resolution; only treehouse.toml does.

Non-goals

  • Not a git wrapper. Branching, committing, and pushing inside a slot are plain git; treehouse only owns the slot's lifecycle.
  • No structured output beyond status --json and get --lease --json. Errors are unstructured stderr lines and every failure exits 1, so branch on the message, not on a code. docs/axi-retrofit-spec.md in this repository specifies the fix.
  • Not a scheduler or a daemon. Nothing expires a lease, garbage-collects a dirty slot, or runs in the background; every state change is a command someone ran.
  • Not a flag reference. Use --help.

Verwandte Aufgaben