Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
7684c3f
Complete pending terminal, session, skills, and MCP changes
igorcosta Nov 10, 2026
c4fe545
Preserve provider selection and bound delegated tool requests
igorcosta Nov 10, 2026
7c350e2
Validate native terminal startup and updated session contracts
igorcosta Nov 10, 2026
90caded
Keep native terminal fixtures within viewport and socket limits
igorcosta Nov 10, 2026
41934c6
Make native terminal evidence and lock contention tests deterministic
igorcosta Nov 10, 2026
9e15448
Read VS Code terminal buffers without replaying accessibility announc…
igorcosta Nov 10, 2026
bbbcbe1
Assert interactive readiness before advancing terminal scenarios
igorcosta Nov 10, 2026
7737a86
Track native VS Code windows while reading current terminal rows
igorcosta Nov 10, 2026
f110614
Match native terminal row geometry to xterm text scaling
igorcosta Nov 10, 2026
5d6f637
Wait for complete native terminal frames before asserting content counts
igorcosta Nov 10, 2026
c2c4a1c
Read VS Code terminal content through focused native clipboard copies
igorcosta Nov 10, 2026
c42e216
Capture bounded native terminal copy and write timing diagnostics
igorcosta Nov 10, 2026
69c88df
Coordinate streamed resize observation within the native settling dea…
igorcosta Nov 10, 2026
81c1812
Preserve composer input across asynchronous command completion
igorcosta Nov 10, 2026
31c38ad
Document composer ownership in the combined CLI integration
igorcosta Nov 10, 2026
cc24d92
Track late terminal reflow with authoritative observation state
igorcosta Nov 10, 2026
e7010af
Prepare native Code windows with independent edge resize targets
igorcosta Nov 10, 2026
1e4b713
Read fresh native terminal copies before entering the fallback waiter
igorcosta Nov 10, 2026
0afefff
Use a graphical Code profile for native buffer-copy qualification
igorcosta Nov 10, 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
12 changes: 9 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ on:
- beta
- 'cto/**'
- 'nikita/**'
- 'repair/**'
workflow_dispatch:

concurrency:
Expand Down Expand Up @@ -81,6 +82,8 @@ jobs:
shard: [1, 2, 3]
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v7
Expand All @@ -95,7 +98,7 @@ jobs:

- name: Install build tools (Ubuntu)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down Expand Up @@ -131,14 +134,17 @@ jobs:
bun-version-file: package.json

- name: Install build tools (Ubuntu)
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build CLI for terminal tests
run: bun run build

- name: Prepare pinned Zit for tmux isolation tests
run: node --input-type=module -e "import { installZit } from './scripts/install-zit.mjs'; await installZit({ force:true });"

- name: Run built terminal tests
run: bun run test:tuistory -- --shard=${{ matrix.shard }}/4

Expand All @@ -164,7 +170,7 @@ jobs:

- name: Install build tools (Ubuntu)
if: runner.os == 'Linux'
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/full-proof.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,16 @@ jobs:
bun-version-file: package.json

- name: Install native build tools
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep
run: sudo apt-get update && sudo apt-get install -y build-essential python3 make g++ ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Prepare built CLI fixtures
run: bun run build

- name: Prepare pinned Zit for tmux isolation tests
run: node --input-type=module -e "import { installZit } from './scripts/install-zit.mjs'; await installZit({ force:true });"

- name: Run complete proof
run: bun run proof
11 changes: 9 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ jobs:
shard: [1, 2, 3]
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v7
Expand All @@ -202,7 +204,7 @@ jobs:
bun-version-file: package.json

- name: Install ripgrep
run: sudo apt-get update && sudo apt-get install -y ripgrep
run: sudo apt-get update && sudo apt-get install -y ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile
Expand Down Expand Up @@ -240,14 +242,17 @@ jobs:
bun-version-file: package.json

- name: Install ripgrep
run: sudo apt-get update && sudo apt-get install -y ripgrep
run: sudo apt-get update && sudo apt-get install -y ripgrep tmux

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Build CLI for terminal tests
run: bun run build

- name: Prepare pinned Zit for tmux isolation tests
run: node --input-type=module -e "import { installZit } from './scripts/install-zit.mjs'; await installZit({ force:true });"

- name: Run built terminal tests
run: bun run test:tuistory -- --shard=${{ matrix.shard }}/4

Expand Down Expand Up @@ -572,10 +577,12 @@ jobs:
chmod +x "$binary"
file "$binary"
codesign --verify --strict --verbose=4 "$binary"
codesign --verify --strict -R=notarized --check-notarization "$binary"
"$binary" --version < /dev/null
chmod +x "$ahtraces"
file "$ahtraces"
codesign --verify --strict --verbose=4 "$ahtraces"
codesign --verify --strict -R=notarized --check-notarization "$ahtraces"
"$ahtraces" --version < /dev/null
mkdir -p computer-use-verification
tar -xzf "$computer_use_archive" -C computer-use-verification
Expand Down
130 changes: 130 additions & 0 deletions .github/workflows/terminal-compatibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
name: Terminal compatibility

on:
pull_request:
paths:
- 'src/ui/**'
- 'src/testing/**'
- 'src/utils/tmux.ts'
- 'src/startup/cliOptions.ts'
- 'src/index.ts'
- 'package.json'
- 'bun.lock'
- 'tests/tuistory/*terminal*'
- 'tests/tuistory/*resize*'
- 'tests/tuistory/*tmux*'
- 'tests/testing/nativeTerminal.test.ts'
- '.github/workflows/terminal-compatibility.yml'
workflow_dispatch:

permissions:
contents: read

concurrency:
group: terminal-compatibility-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
tmux:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24
package-manager-cache: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- run: sudo apt-get update && sudo apt-get install -y build-essential python3 ripgrep tmux
- run: bun install --frozen-lockfile
- run: bun run build
- name: Prepare pinned Zit for real isolation tests
run: node --input-type=module -e "import { installZit } from './scripts/install-zit.mjs'; await installZit({ force:true });"
- name: Test compiled startup and rapid resize through real tmux
run: bun run test:tuistory tests/tuistory/tmux-startup.tuistory.test.ts tests/tuistory/resize-flicker.tuistory.test.ts

native-macos:
runs-on: macos-26
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
terminal: [iterm2, ghostty, cmux, vscode]
env:
AUTOHAND_NATIVE_TERMINAL: ${{ matrix.terminal }}
HOMEBREW_NO_AUTO_UPDATE: '1'
AUTOHAND_SKIP_COMPUTER_CONTROL_INSTALL: '1'
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: actions/setup-node@v7
with:
node-version: 24
package-manager-cache: false
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: package.json
- name: Install native terminal and UI test build tools
shell: bash
run: |
set -euo pipefail
brew install xcodegen ripgrep tmux
case "$AUTOHAND_NATIVE_TERMINAL" in
iterm2) brew install --cask iterm2; terminal_app=/Applications/iTerm.app ;;
ghostty) brew install --cask ghostty; terminal_app=/Applications/Ghostty.app ;;
cmux) brew install --cask cmux; terminal_app=/Applications/cmux.app ;;
vscode) brew install --cask visual-studio-code; terminal_app='/Applications/Visual Studio Code.app' ;;
esac
codesign --verify --deep --strict "$terminal_app"
spctl --assess --type execute --verbose "$terminal_app"
# Approve only the verified app on this disposable VM for unattended launch.
xattr -dr com.apple.quarantine "$terminal_app"
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -f "$terminal_app"
defaults read "$terminal_app/Contents/Info" CFBundleIdentifier
system_profiler SPDisplaysDataType
stat -f 'Console user: %Su' /dev/console
mkdir -p .artifacts/native-terminal
brew info --json=v2 --installed > .artifacts/native-terminal/installed-versions.json
# These preferences belong only to this disposable Actions VM.
defaults write com.googlecode.iterm2 EnableAPIServer -bool false
defaults write com.googlecode.iterm2 PromptOnQuit -bool false
defaults write com.googlecode.iterm2 SUEnableAutomaticChecks -bool false
defaults write com.googlecode.iterm2 NSQuitAlwaysKeepsWindows -bool false
defaults write com.googlecode.iterm2 ApplePersistenceIgnoreState -bool true
- run: bun install --frozen-lockfile
- name: Verify native automation boundary and disposable profiles
run: bun run test tests/testing/nativeTerminal.test.ts tests/testing/resizeWriteMetadata.test.ts tests/testing/resizeStreamGate.test.ts
- run: bun run build
- name: Run Tuistory with native XCTest window and accessibility checks
run: bun run test:tuistory tests/tuistory/native-terminal.tuistory.test.ts
- name: Export native screen captures
if: always()
shell: bash
run: |
result=".artifacts/native-terminal/$AUTOHAND_NATIVE_TERMINAL/NativeTerminal.xcresult"
if [ -d "$result" ]; then
xcrun xcresulttool export attachments --path "$result" --output-path ".artifacts/native-terminal/$AUTOHAND_NATIVE_TERMINAL/screenshots"
fi
- name: Preserve native screenshots and XCTest results
if: always()
uses: actions/upload-artifact@v7
with:
name: native-terminal-${{ matrix.terminal }}
path: |
.artifacts/native-terminal/installed-versions.json
.artifacts/native-terminal/**/*.xcresult
.artifacts/native-terminal/**/screenshots
.artifacts/native-terminal/**/xcodebuild.log
.artifacts/native-terminal/**/write-metadata-*.jsonl
.artifacts/native-terminal/**/write-metadata-*.jsonl.pending
.artifacts/native-terminal/**/copy-samples-*.jsonl
.artifacts/native-terminal/**/stream-control-*.json*
.artifacts/native-terminal/**/vscode-profile/**/settings.json
.artifacts/native-terminal/**/vscode-profile/**/keybindings.json
if-no-files-found: error
retention-days: 7
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,27 @@

## Unreleased

### Added

- Squad MCP now also manages agent profiles, abilities, extra project folders, skills, group chats, channel membership and scheduled routines.
- Squad is built in as an MCP connection. Select an agent in the running app with `/squad`, send it direct messages with `/message`, and read conversation history and delivery receipts. The connection also reads Squad artifacts and memories.

### Fixed

- Start chat and file work in ordinary folders without initializing Git or creating an ignore file. Existing repositories still show their branch; initialize Git only when you choose to use it.
- Keep the composer editable while restoring saved conversations, preserve drafts and early submissions, and wait for restored history before executing queued work.
- Prevent full-screen resize frames from accumulating in iTerm2 scrollback, preserve drafts and cursor edits, and relaunch compiled executables correctly inside tmux. Plain `--tmux` uses the current folder; `--worktree` and `--zit` request isolation explicitly.
- Restore the previous interaction mode after a Computer Use task while preserving manual mode changes, explicit permission denials, hooks, and restricted mode. MCP startup waits for the child process and decodes fragmented UTF-8 responses correctly.
- Continue the latest nonempty conversation in the current project, and keep background sync disabled until explicitly enabled. Disabling sync cancels queued and active work immediately.
- Bound command output sent to the model while retaining complete oversized output in private session artifacts. Configure the limit with `tools.maxCommandOutputChars` or `AUTOHAND_MAX_COMMAND_OUTPUT_CHARS`.
- Discover installed skills through a compact name index and load descriptions on demand. Keep approved completions to one confirmed reply instead of displaying the candidate before its required review.
- Require notarization checks for transported macOS CLI and trace binaries, and protect the existing CLI option contract with a committed snapshot.
- Preserve the active provider and model when removing another custom provider, and clear remembered local transport settings when restoring the cloud account.
- Bound OpenAI-family tool requests to 128 definitions, including delegated agents, and use compatible completion parameters for Azure reasoning models.

### Testing

- Exercise resize behavior through real tmux and native iTerm2, Ghostty, cmux, and VS Code windows in GitHub Actions, with the iTerm2 Python API disabled.

## 0.9.10 - 2026-11-04

Expand Down
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ events and writes exactly one final `result` or `error` object to stdout.
| `--permissions` | | Display current permission settings and exit |
| `--login` | | Sign in to your Autohand Code account |
| `--logout` | | Sign out of your Autohand Code account |
| `--sync-settings [bool]` | | Enable/disable settings sync (default: true for logged users) |
| `--sync-settings [bool]` | | Enable/disable settings sync (default: false; explicit opt-in required) |
| `--patch` | | Generate git patch without applying changes |
| `--output <file>` | | Output file for patch (default: stdout) |
| `--mode <mode>` | | Run mode: interactive (default), rpc, or acp |
Expand Down Expand Up @@ -423,7 +423,7 @@ Node installs use `HTTPS_PROXY`, `HTTP_PROXY` and `NO_PROXY` for requests, inclu
| `/goals complete` | Mark the current goal complete and advance queued work when completion requirements are met |
| `/goals clear` | Clear this session's current goal while retaining queued work |
| `/goals templates` | List reusable goal templates |
| `/squad` | Open/manage the local Autohand Squad runtime |
| `/squad` | Select an agent in the running Squad app; `/squad app` opens or installs it |
| `/go` | Pair this session with the Autohand Code iOS app |
| `/sync` | Sync settings across devices |
| `/add-dir` | Add additional workspace directory |
Expand All @@ -436,12 +436,18 @@ Node installs use `HTTPS_PROXY`, `HTTP_PROXY` and `NO_PROXY` for requests, inclu
| `/mcp install` | Install validated Official MCP Registry servers (stdio and HTTP) |
| `/team` | Manage team collaboration |
| `/tasks` | List team tasks |
| `/message` | Send team message |
| `/message` | Message the selected Squad agent or a local CLI teammate |
| `/import` | Import data from Claude, Codex, Gemini, Cursor, OpenCode, Kimi, Grok hooks, and other agents |
| `/repeat` | Repeat previous actions |
| `/browser` | Browser integration |
| `/review` | Code review |

Squad MCP is built in. Select an agent with `/squad`, then use `/message <text>`
and `/squad history`. `/message squad <agent-id> <text>` addresses an agent
explicitly; `/message team <name> <text>` addresses your local CLI team.
See [Squad connection and commands](docs/mcp.md#built-in-autohand-squad) for
delivery receipts, Library tools, bridge discovery and opt-out settings.

Persistent goal data remains in the workspace across conversations, but execution does not silently transfer work owned by another live session. Bare `/goal` inspects prior state and starts the next queued item when this session has no goal and no live peer owns the backlog. Use `/goal resume` to resume this session's paused goal or explicitly start queued work.

Published CLI announcements appear as a cached launch block and a persistent line above the composer. Press `Ctrl+X` to dismiss the visible item, or use `/whatsnew` to review and dismiss all active announcements. Dismissal is per announcement; `--offline` keeps cached announcements visible without making announcement requests.
Expand Down
Loading
Loading