Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .claude/commands/start-work-cascade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
description: Start a cross-repo worktree cascade for a task
argument-hint: <task-name> [repo...]
---

Create one worktree per repo for this task, so cross-repo changes can be
developed in parallel with matching branch names.

Run:

```bash
start-work-cascade <task-name> [repo...]
```

Defaults to `reading-room open-agent agent-skills` under `~/src/personal`.
Each worktree lands at `<repo>/.claude/worktrees/<task-name>` on branch
`<task-name>` off `origin/main` — the same convention reading-room already
uses. Existing worktrees are skipped.

After the work is done and merged, clean up with:

```bash
worktree-cascade-done <task-name>
```

which removes each worktree and deletes the branch (refusing unmerged
branches, mirroring `just worktree-done`).

If the task touches repos outside the default set, pass them explicitly:
`/start-work-cascade my-task the-met-db wateralert-backend datalink`
22 changes: 22 additions & 0 deletions .claude/settings.local.json.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"permissions": {
"allow": [
"Bash(deno task:*)",
"Bash(deno check:*)",
"Bash(deno fmt:*)",
"Bash(deno lint:*)",
"Bash(deno test:*)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(git show:*)",
"Bash(git branch:*)",
"Bash(git worktree:*)",
"Bash(gh pr:*)",
"Bash(gh run:*)",
"Bash(gh api repos/tlockney/*)",
"Read(//tmp/**)",
"Read(//Users/tlockney/src/personal/**)"
]
}
}
59 changes: 59 additions & 0 deletions bin/start-work-cascade
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# start-work-cascade — create one worktree per repo for a task, across
# multiple repos, so a cross-repo change can be developed in parallel
# worktrees with matching branch names.
#
# Usage:
# start-work-cascade <task-name> [repo...]
#
# Default repos (personal): reading-room open-agent agent-skills
# Override with: START_WORK_CASCADE_REPOS="repo1 repo2" or pass repos as args.
#
# Each worktree lands at <repo>/.claude/worktrees/<task-name> on branch
# <task-name> off origin/main — the same convention reading-room already
# uses. Idempotent: existing worktrees are skipped, not recreated.
set -euo pipefail

TASK="${1:-}"
if [ -z "$TASK" ]; then
echo "usage: start-work-cascade <task-name> [repo...]" >&2
exit 1
fi
shift || true

if [ "$#" -gt 0 ]; then
REPOS=("$@")
elif [ -n "${START_WORK_CASCADE_REPOS:-}" ]; then
read -r -a REPOS <<< "$START_WORK_CASCADE_REPOS"
else
REPOS=(reading-room open-agent agent-skills)
fi

SRC_ROOT="${START_WORK_CASCADE_ROOT:-$HOME/src/personal}"

created=0
skipped=0
for repo in "${REPOS[@]}"; do
dir="$SRC_ROOT/$repo"
if [ ! -d "$dir/.git" ] && [ ! -f "$dir/.git" ]; then
echo "skip: $repo (not a repo at $dir)" >&2
continue
fi
dest="$dir/.claude/worktrees/$TASK"
if [ -e "$dest" ]; then
echo "skip: $repo (worktree exists: $dest)"
skipped=$((skipped + 1))
continue
fi
(
cd "$dir"
git fetch -q origin
git worktree add "$dest" -b "$TASK" origin/main
)
echo "created: $dest"
created=$((created + 1))
done

echo
echo "cascade ready: $created created, $skipped skipped"
echo "branches: $TASK (one per repo)"
44 changes: 44 additions & 0 deletions bin/worktree-cascade-done
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# worktree-cascade-done — finish a cascade: remove the worktree and branch
# in every repo that has one for the task. Mirrors the dotfiles
# `just worktree-done` semantics: -d (never -D) so unmerged branches are
# refused, and the launcher checkout is left alone.
#
# Usage:
# worktree-cascade-done <task-name> [repo...]
set -euo pipefail

TASK="${1:-}"
if [ -z "$TASK" ]; then
echo "usage: worktree-cascade-done <task-name> [repo...]" >&2
exit 1
fi
shift || true

if [ "$#" -gt 0 ]; then
REPOS=("$@")
elif [ -n "${START_WORK_CASCADE_REPOS:-}" ]; then
read -r -a REPOS <<< "$START_WORK_CASCADE_REPOS"
else
REPOS=(reading-room open-agent agent-skills)
fi

SRC_ROOT="${START_WORK_CASCADE_ROOT:-$HOME/src/personal}"

removed=0
for repo in "${REPOS[@]}"; do
dir="$SRC_ROOT/$repo"
dest="$dir/.claude/worktrees/$TASK"
if [ ! -d "$dest" ]; then
continue
fi
(
cd "$dir"
git worktree remove "$dest"
git branch -d "$TASK" 2>/dev/null || echo " $repo: branch $TASK not deleted (unmerged?)"
)
echo "removed: $dest"
removed=$((removed + 1))
done

echo "cascade done: $removed worktrees removed"
Loading