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
42 changes: 42 additions & 0 deletions .claude/skills/reload-architect/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
name: reload-architect
description: Rebuild the Architect app from the current worktree (committed + uncommitted local changes) and relaunch it, so the running app reflects in-progress code. Use when the user wants to see/test their Architect changes in the actual app — e.g. "reload architect", "rebuild and restart architect", "run my changes", "relaunch with my edits", "I closed and reopened but don't see my changes".
---

# Reload Architect

Goal: get the running Architect to be the build of **this worktree's current code** (including uncommitted changes). Editing source and relaunching the *installed* app does nothing — the `.app` must be rebuilt. This skill does build → quit → relaunch in one step via `scripts/dev-reload.sh`.

## Steps

1. Find the repo root and confirm we're in the Architect repo:
```bash
ROOT="$(git rev-parse --show-toplevel)" && test -f "$ROOT/scripts/dev-reload.sh" && echo "$ROOT"
```
If that fails, tell the user to run the skill from inside the Architect repo (or a worktree of it) and stop.

2. Run the reload from the repo root:
```bash
bash "$ROOT/scripts/dev-reload.sh"
```
This builds (debug), packages the `.app`, quits the running Architect, swaps the fresh build into `/Applications`, and relaunches it. The relaunch is detached, so it completes on its own.

3. Report the outcome:
- On success, tell the user Architect will close and reopen on the fresh build, and remind them what changed (branch + the local edits being tested).
- If the build fails (`zig build` error), surface the compiler error and offer to fix it. Do **not** leave them thinking it reloaded.

## If the toolchain isn't reachable from your shell

The build needs the Nix dev shell (`zig`). If `scripts/dev-reload.sh` exits with **"neither 'zig' nor 'nix' is on PATH"**, then this agent's shell can't reach the build toolchain (it lives in the user's login/direnv shell, not necessarily yours). In that case, do **not** keep retrying — tell the user to run it in their own session instead, where the toolchain is loaded:

```
!just reload
```

(or `!./scripts/dev-reload.sh`). The `!` prefix runs it in the user's interactive session, and the output comes back into the conversation.

## Notes

- Works in any Architect worktree — it resolves the repo root from the current directory, so it reloads whichever branch/worktree you're in.
- Safe to run while Architect is the frontmost app or in the background; the quit+relaunch is detached and survives even if it was launched from inside the Architect being replaced.
- This replaces `/Applications/Architect.app`, so Spotlight/Dock launches afterward also get the fresh build — no "which version am I running?" ambiguity.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Architect solves this with a grid view that keeps all your agents visible, with
- **Status highlights** — agents glow when awaiting approval or done, so you never miss a prompt
- **Agent session persistence** — when you quit Architect, any running Claude, Codex, or Gemini agents are gracefully terminated and their session IDs saved; on next launch the agents resume automatically where they left off
- **Dynamic grid** — starts with a single terminal in full view; press ⌘N to add a terminal after the current one, and closing terminals compacts the grid forward
- **Grid view** — keep all agents visible simultaneously, expand any one to full screen
- **Grid view** — keep all agents visible simultaneously; single-click a pane to move focus to it (no shell is spawned), double-click to expand it to full screen
- **Worktree picker** (⌘T) — quickly `cd` into git worktrees for parallel agent work on separate branches; new worktrees are created outside the repo tree (configurable via `[worktree]` in `config.toml`) with automatic post-create initialization
- **Recent folders** (⌘O) — quickly `cd` into recently visited directories with instant search filtering (start typing to narrow the list), substring highlighting, arrow key navigation, and ⌘1–⌘9 quick selection
- **Diff review comments** — click diff lines in the ⌘D overlay to leave inline comments with multiline wrapping, then send them all to a running agent (or start one) with the "Send to agent" button
Expand Down
4 changes: 2 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Note: Runtime window position and size are saved to `persistence.toml` and take

```toml
[theme]
background = "#0E1116" # Terminal background color
background = "#262624" # Terminal background color
foreground = "#CDD6E0" # Default text color
selection = "#1B2230" # Selection highlight color
accent = "#61AFEF" # Accent color (focused borders, UI elements)
Expand All @@ -70,7 +70,7 @@ The configured theme colors are reused across terminal chrome and overlay surfac

| Setting | Default | Description |
|---------|---------|-------------|
| `background` | `#0E1116` | Dark gray background |
| `background` | `#262624` | Warm dark gray background |
| `foreground` | `#CDD6E0` | Light gray text |
| `selection` | `#1B2230` | Darker blue for selections |
| `accent` | `#61AFEF` | Blue accent for focus indicators |
Expand Down
12 changes: 12 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ just run
zig build run
```

Reload the installed app with your in-progress changes:
```bash
just reload
# or
./scripts/dev-reload.sh
```
This rebuilds from the current worktree (committed + uncommitted changes), quits the
running Architect, swaps the fresh build into `/Applications/Architect.app`, and
relaunches it. Use it to avoid restarting a stale binary after editing source — relaunching
the installed app alone never picks up source changes. The Claude Code skill
`/reload-architect` runs the same script.

## Dependencies and Tooling

- **ghostty-vt** is fetched as a pinned tarball via the Zig package manager (`build.zig.zon`).
Expand Down
4 changes: 4 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ run:
run-release:
zig build run -Doptimize=ReleaseFast

# Rebuild from the current worktree, then quit and relaunch the installed app.
reload:
./scripts/dev-reload.sh

lint:
#!/usr/bin/env bash
set -euo pipefail
Expand Down
133 changes: 133 additions & 0 deletions scripts/dev-reload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env bash
# Rebuild Architect from the CURRENT worktree (committed + uncommitted changes)
# and relaunch it, so you never again restart a stale binary.
#
# Flow: build (debug) -> package an .app bundle -> quit the running Architect ->
# swap the fresh bundle into /Applications -> relaunch via `open`.
#
# The quit+relaunch runs in a detached subprocess (nohup/disown) so it survives
# even if this script is itself running inside the Architect being replaced.
set -euo pipefail

ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
if [[ -z "$ROOT" || ! -f "$ROOT/scripts/bundle-macos.sh" ]]; then
echo "error: run this from inside the Architect repo (no scripts/bundle-macos.sh found)" >&2
exit 1
fi
cd "$ROOT"

# --- Ensure a working build toolchain + SDK ---
# Preferred path: a Nix dev shell provides zig, a linkable SDK, and SDL3. If
# zig is not on PATH but nix is, re-enter the flake dev shell and re-run there.
if ! command -v zig >/dev/null 2>&1; then
if command -v nix >/dev/null 2>&1; then
exec nix develop "$ROOT" -c "$0" "$@"
fi
echo "error: 'zig' is not on PATH and 'nix' is unavailable." >&2
echo " Install zig (or symlink it onto PATH), or run from your Nix dev shell." >&2
exit 1
fi

# Native (Homebrew) build setup. Each line only fills in a value that isn't
# already set, so this is a no-op inside a Nix dev shell that already provides them.

# SDL3 / SDL3_ttf: build.zig reads *_INCLUDE_PATH and derives the lib dir (../lib).
if command -v brew >/dev/null 2>&1; then
: "${SDL3_INCLUDE_PATH:=$(brew --prefix sdl3 2>/dev/null)/include}"
: "${SDL3_TTF_INCLUDE_PATH:=$(brew --prefix sdl3_ttf 2>/dev/null)/include}"
export SDL3_INCLUDE_PATH SDL3_TTF_INCLUDE_PATH
fi

# Zig 0.15.2 cannot link the macOS 26.x SDK family (ziglang/zig#31756). Redirect
# SDK discovery to the 15.4 SDK when present and DEVELOPER_DIR isn't already set.
legacy_sdk="/Library/Developer/CommandLineTools/SDKs/MacOSX15.4.sdk"
if [ -z "${DEVELOPER_DIR:-}" ] && [ -d "$legacy_sdk" ]; then
wr="$ROOT/.tmp/macos-sdk-workaround"
mkdir -p "$wr/bin" "$wr/developer/SDKs" "$wr/developer/usr/bin"
ln -sfn "$legacy_sdk" "$wr/developer/SDKs/MacOSX.sdk"
cat > "$wr/developer/usr/bin/xcrun" <<XCRUN
#!/bin/sh
if [ "\$1" = "--sdk" ] && [ "\$2" = "macosx" ] && [ "\$3" = "--show-sdk-path" ] && [ "\$#" -eq 3 ]; then
printf '%s\n' '$legacy_sdk'
exit 0
fi
exec env DEVELOPER_DIR= /usr/bin/xcrun "\$@"
XCRUN
chmod +x "$wr/developer/usr/bin/xcrun"
ln -sfn "$wr/developer/usr/bin/xcrun" "$wr/bin/xcrun"
case ":$PATH:" in
*":$wr/bin:"*) ;;
*) export PATH="$wr/bin:$PATH" ;;
esac
export DEVELOPER_DIR="$wr/developer"
fi

# Default to an optimized ReleaseFast build — this replaces your daily-driver
# /Applications app, so it must not be a slow Debug build. Pass --debug (or set
# DEV_RELOAD_DEBUG=1) only when you specifically need debug assertions/symbols.
build_debug=false
for arg in "$@"; do
[ "$arg" = "--debug" ] && build_debug=true
done
[ -n "${DEV_RELOAD_DEBUG:-}" ] && build_debug=true

branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo '?')"
if [ "$build_debug" = true ]; then
echo "==> Building Architect (Debug) from '$branch' + local changes..."
zig build
else
echo "==> Building Architect (ReleaseFast) from '$branch' + local changes..."
zig build -Doptimize=ReleaseFast
fi

# Build-only mode: verify the build without touching the running app.
if [ -n "${DEV_RELOAD_BUILD_ONLY:-}" ]; then
echo "==> DEV_RELOAD_BUILD_ONLY set: built successfully, leaving the running app untouched."
exit 0
fi

echo "==> Packaging app bundle..."
staging="$(mktemp -d)"
trap 'rm -rf "$staging"' EXIT
if [ "$build_debug" = true ]; then
./scripts/bundle-macos.sh zig-out/bin/architect "$staging" zig-out/bin/architect-mcp --debug
else
./scripts/bundle-macos.sh zig-out/bin/architect "$staging" zig-out/bin/architect-mcp
fi

# Hand the swap+relaunch to a detached process. It outlives this shell, so the
# new Architect comes up even if quitting the old one tears down our terminal.
echo "==> Quitting Architect (waiting for agents to shut down + flush) and relaunching..."
old_pid="$(pgrep -x architect | head -1 || true)"
# Variables below are for the inner shell, not this one (intentional single quotes).
# shellcheck disable=SC2016
nohup bash -c '
set -e
staging="$1"
old_pid="$2"
# Quit gracefully, then block until the old process exits. This matters for
# agent resume: on quit, Architect Ctrl+Cs each running agent so Claude
# flushes its session to disk before exiting. Force-killing instead kills the
# agents mid-turn, so the next `claude --resume` reloads a rewound transcript.
# caffeinate -w waits on the process-exit event (no polling, no re-sending the
# quit). A watchdog force-kills ONLY if the teardown truly hangs (~5 min),
# which loses agent state.
osascript -e "quit app \"Architect\"" 2>/dev/null || true
if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
( sleep 300; kill -TERM "$old_pid" 2>/dev/null; sleep 2; kill -KILL "$old_pid" 2>/dev/null ) &
watchdog=$!
caffeinate -w "$old_pid" 2>/dev/null || true
kill "$watchdog" 2>/dev/null || true
wait "$watchdog" 2>/dev/null || true
fi
rm -rf "/Applications/Architect.app"
mv "$staging/Architect.app" "/Applications/Architect.app"
rmdir "$staging" 2>/dev/null || true
open "/Applications/Architect.app"
' _ "$staging" "$old_pid" >/dev/null 2>&1 &
disown

# The detached job owns the staging dir now; do not let our EXIT trap delete it.
trap - EXIT

echo "==> Done. Architect will close and reopen on the fresh build."
Loading