Skip to content
Merged
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
9 changes: 7 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ if git diff --cached --no-renames --name-only | grep -q '^ui/goose2/'; then
REPO_ROOT="$(pwd)"
echo "Running goose2 pre-commit checks..."

# Auto-format only staged files and re-stage them
STAGED_FILES=$(git diff --cached --no-renames --diff-filter=ACMR --name-only | grep '^ui/goose2/' | sed 's|^ui/goose2/||' || true)
# Auto-format only staged files that biome can process, then re-stage them.
# Exclude justfile and .swift files — biome doesn't understand these formats
# and would fail with "no files were processed" when only such files are staged.
STAGED_FILES=$(git diff --cached --no-renames --diff-filter=ACMR --name-only \
| grep '^ui/goose2/' \
| grep -v -E '(^ui/goose2/justfile$|\.swift$)' \
| sed 's|^ui/goose2/||' || true)
if [ -n "$STAGED_FILES" ]; then
cd ui/goose2
echo "$STAGED_FILES" | xargs npx biome format --write
Expand Down
3 changes: 2 additions & 1 deletion ui/goose2/biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"!src-tauri/plugins/*/permissions/{schemas,autogenerated}",
"!.agents",
"!.worktrees",
"!.claude/worktrees"
"!.claude/worktrees",
"!justfile"
]
},
"formatter": {
Expand Down
62 changes: 57 additions & 5 deletions ui/goose2/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,45 @@ dev-debug: setup
dev-frontend:
pnpm dev

# Kill the dev process (if running)
kill:
# Parse `git worktree list --porcelain` into tab-separated "path\tbranch" lines.
# Uses sub() instead of $2 so worktree paths containing spaces are preserved.
# Detached-HEAD worktrees (no branch line) are silently skipped.
_worktree_awk := '/^worktree / { sub(/^worktree /, ""); wt=$0 } /^branch refs\/heads\// { b=$2; sub(/^refs\/heads\//, "", b); print wt "\t" b }'

# Compute a stable vite port from a directory path passed as $1.
_port_cmd := "import hashlib,sys; h=int(hashlib.sha256(sys.argv[1].encode()).hexdigest(),16); print(10000+h%55000)"

# List worktrees with an active dev server
running:
#!/usr/bin/env bash
git worktree list --porcelain | awk '{{ _worktree_awk }}' \
| while IFS=$'\t' read -r wt branch; do
dir="$wt/ui/goose2"
port=$(python3 -c '{{ _port_cmd }}' "$dir")
if lsof -ti :"$port" &>/dev/null; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict running to actual node dev listeners

This check marks a branch as “running” whenever any process listens on the derived port. If a non-dev process happens to use that port, kill-all will include that branch and then fail in just kill (which rejects non-node), aborting the loop under set -euo pipefail and leaving real dev servers alive. running should validate the listener type (or kill-all should tolerate per-branch failures) before treating it as an active dev server.

Useful? React with 👍 / 👎.

echo "$branch"
fi
done

# Kill the dev process (if running). Optionally pass a branch name to kill another worktree's process.
kill branch="":
#!/usr/bin/env bash
set -euo pipefail

VITE_PORT={{ vite_port }}
if [[ -n "{{ branch }}" ]]; then
WORKTREE_PATH=$(git worktree list --porcelain \
| awk '{{ _worktree_awk }}' \
| awk -F'\t' -v branch="{{ branch }}" '$2 == branch { print $1; exit }')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Escape branch names before shell interpolation

kill injects {{ branch }} directly into double-quoted shell arguments (notably -v branch="{{ branch }}"), so shell expansion runs before awk receives the literal branch name. Git allows branch names containing $/backticks (for example, git check-ref-format --branch 'foo$(id)' succeeds), which means just kill <branch> can mis-resolve valid worktrees and kill-all can execute unintended command substitutions when iterating branch names. Pass the branch as a positional/env value inside the script instead of templating it directly into shell code.

Useful? React with 👍 / 👎.

if [[ -z "$WORKTREE_PATH" ]]; then
echo "No worktree found for branch '{{ branch }}'"
exit 1
fi
TARGET_DIR="$WORKTREE_PATH/ui/goose2"
VITE_PORT=$(python3 -c '{{ _port_cmd }}' "$TARGET_DIR")
else
VITE_PORT={{ vite_port }}
fi

PID=$(lsof -ti :"$VITE_PORT" 2>/dev/null | head -1) || true

if [[ -z "$PID" ]]; then
Expand All @@ -199,8 +232,27 @@ kill:
exit 1
fi

echo "Killing node (PID $PID) on port $VITE_PORT"
kill -9 "$PID"
PGID=$(ps -p "$PID" -o pgid= 2>/dev/null | tr -d ' ')
if [[ -z "$PGID" || "$PGID" == "0" || "$PGID" == "1" ]]; then
echo "Killing node (PID $PID) on port $VITE_PORT"
kill -9 "$PID"
else
echo "Killing process group $PGID (found via node PID $PID on port $VITE_PORT)"
kill -9 -"$PGID" 2>/dev/null || true
fi

# Kill all dev processes across all worktrees
kill-all:
#!/usr/bin/env bash
set -euo pipefail
branches=$(just running)
if [[ -z "$branches" ]]; then
echo "No running dev servers found"
exit 0
fi
while read -r branch; do
just kill "$branch" || true
done <<< "$branches"

# ── Utilities ────────────────────────────────────────────────

Expand Down
Loading