Skip to content
Closed
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: 9 additions & 0 deletions .agents/provision
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# Agent worktree provisioning hook: set this tree up (uv venv/sync, .envrc, direnv).
SELF=$0
case "$SELF" in
*/*) ;;
*) SELF=$(command -v -- "$SELF") ;;
esac
SCRIPT_DIR="$(cd "$(dirname "$SELF")" && pwd)"
exec "$SCRIPT_DIR/../bin/worktree" provision "$@"
36 changes: 30 additions & 6 deletions bin/worktree
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
# bin/worktree new --dir ../path <branch> # override the worktree directory
# bin/worktree ls # list worktrees (branch = value for rm)
# bin/worktree rm <branch|dir> [-b] # remove a worktree (-b also deletes the branch)
# bin/worktree provision [dir] # (re)provision an existing worktree in place
#
# `new` (aka create/add) provisions the worktree so mypy/pytest/pre-commit work
# out of the box (uv venv + `uv sync --all-groups`, `.envrc` symlink, direnv allow).
# `new` provisions the worktree so mypy/pytest/pre-commit work out of the box
# (uv venv + `uv sync --all-groups`, `.envrc` symlink, direnv allow) by calling
# `provision` — which is idempotent, so you can also run it on a bare tree
# (e.g. a plain `git worktree add`) to set it up after the fact.
#
# Examples:
# bin/worktree new feat/ivan/foo # new branch off current HEAD -> ../dimos-foo
Expand All @@ -18,10 +21,11 @@
# bin/worktree rm feat/ivan/foo -b # remove worktree and delete the branch
set -euo pipefail

REPO_ROOT=$(git rev-parse --path-format=absolute --git-common-dir)
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
REPO_ROOT=$(git -C "$SCRIPT_DIR" rev-parse --path-format=absolute --git-common-dir)
REPO_ROOT=$(cd "$(dirname "$REPO_ROOT")" && pwd) # main worktree root

usage() { sed -n '2,18p' "$0" | sed 's/^# \{0,1\}//'; }
usage() { sed -n '2,21p' "$0" | sed 's/^# \{0,1\}//'; }

# Default worktree dir for a branch: ../dimos-<last path component>, sanitized.
default_dir() {
Expand Down Expand Up @@ -125,6 +129,25 @@ cmd_add() {
GIT_LFS_SKIP_SMUDGE=1 git worktree add -b "$BRANCH" "$DIR" "${BASE:-HEAD}"
fi

cmd_provision "$DIR"
}

cmd_provision() {
# Provision an EXISTING worktree in place so mypy/pytest/pre-commit work out
# of the box: .envrc symlink + uv venv + `uv sync --all-groups` + direnv
# allow. Idempotent, so it's safe to re-run and `new` calls it after adding
# the tree; you can also point it at a bare `git worktree add` dir to set it
# up after the fact. With no argument, provisions the worktree this script
# lives in (not the caller's cwd).
local DIR="${1:-}" resolved=""
[[ -n "$DIR" ]] || DIR=$(git -C "$SCRIPT_DIR/.." rev-parse --show-toplevel)
# realpath -m (resolve non-existent paths) is GNU-only; fall back for BSD/macOS.
if resolved=$(realpath -m "$DIR" 2>/dev/null); then
DIR=$resolved
else
DIR=$(cd "$(dirname "$DIR")" && echo "$PWD/$(basename "$DIR")")
fi
[[ -d "$DIR" ]] || { echo "not a directory: $DIR" >&2; exit 1; }
cd "$DIR"

# Per-worktree env (.envrc is gitignored, so each worktree needs its own).
Expand All @@ -139,9 +162,9 @@ cmd_add() {
# the system toolchain directly.
echo ">>> uv venv + sync via $envrc (may take a few min on first run)"
if [[ "$envrc" == .envrc.nix ]]; then
nix develop --command bash -c 'uv venv --python 3.12 && uv sync --all-groups'
nix develop --command bash -c 'uv venv --python 3.12 --allow-existing && uv sync --all-groups'
else
uv venv --python 3.12 && uv sync --all-groups
uv venv --python 3.12 --allow-existing && uv sync --all-groups
fi

# Let direnv auto-activate it next time you cd in.
Expand All @@ -161,5 +184,6 @@ case "${1:-}" in
ls|list) shift; cmd_ls "$@" ;;
rm|remove) shift; cmd_rm "$@" ;;
new|create|add) shift; cmd_add "$@" ;;
provision) shift; cmd_provision "$@" ;;
*) echo "unknown command: $1 (did you mean 'new'?)" >&2; echo >&2; usage >&2; exit 1 ;;
esac
Loading