Skip to content

Latest commit

 

History

History
480 lines (338 loc) · 14.9 KB

File metadata and controls

480 lines (338 loc) · 14.9 KB

Chau7 (macOS)

Chau7 is a macOS menu bar helper and floating terminal overlay built for AI-assisted CLI work. It tails local JSONL logs and CLI history to send notifications and keep a live multi-tab terminal in view.

Feature Highlights

  • Menu bar status item with quick toggles, recent activity, and session status.
  • Native notifications for AI events and command idle detection.
  • Multi-tab terminal overlay with rename, colors, last-command badges, and git branch indicator.
  • Command palette, search overlay (regex + case sensitivity), snippets, clipboard history, bookmarks, and broadcast input.
  • AI CLI detection with auto tab theming and custom detection rules.
  • Multi-agent event monitoring, notifications, and runtime integration for modern AI CLIs.
  • SSH connection manager with jump hosts and import from ~/.ssh/config.

For a complete feature inventory, see docs/FEATURES.md:

Requirements

  • macOS 14+
  • Xcode 26+ to build
  • Network access the first time to fetch Swift Package Manager dependencies

Local CI

Repo-root verification lives outside the app-specific build helpers:

../../Scripts/ci-local-fast
../../Scripts/ci-local

Use those for local verification. Keep ./Scripts/build-app.sh, ./Scripts/build-and-run.sh, and ./Scripts/order66 for packaging and launch workflows.

For repo-wide doc ownership and canonical entry points, see ../../docs/README.md.

Install (pre-built)

brew tap aeptus/chau7
brew install --cask chau7

Or grab the DMG from the latest release.

Build from source

All commands below assume you are in apps/chau7-macos.

Option A: Open in Xcode

  1. Open Package.swift in Xcode.
  2. Select the Chau7 scheme.
  3. Run (Cmd+R).

The first time it runs, macOS will ask for Notifications permission. To see verbose logs when launched from Terminal, set CHAU7_VERBOSE=1.

Option B: Build in Terminal

From the project folder:

swift build -c release
CHAU7_VERBOSE=1 .build/release/Chau7

Keep the app running to keep notifications active.

Recommended: Build a proper .app bundle (better notifications)

For notifications to show up under their own app entry in macOS Settings, run the helper script to create an app bundle:

swift build -c release
./Scripts/build-app.sh
open ./build/Chau7.app

build-app.sh now defaults to a development bundle identifier (com.chau7.app.dev) to avoid macOS TCC permission collisions with the Launchpad app.

Quick install one-liner:

swift build -c release && ./Scripts/build-app.sh && open ./build/Chau7.app

Dock icon is enabled by default for the app bundle; to hide it:

SHOW_DOCK_ICON=0 ./Scripts/build-app.sh

One-shot build + launch (verbose)

./Scripts/build-and-run.sh

build-and-run.sh now defaults to a dev bundle identifier (com.chau7.app.dev) to avoid macOS permission collisions with /Applications/Chau7.app. When ad-hoc signing is used, it now applies a stable designated requirement (designated => identifier "<bundle-id>") so TCC permissions do not churn on every rebuild. The local build scripts also rebuild and bundle chau7-remote automatically so the remote helper stays in sync with app bundles. Code signing is auto-detected. Local dev builds prefer an Apple Development: certificate, installed/release builds prefer Developer ID Application:, and scripts fall back to stable ad-hoc signing when no Apple signing identity is installed. Override when needed:

BUNDLE_IDENTIFIER=com.chau7.app ./Scripts/build-and-run.sh
CHAU7_CODESIGN_IDENTITY="Apple Development: Your Name (TEAMID)" ./Scripts/build-and-run.sh

Install / update the Launchpad app

To install the production Launchpad app (com.chau7.app) into /Applications:

./Scripts/install-launchpad-app.sh

Note: this script refuses to replace /Applications/Chau7.app while it is running. Replacing a running app causes TCC code-requirement mismatches and repeated permission prompts.

To force Developer ID signing for the Launchpad app:

CHAU7_CODESIGN_IDENTITY="Developer ID Application: Your Name (TEAMID)" ./Scripts/install-launchpad-app.sh

Share a pre-release DMG

Build a clean testing DMG:

./Scripts/build-dist.sh

This produces apps/chau7-macos/dist/Chau7-AppleSilicon.dmg with:

  • Chau7.app
  • an Applications symlink
  • bundled legal notices inside the app

When a Developer ID Application: identity is installed, the app bundle and DMG are signed with it automatically. Without one, the script falls back to stable ad-hoc app signing.

If you explicitly want the larger mixed-architecture helper build, use:

./Scripts/build-dist.sh --universal

That produces apps/chau7-macos/dist/Chau7-Universal.dmg.

Notarization is opt-in. First store Apple notary credentials in the keychain:

xcrun notarytool store-credentials chau7-notary --apple-id you@example.com --team-id TEAMID --password app-specific-password

Then build, submit, wait, and staple:

CHAU7_CODESIGN_IDENTITY="Developer ID Application: Your Name (TEAMID)" \
CHAU7_NOTARY_PROFILE=chau7-notary \
CHAU7_NOTARIZE=1 \
./Scripts/build-dist.sh

Important limits:

  • ad-hoc fallback builds are not notarized
  • first launch after switching from ad-hoc to Apple signing may require macOS permissions once
  • first launch of an ad-hoc build on another Mac may require Finder: Control-click Chau7.app -> Open

Optional: launch it after install:

OPEN_AFTER_INSTALL=1 ./Scripts/install-launchpad-app.sh

You can also run the bundled binary directly with verbose logs:

CHAU7_VERBOSE=1 ./build/Chau7.app/Contents/MacOS/Chau7

For extremely verbose trace logs (tailers, parsing, idle tracking):

CHAU7_VERBOSE=1 CHAU7_TRACE=1 ./build/Chau7.app/Contents/MacOS/Chau7

Logs are written to:

~/Library/Logs/Chau7.log

Getting Started Cheatsheet

  • Open overlay: menu bar icon → "Open Terminal"
  • New tab: Cmd+T
  • Command palette: Cmd+Shift+P
  • Find: Cmd+F (regex and case toggles)
  • Snippets: Cmd+;
  • Next/prev tab: Cmd+Shift+] / Cmd+Shift+[
  • Toggle dropdown: Ctrl+` (if enabled)
  • Debug console: Cmd+Shift+D

Chau7 terminal window

The app ships with a floating terminal overlay powered by the native Rust terminal backend. It starts automatically and provides:

  • A shell running your default login shell (configurable)
  • Tabs with standard shortcuts (Cmd+T, Cmd+W, Cmd+Shift+[ / ], Ctrl+Tab)
  • Multi-window support (Cmd+N) and tab jump (Cmd+1-9)
  • Search overlay with regex/case-sensitive options (Cmd+F)
  • Command palette (Cmd+Shift+P) and snippets (Cmd+;)
  • Clipboard history, bookmarks, and broadcast input
  • AI CLI detection with auto tab colors and product icons
  • Command idle notifications based on input/output activity
  • Optional dropdown terminal (Ctrl+`) when enabled in Settings

Use the menu bar icon to reopen the overlay if the window is hidden.

Idle behavior:

  • "Idle seconds" triggers a notification.
  • "Stale seconds" marks sessions closed and stops further idle alerts.

Emit events from your CLI tools

Default log file: ~/.ai-events.log

Use the helper script:

./Scripts/ai-event.sh needs_validation "Claude" "Please review the plan"
./Scripts/ai-event.sh finished "Codex" "Bulk upload complete"
./Scripts/ai-event.sh failed "Codex" "Tests failed"

Each line is JSON. Example:

{"type":"finished","tool":"Codex","message":"Bulk upload complete","ts":"2026-01-09T12:00:00+01:00"}

Wiring into Claude CLI / Codex

You can wrap your commands. Example pattern:

your_command_here || ./Scripts/ai-event.sh failed "Claude" "Command failed"
./Scripts/ai-event.sh finished "Claude" "Command finished"

There are example wrapper scripts in Scripts/.

Live terminal output (PTY wrapper)

The history JSONL logs do not include the live terminal output. To capture it, use the PTY wrappers:

./Scripts/codex-pty.sh
./Scripts/claude-pty.sh

When running AI CLIs inside the Chau7 terminal overlay, PTY output and AI events are captured automatically. The wrappers are only needed for external terminals.

These log raw terminal output to:

  • ~/Library/Logs/Chau7/codex-pty.log
  • ~/Library/Logs/Chau7/claude-pty.log

You can override the paths with:

AI_CODEX_TTY_LOG=~/codex-tty.log ./Scripts/codex-pty.sh
AI_CLAUDE_TTY_LOG=~/claude-tty.log ./Scripts/claude-pty.sh

Input lines are tagged as:

[INPUT] your text

Codex update prompt in Terminal.app

If Codex is installed through Volta, Terminal.app can resolve codex through ~/.volta/bin before the npm-managed Node image bin. That leaves Terminal.app running a stale Volta package image even after Codex's update prompt updates the npm global package. Chau7's built-in terminal already repairs this PATH order at startup; for Terminal.app, install the same managed zsh startup block:

./Scripts/install-codex-terminal-path-fix.sh

Open a new Terminal.app window and verify:

command -v codex
codex --version

The first command should point under ~/.volta/tools/image/node/.../bin/codex, not ~/.volta/bin/codex.

TTY readability:

  • "Normalize terminal output" strips ANSI codes, handles backspaces, and removes control chars.
  • You can disable it in the UI or set CHAU7_TERMINAL_NORMALIZE=0 (legacy AI_TTY_NORMALIZE=0).
  • "Render ANSI styling" keeps ANSI colors/styles in the terminal stream (set CHAU7_TERMINAL_ANSI=0 or legacy AI_TTY_ANSI=0).

Start at login (optional)

A sample LaunchAgent plist is included in LaunchAgent/.

Because the binary path depends on where you built it, do this:

  1. Build release:
swift build -c release
  1. Copy the binary somewhere stable, for example:
mkdir -p ~/Applications/Chau7
cp .build/release/Chau7 ~/Applications/Chau7/
  1. Edit LaunchAgent/com.chau7.plist and set the binary path to:
$HOME/Applications/Chau7/Chau7
  1. Install the LaunchAgent:
mkdir -p ~/Library/LaunchAgents
cp LaunchAgent/com.chau7.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/com.chau7.plist

Unload:

launchctl unload -w ~/Library/LaunchAgents/com.chau7.plist

Security & Privacy

  • API Proxy: The optional TLS proxy (chau7-proxy) runs locally on your machine for AI API analytics. API keys pass through to the original provider and are never stored or transmitted elsewhere. The proxy is opt-in and can be disabled in Settings.
  • MCP Server: The Unix socket API is bound to ~/.chau7/mcp.sock with 0600 permissions (owner-only access).
  • Bug Reports: Submitted via a Cloudflare Worker relay to a private GitHub repo. No data is sent without explicit user action. All diagnostic sections are opt-in. See the in-app privacy page for full GDPR sub-processor disclosure.
  • Terminal Data: Scrollback, command history, and telemetry stay on your machine in ~/.chau7/ and ~/Library/Application Support/Chau7/.

For vulnerability reports, see SECURITY.md.

Troubleshooting

  • Notifications do not appear: run the app bundle (./Scripts/build-app.sh), and verify notifications are allowed in System Settings.
  • Menu bar icon is missing: quit and relaunch, or check ~/Library/Logs/Chau7.log for launch errors.
  • No AI events: confirm ~/.ai-events.log is being written and CHAU7_EVENTS_LOG is not pointing elsewhere.
  • PTY logs are empty: if you are using an external terminal, run ./Scripts/codex-pty.sh or ./Scripts/claude-pty.sh and verify CHAU7_CODEX_TERMINAL_LOG/CHAU7_CLAUDE_TERMINAL_LOG. Inside the Chau7 terminal overlay, logs are captured automatically.
  • Overlay is hidden or off-screen: use Settings -> Actions -> Reset Window Positions, then reopen via the menu bar icon.

FAQ

Q: What does an AI event line look like? A: Each line is JSON with at least type and tool. Example:

{"type":"finished","tool":"Codex","message":"Bulk upload complete","ts":"2026-01-09T12:00:00+01:00"}

Q: How do I emit events from my own CLI? A: Use the helper script or inline it in your wrappers:

./Scripts/ai-event.sh needs_validation "Claude" "Please review the plan"
./Scripts/ai-event.sh finished "Codex" "All done"
./Scripts/ai-event.sh failed "Codex" "Tests failed"

Q: How do I capture live terminal output (PTY)? A: Run the PTY wrappers instead of calling the CLI directly:

./Scripts/codex-pty.sh
./Scripts/claude-pty.sh

Logs default to ~/Library/Logs/Chau7/codex-pty.log and ~/Library/Logs/Chau7/claude-pty.log.

Testing

Chau7 includes a comprehensive test suite for core functionality.

Running Tests

# Ensure Xcode is set as the developer directory
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

# Run all tests
swift test

Test Coverage

  • CommandDetectionTests (40 tests): AI CLI detection, tokenization, environment parsing
  • EventParsingTests (6 tests): Hook event parsing, session ID extraction

Adding New Tests

Tests live in apps/chau7-macos/Tests/Chau7Tests/. The testable logic is in apps/chau7-macos/Sources/Chau7Core/:

  • CommandDetection.swift - Pure functions for detecting AI CLIs
  • Add new pure functions here for testability

Remote Control (experimental)

  • Build the remote agent from the repo root: cd services/chau7-remote && go build ./cmd/chau7-remote
  • Configure relay and pairing in Chau7 settings: Settings > Remote Control

Debugging

Debug Console (Cmd+Shift+D)

Press Cmd+Shift+D anywhere in the app to open the Debug Console:

  • State: Real-time app state, tabs, Claude sessions
  • Contexts: Active debug operations with correlation IDs
  • Events: Claude Code event stream
  • Logs: Live log viewer with filtering
  • Report: Generate bug reports and state snapshots

Structured Logging

All operations use correlation IDs for tracing:

[ABC123] START command-detection {input=claude --help}
[ABC123] Found token {token=claude}
[ABC123] END command-detection SUCCESS (2ms) {result=Claude}

Logs are written to ~/Library/Logs/Chau7.log

Bug Reports

Generate detailed bug reports from the Debug Console or programmatically:

let path = BugReporter.shared.generateReport(userDescription: "Describe the issue")

Reports are saved to ~/.chau7/reports/ and include:

  • Full app state snapshot
  • Recent events
  • Last 50 log lines
  • Feature flag states

Notes

  • Notifications are delivered via UserNotifications (native).
  • If you want action buttons (Approve or Retry), that is a small follow-up change.