Skip to content

feat(desktop): ship Terminal as a system app - #112

Closed
ymote wants to merge 3 commits into
mainfrom
feat/terminal-system-app
Closed

ymote wants to merge 3 commits into
mainfrom
feat/terminal-system-app

Conversation

@ymote

@ymote ymote commented Sep 28, 2026

Copy link
Copy Markdown
Contributor

Ships the Makepad Terminal as a desktop system app, linked in-process like Rinx.

  • app-terminal feature (in the desktop's default set) registers makepad-terminal's TERMINAL_MODULE. terminal is hosted in-process by default; terminal: Process in wm/apps.splash keeps the child-process form.
  • No first-launch compile: on macOS the PTY helper is octosense itself (--exec-pty), so nothing ships beside the binary.
  • Manifest: declares process and clipboard, no octos.* service. The assistant gets read_screen/read_scrollback only; run (Risk::Act) is not offered by a default system app.
  • Keyboard focus fixes for module tiles: re-assert a pending focus after the tile draws, and release the keyboard from the tile that last held it on a focus change.
  • Phone builds are unchanged (mobile-apps does not include it).

Builds on the current makepad pin (75e3e24d, which has makepad #40/#41). Tabs, split panes, settings, fonts/profiles and terminal-ctl are in OctoSense-org/makepad#47; they arrive with a later pin bump, and this PR doesn't need them.

Verification

  • cargo build --locked -p octosense against the pinned makepad + reviewed runtime patches
  • bash tools/check-shell-graph.sh -p octosense: ok
  • cargo test -p octosense-shell --features app-terminal: 345 passed

🤖 Generated with Claude Code

@ymote

ymote commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Review: changes requested, to match ADR 0004 (accepted in #110 after this PR was opened).

  1. Hosting (ADR 0004 §2, §10). Terminal is the first process app. The ADR does this because a terminal font crash on 2026-09-27 took the whole shell down.
  2. Terminal AI (ADR 0004 §10). The Terminal's AI may type commands, not only read.
    • Each typed command goes through the shell with a live approval showing the exact command. It is auto_approvable: false, so no standing rule approves it; developer mode is the exception (§13).
    • makepad#41's per-run confirmation already matches this. Please offer run behind that approval instead of dropping it.
  3. Rebase on main after Desktop: host Rinx as the linked module it is #101. Desktop: host Rinx as the linked module it is #101 renamed the stale "robrix" id to "rinx", so the list becomes "rinx" | "finance" | "terminal".
  4. Keep: the keyboard-focus fixes for module tiles (release the previous holder; re-assert a pending focus after the tile draws). They're good.

Also: ADR 0004 §1 plans a native-apps.json manifest plus a generator for native apps. Hand edits are fine here until that lands.

🤖 Generated with Claude Code

ymote and others added 3 commits September 28, 2026 14:35
… draws

A focus that cannot land at launch (the tile is not drawn yet) is kept in
`pending_focus` and re-asserted when the client's first frame arrives, on the
PresentableDraw path. A module tile never sends a frame, so its pending
focus was never retried: ModuleView stayed unfocused, its gate dropped every
key, and a module opened from the dock or launcher took no typing until the
person clicked into it.

After the UI handles a Draw, retry a pending focus that belongs to a module
client. On success it clears; otherwise nothing forces a redraw, so a tile
that still cannot take it just tries again on the next natural draw.

Found with the Terminal module: typed keys never reached its root (a probe
in its key path logged nothing) until the tile was clicked; with this change
`echo` typed right after opening it from the dock ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Terminal was a developer program: built on first launch from the Makepad
checkout, then run as a child process. It now links in-process like Rinx:
the new `app-terminal` feature (on in the desktop's default set) registers
makepad-terminal's TERMINAL_MODULE, and `terminal` joins robrix and finance
as a module hosted in-process by default unless the person switched it
(`terminal: Process` in wm/apps.splash keeps the process form, whose
config/apps.json row stays).

- Opens instantly: no compile on first launch, no swapchain round trip.
- On macOS its PTY helper is `octosense` itself (Cx::pre_start answers
  `--exec-pty`), so nothing ships beside the binary.
- It declares `process` and `clipboard` and no `octos.*` service. The
  assistant gets read_screen and read_scrollback only; `run` (an unsandboxed
  shell, rated Risk::Act) is not offered by a default system app.
- Phone builds are unchanged: `mobile-apps` does not include it.

Builds on the current makepad pin (75e3e24d), which already carries
TERMINAL_MODULE, the PTY-helper fallback and the macOS signal-wake fix
(OctoSense-org/makepad #40, #41); Cargo.toml pins makepad-terminal there.
Tabs, panes, settings and terminal-ctl (makepad #47) arrive with a later
pin bump.

Verified locally with those makepad commits applied under .sources/makepad:
- cargo check --locked -p octosense (and --features mobile-apps)
- bash tools/check-shell-graph.sh -p octosense
- cargo test --locked -p octosense-shell --features app-terminal: 333 passed
- from phone/: cargo test --locked --features mobile-apps -p octosense-shell:
  342 passed
- hidden desktop over MAKEPAD_REMOTE: Terminal opens from the dock as
  "in-process, terminal"; the shell's parent is octosense; octoscode's
  composer stayed clean on 3 of 3 launches; closing the tile ended zsh and
  octoscode and freed the isolate; two Terminals ran two shells.
Rebased onto main: cargo build --locked -p octosense and
tools/check-shell-graph.sh pass against the pinned makepad with the reviewed
runtime patches; cargo test -p octosense-shell --features app-terminal: 345 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…us change

Focusing a process tile moves key focus to it (its forwarding needs that),
but a module tile deliberately never moves key focus: its own widgets claim
it. Nothing told the previously focused tile to let go, so after switching
between the tabs of a window group the hidden tab kept the keyboard and
every key typed into the visible one was dropped.

Track the client whose tile last took the keyboard (`keyboard_holder`); in
`focus_client`, release that tile (TileHost::release_keyboard) before
focusing another. The layout already reports the new client as focused by
then, so the previous one is tracked here rather than read from it.

Needs the matching makepad-terminal change (claim the keyboard on a key that
arrives while nobody holds it, OctoSense-org/makepad#40).

Verified: Omarchy style, a two-tab Terminal group; after Cmd+Alt+Tab text
typed runs in the tab now shown, both directions. cargo test --locked
-p octosense-shell --features app-terminal: 333 passed; from phone/:
--features mobile-apps: 342 passed; cargo check --locked -p octosense.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ymote
ymote force-pushed the feat/terminal-system-app branch from e7ef0ca to 5b458a8 Compare September 28, 2026 21:37
@ymote

ymote commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto main after #101 (robrix → rinx). The conflict in crates/shell/src/apps.rs is resolved, and cargo test -p octosense-shell --features app-terminal passes (346).

Both requested changes are in #113, which is stacked on this PR, so the hosting table and the §10 rules come from native-apps.json:

  • Hosting (§2, §10): Terminal is a process by default on macOS and Windows, and on Linux only with a Vulkan build under Wayland. It is in-process elsewhere, and the person's wm/apps.splash override still wins. Release packaging of the bin is Desktop release packages (macOS .app/.dmg, Windows NSIS, Linux .deb/.AppImage) and release-desktop workflow #94; until then a missing binary falls back to in-process.
  • Terminal AI typing (§10): run stays registered in both hostings. It is confirm: host and auto_approvable: false, and every command waits on the shell's live confirmation.

Review #112 and #113 together and merge in order, or I can fold #113 into this PR if you prefer one PR.

🤖 Generated with Claude Code

@ymote

ymote commented Sep 28, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #113 at the reviewer's request: #113 now targets main and contains this PR's three commits plus manifest-driven hosting (Terminal as a process on macOS/Windows/Vulkan+Wayland) and the §10 Terminal AI typing with live confirmation, so Terminal never lands in-process-only with a read-only AI.

🤖 Generated with Claude Code

@ymote ymote closed this Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant