termio-device
See and drive the sibling agent sessions running alongside you on this machine via the…
Kill the running termio dev app, rebuild it with SwiftPM, and relaunch it as a foreground app. Invoke when the user says 'rebuild', 'rebuild app', 'restart app', 'relaunch', '重新编译', or '重启 app'.
$ npx -y skills add termio-sh/termio --skill macos-rebuild-dev --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/macos-rebuild-devContext preview
The summary Claude sees to decide when to auto-load this skill.
Kill the running termio dev app, rebuild it with SwiftPM, and relaunch it as a foreground app. Invoke when the user says 'rebuild', 'rebuild app', 'restart app', 'relaunch', '重新编译', or '重启 app'.
name: macos-rebuild-dev description: "Kill the running termio dev app, rebuild it with SwiftPM, and relaunch it as a foreground app. Invoke when the user says 'rebuild', 'rebuild app', 'restart app', 'relaunch', '重新编译', or '重启 app'."
Kill the running **dev** build, rebuild it as the isolated `termio-dev.app` bundle, and relaunch — so every rebuild reflects the current Dock icon and, crucially, does **not** disturb an installed release build you use daily.
termio ships a `TERMIO_CHANNEL=dev` build that is a fully separate app from the release one, so both can run at the same time:
| | release | dev (this skill) | | --- | --- | --- | | Bundle | `termio.app` (usually `/Applications`) | `termio-dev.app` (repo root) | | Bundle id | `sh.termio.app` | `sh.termio.app.dev` | | State + sockets | `~/Library/Application Support/termio` | `…/termio-dev` | | User config | `~/.termio` | `~/.termio-dev` | | Daemon socket | `$TMPDIR/termiod-<uid>` | `…-dev` | | Daemon launchd job | `sh.termio.termiod` | `sh.termio.termiod.dev` | | Companion port | 8787 | 8788 | | CLI on PATH | `termio` | `termio-dev` | | Sparkle auto-update | on | **no update feed** (dev never self-updates) |
All of this falls out of the `.dev` bundle-id suffix via `Sources/termio/Companion/AppChannel.swift` (paths + port) and `scripts/build-app.sh` (id, name, `SUFeedURL` deletion, CLI rebind). Sparkle.framework itself is embedded on both channels — the binary links it either way — so a dev bundle still carries it; it just has nothing to check.
termio is a plain SwiftPM executable (`Package.swift` → `executableTarget` named `termio`); `swift build` alone produces a bare binary with **no Dock icon**. So this skill builds the real bundle via `scripts/build-app.sh`. For a dev build the script auto-picks a real codesigning identity from **your own** keychain (any "Apple Development" / "Developer ID Application" cert — a free Apple ID gives you one) so the dev app can post macOS notifications; `usernoted` rejects an ad-hoc signature outright, so an unsigned dev build can **never** banner. A contributor with **no** signing cert falls back to ad-hoc automatically — the build still succeeds, they just don't get notifications. Set `SIGN_IDENTITY=…` to force a specific one. The app runs unsandboxed with `.exec` PTYs — see `CLAUDE.md`. The icon is `packaging/icon-static.svg`, rasterized to `packaging/AppIcon.png` by `scripts/render-icon.sh` (needs headless Chrome). Note: dev and release currently share the same icon art and differ only by name ("termio dev") — a tinted dev icon is a possible follow-up.
When invoked, execute these steps sequentially:
1. **Kill only the running dev app + its tunnel.** Both channels' inner binary is named `termio` (`CFBundleExecutable`), so `pkill -x termio` would kill the release app too. Match the dev bundle **path** instead. SIGKILL skips the app's `willTerminate` cleanup, so also reap the companion tunnel it spawned on the dev port (8788):
pkill -9 -f "termio-dev.app/Contents/MacOS/termio" || true pkill -9 -f "cloudflared tunnel --url http://127.0.0.1:8788" || true pkill -9 -f "tunelo port 8788" || true
2. **Build the dev bundle** from the committed `packaging/AppIcon.png` — do *not* re-render the icon (see "Icons" below). Show the tail of the output; if the build fails, show the error and **stop — do NOT relaunch**:
TERMIO_CHANNEL=dev ./scripts/build-app.sh 2>&1 | tail -12
3. **Re-register the dev bundle with LaunchServices, then refresh the Dock cache.** macOS resolves an app's icon by its bundle id (`sh.termio.app.dev`); `lsregister -f` forces our path to win and `killall Dock` drops the cached icon:
LSREG="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister" "$LSREG" -f "$PWD/termio-dev.app" touch ./termio-dev.app killall Dock 2>/dev/null || true
4. **Relaunch via `open`** (NOT `nohup` on the inner binary — that bypasses LaunchServices). `open`'s `--stdout` / `--stderr` still capture logs:
open ./termio-dev.app --stdout /tmp/termio-dev.log --stderr /tmp/termio-dev.log echo "launched ./termio-dev.app (logs: /tmp/termio-dev.log)"
5. **Upgrade the running dev daemon.** `build-app.sh` already rebuilt the daemon into `Resources/termiod`, but a **running** dev daemon keeps its old image: a dev app's launch-time reconcile deliberately refuses to stage (its bundle stamp is a placeholder, and that guard is what keeps a dev build from ever deploying itself over a release daemon). Without this step, a termiod-side change gets "verified" against the previous daemon. The deploy is idempotent — same version reports `current` and does nothing, so it costs nothing on Swift-only rebuilds — and an execve handoff keeps the pid and carries every live session. `TERMIOD_SOCK` must be unset first: a shell inside a termio session carries it pointed at the *release* daemon, and it overrides the channel.
unset TERMIOD_SOCK TERMIO_CHANNEL=dev ./termio-dev.app/Contents/Resources/termiod deploy --json 2>&1 | tail -3
A daemon that isn't running needs nothing: the first pane starts it from the new bundle.
6. **Report** the result: whether the build succeeded, the app relaunched, and the daemon version the deploy reported. If the window doesn't appear, check `/tmp/termio-dev.log`.
Sessions carried across the handoff keep the environment and shell their **old** daemon spawned them with — a change to session spawning (env, injection, PTY setup) is invisible in them by design. Open a **new** session to see it.
`scripts/render-icon.sh` rasterizes `packaging/icon-static.svg` into `packaging/AppIcon.png` (and the iOS asset) through headless Chro
A terminal-first agentic development environment for agentic coding. Build for CLI/TUI agent. Runtime for Coding Agent, Tmux alternative
Repo: termio-sh/termio
See and drive the sibling agent sessions running alongside you on this machine via the…
See and drive the sibling agent sessions running alongside you in this Termio project via the…
Reverse-lookup glossary that turns a vague description of a web animation or motion effect…
Drive the running termio app via AppleScript / System Events to reach a UI state (focus the…
Apple's approach to interface design and fluid, physical motion, translated for the web. Use…
Drive App Store Connect from the terminal with the `asc` CLI — TestFlight builds, groups,…