Skip to main content
ClaudeWave
Skill4.7k repo starsupdated 3d ago

gitbutler-stacks

Hard-won GitButler mechanics for multi-lane work in this repo — committing to a specific lane in a stack, spreading a pile of edits back across an existing stack, ordering a stack and setting PR bases, and recovering from a scrambled workspace. Use when working with stacked branches, when `but rub`/`but absorb`/`but commit --only` mis-routes a change, when a stack collapses or a commit lands on the wrong lane, or when a hunk gets dropped. Not needed for ordinary single-lane work.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/Agenta-AI/agenta /tmp/gitbutler-stacks && cp -r /tmp/gitbutler-stacks/.agents/skills/gitbutler-stacks ~/.claude/skills/gitbutler-stacks
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# GitButler stacks (Agenta)

Everyday `but` usage — `but status`, `but commit`, `but push`, `but absorb` — is covered by
the root `AGENTS.md`. This skill is the multi-lane layer: it only matters once you have a
**stack** of branches, which is roughly 6% of the work here.

**Read the first rule first.** Most of what follows exists to undo damage that only happens
when edits are made first and assigned to lanes afterward. Committing each change to its lane
as you go avoids nearly all of it.

## Prefer one lane at a time

Land a lane before starting the next. A single lane per session needs none of the machinery
below — no `--only` staging discipline, no stash isolation, no oplog restores. Reach for a
stack only when a change genuinely depends on another in-flight branch's commits.

Sync a lane with **rebase, not merge**. Merge commits between branches are what collapse a
series (see the first hard-won gotcha).

## Committing to specific lanes in a stack (the part that bites)

Changes are assigned to the **stack**, not to an individual branch. `but rub <file>
<branch>` and `but commit <branch> --only` both operate on the stack's *assigned-changes*
set — `--only` commits **whatever is currently assigned** to the named branch, regardless
of which branch name you used when staging. So:

- **Never pre-stage multiple lanes' files and then commit them one lane at a time.** The
  first `but commit --only` sweeps the entire assigned set into that one branch (the others
  end up empty or scrambled). Instead, work **one lane at a time**: assign exactly that
  lane's files → `but commit <branch> --only` → **verify** → then assign the next lane's
  files. Keep the assigned set equal to exactly one lane's files at each commit.
- **Verify every commit immediately:** `git show --stat --name-only <branch>`. If a file
  from another lane leaked in, stop and fix before continuing.
- **`but rub` by path goes stale after any mutation.** Every `but` mutation kicks a
  background sync that invalidates the path index, so the *next* path-based
  `but rub <path> ...` often fails with "Source '<path>' not found". Use the stable
  **cliId** instead (the 2-4 char code in `but status` / `but status --json`):
  `but rub <cliId> <target>`. cliIds survive across the sync; paths don't.
- **Splitting one file across two stacked lanes** (e.g. `routers.py` where the lower lane
  owns half the edit and the upper lane the other half): you cannot split mixed hunks
  reliably. Instead use sequential working-tree states — make the file the lower lane's
  version, commit it to the lower lane; then edit the file to add the upper lane's delta
  and `but rub <fileCliId> <upperCommitCliId>` to amend that delta into the upper commit.
- The **branch ref can diverge from the workspace-applied commit** mid-session (after
  absorb/amend/rebase). The **working tree is the source of truth**; `but push` pushes the
  applied state. Don't panic if `git diff <branch> -- <file>` shows a delta while
  `git status` is clean — verify against `git show "<branch>:<file>"` and re-push.

## Spreading a pile of edits back across an existing stack (the reliable way)

When you have a working tree full of changes that belong to *many* lanes of an
already-pushed stack (e.g. a review-pass that fixes files across wp0…wp4), do NOT try to
assign-and-commit lane by lane against the live working tree — `but rub`/`but commit
--only`/`but absorb` all route by **hunk dependency across the whole stack**, and they
mis-route in three predictable ways that scramble the stack and waste hours:

- **New (untracked) files ignore the target branch.** `but rub <newFileCliId> <lowerLane>`
  dumps every untracked file into the **topmost** lane's staging group, not the one you
  named. New files cannot be assigned to a lower lane at all.
- **`but absorb` sends anything it can't attribute to the docs/top lane.** Renamed files,
  new files, and hunks in line-regions the target lane's original commit never touched all
  fall to the "last commit in the primary lane" fallback — silently the wrong lane.
- **A multi-hunk file whose hunks belong to different commits won't commit whole.** `but
  commit <lane>` / `-p <file>` commits the attributable hunks and **drops the rest**
  ("Warning: Some selected changes could not be committed"), often leaving an empty
  no-change commit. Splitting one file across lower+upper lanes is the §"Splitting one file
  across two stacked lanes" case above.

The technique that actually works — **git-stash isolation, one lane at a time:**

1. `but oplog snapshot -m "pristine"` then `git stash push -u` everything. Working tree
   clean, every lane back at its remote tip. This snapshot is your only safe recovery
   point — `but oplog restore` it whenever a step scrambles the stack (it does, often).
2. For each lane, restore **only that lane's files** into the clean tree:
   tracked-modified from `git checkout 'stash@{0}' -- <paths>`; **untracked/new** files
   from the stash's untracked parent `git checkout 'stash@{0}^3' -- <paths>`; reproduce
   deletes/renames with `git rm`. Verify with `git status` that ONLY that lane's files are
   present — nothing else.
3. Land them: if every hunk dependency-attributes cleanly to existing commits in that lane
   (and the lane below), a blanket `but absorb` (no source — the tree holds only this
   lane's files, so there's nothing to mis-route) puts each hunk in the right commit. If
   the lane needs **new** files, use `but commit <lane>` instead (the new files have only
   this lane to land in because the tree is isolated).
4. **Verify the lane's tip TREE, not the diff** (commit history within a lane doesn't
   matter; the resulting tree does): `git show <lane>:<file>` for each touched file, plus
   `git ls-tree -r <lane> <dir>` for moves/deletes. Then check the lanes *above* it for
   resurrected deletes / phantom files (the rebase re-materializes deleted dirs as
   untracked — `rm -rf` that residue; it's noise, the tip
add-announcementSkill

Helps add announcement cards to the sidebar banner system. Use when adding changelog entries, feature announcements, updates, or promotional banners to the Agenta sidebar. Handles both simple changelog entries and complex custom banners.

add-harnessSkill

Playbook for adding a new coding-agent harness to Agenta (Codex, Hermes, Gemini, OpenCode, ...). Use when starting, planning, or reviewing a new-harness project. Covers the readiness audit of prior art, the spike-first milestone plan, the full integration-surface checklist, the per-harness variance axes to probe, and the process/communication contract with Mahmoud. Living document: every harness project appends its lessons to resources/LESSONS.md.

agent-release-gateSkill

>-

agenta-package-practicesSkill

Where to put frontend code (package vs app layer) and how to use the @agenta/* packages. Use when authoring or moving code in web/packages, choosing between @agenta/ui, @agenta/entities, @agenta/entity-ui, @agenta/shared, @agenta/playground, using molecules, loadable/runnable bridges, the EntityPicker, or writing package unit tests.

create-changelog-announcementSkill

Use this skill to create and publish changelog announcements for new features, improvements, or bug fixes. This skill handles the complete workflow - creating detailed changelog documentation pages, adding sidebar announcement cards, and ensuring everything follows project standards. Use when the user mentions adding changelog entries, documenting new features, creating release notes, or announcing product updates.

implement-featureSkill

Drive a researched and planned feature to a landed, tested change. Use after plan-feature has produced a docs/design/<project>/ workspace and the user says "implement it", "build the plan", "run the plan", or "let's ship this". Orchestrates refresh-plan, implement, review, a debug-local-deployment loop, and a test loop across the daytona / local-pi / claude x SDK / UI matrix, then documentation and a GitButler stacked branch. The orchestrator stays in the loop and spins narrow subagents for each phase.

mobile-app-structureSkill

Feature-folder layout, states/ convention, and data-flow rules for the Agenta mobile app (web/mobile). Use when creating or moving files under web/mobile, deciding where a component lives, adding a new feature or screen, or wiring data into mobile components.

mobile-motion-patternsSkill

Motion design rules for the Agenta mobile app (web/mobile) — the shared presets in src/lib/motion, when to animate, and reduced-motion requirements. Use when adding any animation or transition under web/mobile, animating navigation, sheets, skeletons, or list/chat surfaces.