Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9255c64
ci: verify zig downloads, fix unit-tests gate, and refresh docs
arzafran Oct 1, 2026
309ebb3
fix: harden git probes, directory trust, and project config
arzafran Oct 1, 2026
24b88a1
fix: close-on-exec escrow fds and stop WAL write crashes
arzafran Oct 1, 2026
8d21845
fix: keep agent state and notifications consistent across workspaces
arzafran Oct 1, 2026
37547a6
fix: require consent for integration installs and stop CLI socket aut…
arzafran Oct 1, 2026
74d4164
fix: confirm before closing a window with running processes
arzafran Oct 1, 2026
23f61a3
fix: keep socket commands from stealing focus and tighten error contr…
arzafran Oct 1, 2026
ff88eee
test: add regression tests for window close, escrow fds, trust, CLI c…
arzafran Oct 1, 2026
023acc8
merge fix/sweep-infr
arzafran Oct 1, 2026
3c81201
merge fix/sweep-conf
arzafran Oct 1, 2026
50bb2dd
merge fix/sweep-sess
arzafran Oct 1, 2026
f73294a
merge fix/sweep-wksp
arzafran Oct 1, 2026
24334c6
merge fix/sweep-clix
arzafran Oct 1, 2026
03d6093
merge fix/sweep-shel
arzafran Oct 1, 2026
6b9f218
merge fix/sweep-sock
arzafran Oct 1, 2026
3097fb1
fix: wire cross-cluster follow-ups and remove dead render and image-o…
arzafran Oct 1, 2026
8e5d641
fix: repoint the socket's active window when a socket-created window …
arzafran Oct 1, 2026
83667e6
fix: move workspace up/down with its children so hierarchy ordering d…
arzafran Oct 1, 2026
dc1b14b
fix: skip superseded background shell-state reports so a stale prompt…
arzafran Oct 1, 2026
5cc18d3
test: use the shell-reported tty and a browser tab in the socket swee…
arzafran Oct 1, 2026
998bb9f
fix: let focus-window and close-window accept window refs
arzafran Oct 1, 2026
1864033
fix: remove the codex hooks lock file when an install is declined
arzafran Oct 1, 2026
ec02ad6
test: give the nested layout fixture a valid two-child split
arzafran Oct 1, 2026
c3baf5d
test: assert native tab-bar double-click no longer requests a new tab
arzafran Oct 1, 2026
73768cc
fix: keep the hosted inspector divider reachable when the inspector i…
arzafran Oct 1, 2026
df81a4c
test: observe window.list without the per-thread socket scope and com…
arzafran Oct 1, 2026
5813207
test: Programa Codex hook reinstall keeps later foreign groups in place
arzafran Oct 1, 2026
bd03a72
fix: update Programa's Codex hooks in place on reinstall
arzafran Oct 1, 2026
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
16 changes: 6 additions & 10 deletions .claude/commands/pull.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
# Pull

Pull latest main and update all submodules to their latest remote main. No commits, no pushes.
Pull latest main and check out the submodule commits main pins. No commits, no pushes.

## Steps

1. `git pull origin main`
2. For each submodule (ghostty):
- `cd <submodule>`
- `git fetch origin`
- Check if behind: `git rev-list HEAD..origin/main --count`
- If behind, merge: `git merge origin/main --no-edit`
- Do NOT push. We only land submodule changes via PRs.
- Go back to repo root
3. `git submodule update --init --recursive`
4. Report: current commit, which submodules were updated and by how many commits
2. `git submodule update --init --recursive`
- This checks out the exact `ghostty` commit the parent repo pins. Never merge the fork's
`main` into `ghostty/`: it is far ahead of the pin, and moving the pin pulls in unrelated
upstream changes (see `docs/ghostty-fork.md`).
3. Report: current commit, and whether the `ghostty` pin changed (`git diff HEAD@{1} --stat -- ghostty`)
9 changes: 4 additions & 5 deletions .claude/commands/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ completing with `conclusion: success`). There is no nightly/beta channel and no
step for ordinary changes — merge to `main`, let CI go green, and the release ships itself.

This command is only for **milestone marketing-version bumps** (e.g. `0.15.0` → `0.16.0`), which
are still done manually via a PR + optional `vX.Y.Z` tag marker.
are still done manually via a PR, with an optional `vX.Y.Z` tag as a marker.

## When to use this

Expand Down Expand Up @@ -43,14 +43,13 @@ are still done manually via a PR + optional `vX.Y.Z` tag marker.
- **Only include changes that affect the end-user experience** - things users will see, feel, or interact with
- Write clear, user-facing descriptions (not raw commit messages)
- **Credit contributors inline** (see Contributor Credits below)
- Also update the docs changelog page at `web/app/docs/changelog/page.tsx` with the same content
- If there are no user-facing changes, ask the user if they still want to bump the version

5. **Bump the version**
- Run `./scripts/bump-version.sh` (bumps minor by default; accepts `patch`, `major`, or an explicit version)

6. **Commit and push the release branch**
- Stage: `CHANGELOG.md`, `web/app/docs/changelog/page.tsx`, `GhosttyTabs.xcodeproj/project.pbxproj`
- Stage: `CHANGELOG.md`, `GhosttyTabs.xcodeproj/project.pbxproj`
- Commit message: `Bump version to X.Y.Z`
- Push: `git push -u origin release/vX.Y.Z`

Expand All @@ -76,8 +75,8 @@ are still done manually via a PR + optional `vX.Y.Z` tag marker.
git tag vX.Y.Z
git push origin vX.Y.Z
```
- This also triggers `release.yml` via its `push: tags: v*` trigger, publishing under that
exact tag.
- The tag is only a marker: `release.yml` runs on green `CI` for `main`, not on tags, so
pushing it publishes nothing.

11. **Monitor the release workflow**
- Watch: `gh run watch --repo darkroomengineering/programa`
Expand Down
32 changes: 13 additions & 19 deletions .claude/commands/sync-branch.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,33 @@
# Sync Branch

Get the current branch ready: update all submodules to their latest remote main, merge from main, and rebase.
Get the current branch ready: update main, rebase onto it, and check out the submodule commits main pins.

**Important: Never push automatically. Always ask the user before any push.**

## Steps

1. **Update submodules to latest**
- For each submodule (ghostty):
- `cd <submodule>`
- `git fetch origin`
- Check if behind: `git rev-list HEAD..origin/main --count`
- If behind, merge: `git merge origin/main --no-edit`
- Do NOT push submodules. We only land submodule changes via PRs.
- Go back to repo root

2. **Commit submodule updates on main**
1. **Update main**
- `git checkout main && git pull origin main`
- Check if any submodules changed: `git diff --name-only` (look for submodule paths)
- If changed, stage and commit: `git add ghostty && git commit -m "Update submodules: <brief description>"`
- **Do not push.** Ask the user if they want to push.

3. **Rebase current branch on main**
2. **Rebase current branch on main**
- `git checkout <original-branch>`
- `git rebase main`
- If conflicts, resolve them and continue
- **Do not push.** Ask the user if they want to force-push the rebased branch.

3. **Check out pinned submodules**
- `git submodule update --init --recursive`
- This checks out the exact `ghostty` commit the branch pins. Never merge the fork's `main`
into `ghostty/` to "update" it: the fork's `main` is far ahead of the pin, and moving the
pin pulls in unrelated upstream changes. Ghostty changes follow `docs/ghostty-fork.md`.

4. **Report status**
- Show what submodules were updated and by how many commits
- Show whether the `ghostty` pin differs from main
- Show if rebase was clean or had conflicts
- Show current branch and commit

## Notes

- Never commit a submodule pointer in the parent repo unless the submodule commit is reachable from the submodule's remote main (per CLAUDE.md pitfall about orphaned commits)
- If no submodules need updating and main has no new commits, just say "Already up to date"
- If on main already, skip step 3
- Never commit a submodule pointer in the parent repo unless the submodule commit is pushed to the fork (per CLAUDE.md pitfall about orphaned commits)
- If main has no new commits, just say "Already up to date"
- If on main already, skip step 2
2 changes: 1 addition & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ For UI or behavior changes, include a short demo video (GitHub upload, Loom, or

## Checklist

- [ ] I tested the change locally
- [ ] Tested via CI and, for UI or behavior changes, a tagged build (`./scripts/reload.sh --tag <name>`)
- [ ] I added or updated tests for behavior changes
- [ ] I updated docs/changelog if needed
- [ ] I requested bot reviews after my latest commit (copy/paste block above or equivalent)
Expand Down
34 changes: 19 additions & 15 deletions .github/workflows/build-ghosttykit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ on:
- "scripts/ensure-ghosttykit.sh"
- "scripts/required-zig-version.sh"
- "scripts/download-prebuilt-ghosttykit.sh"
- "scripts/update-ghosttykit.sh"
- "scripts/install-zig.sh"
- "scripts/zig-macos-aarch64.sha256"
- ".github/workflows/build-ghosttykit.yml"
pull_request:
paths:
Expand All @@ -25,7 +26,8 @@ on:
- "scripts/ensure-ghosttykit.sh"
- "scripts/required-zig-version.sh"
- "scripts/download-prebuilt-ghosttykit.sh"
- "scripts/update-ghosttykit.sh"
- "scripts/install-zig.sh"
- "scripts/zig-macos-aarch64.sha256"
- ".github/workflows/build-ghosttykit.yml"

concurrency:
Expand Down Expand Up @@ -85,6 +87,20 @@ jobs:
export DEVELOPER_DIR="$XCODE_DIR"
xcodebuild -version

- name: Resolve zig version
if: steps.check-release.outputs.exists == 'false'
id: zig-version
run: printf 'version=%s\n' "$(./scripts/required-zig-version.sh)" >> "$GITHUB_OUTPUT"

# install-zig.sh re-checks the tarball against scripts/zig-macos-aarch64.sha256
# on every run, so a cache hit never skips the checksum.
- name: Cache zig toolchain tarball
if: steps.check-release.outputs.exists == 'false'
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: ~/.cache/programa-zig-dist
key: zig-dist-macos-arm64-${{ steps.zig-version.outputs.version }}

- name: Cache Zig packages
if: steps.check-release.outputs.exists == 'false'
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
Expand All @@ -97,19 +113,7 @@ jobs:
if: steps.check-release.outputs.exists == 'false'
run: |
set -euo pipefail
ZIG_REQUIRED="$(./scripts/required-zig-version.sh)"
if command -v zig >/dev/null 2>&1 && [ "$(zig version 2>/dev/null)" = "$ZIG_REQUIRED" ]; then
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo mkdir -p /usr/local/bin /usr/local/lib
sudo cp -f /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/lib /usr/local/lib/zig
export PATH="/usr/local/bin:$PATH"
zig version
fi
./scripts/install-zig.sh
cd ghostty && zig build -Demit-xcframework=true -Demit-macos-app=false -Dxcframework-target=native -Doptimize=ReleaseFast

- name: Package xcframework
Expand Down
27 changes: 13 additions & 14 deletions .github/workflows/ci-macos-compat.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,21 +97,20 @@ jobs:
path: GhosttyKit.xcframework
key: ghosttykit-v3-${{ steps.ghostty-revision.outputs.revision }}

- name: Resolve zig version
id: zig-version
run: printf 'version=%s\n' "$(./scripts/required-zig-version.sh)" >> "$GITHUB_OUTPUT"

# install-zig.sh re-checks the tarball against scripts/zig-macos-aarch64.sha256
# on every run, so a cache hit never skips the checksum.
- name: Cache zig toolchain tarball
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: ~/.cache/programa-zig-dist
key: zig-dist-macos-arm64-${{ steps.zig-version.outputs.version }}

- name: Set up required Zig
run: |
ZIG_REQUIRED="$(./scripts/required-zig-version.sh)"
if command -v zig >/dev/null 2>&1 && [ "$(zig version 2>/dev/null)" = "$ZIG_REQUIRED" ]; then
echo "zig ${ZIG_REQUIRED} already installed"
else
echo "Installing zig ${ZIG_REQUIRED} from tarball"
curl -fSL "https://ziglang.org/download/${ZIG_REQUIRED}/zig-aarch64-macos-${ZIG_REQUIRED}.tar.xz" -o /tmp/zig.tar.xz
tar xf /tmp/zig.tar.xz -C /tmp
sudo mkdir -p /usr/local/bin /usr/local/lib
sudo cp -f /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/zig /usr/local/bin/zig
sudo cp -rf /tmp/zig-aarch64-macos-${ZIG_REQUIRED}/lib /usr/local/lib/zig
export PATH="/usr/local/bin:$PATH"
zig version
fi
run: ./scripts/install-zig.sh

- name: Download pre-built GhosttyKit.xcframework
if: steps.cache-ghosttykit.outputs.cache-hit != 'true'
Expand Down
Loading
Loading