Skip to content

ForkTTY 0.2.0-alpha.14

Pre-release
Pre-release

Choose a tag to compare

@Lucenx9 Lucenx9 released this 19 Jun 13:21

Security

  • Rejected control characters in restored session identifiers and embedded
    Ghostty command-spawn values so tampered session state cannot influence
    terminal child argv or environment setup.
  • Hardened embedded Ghostty GTK library loading by canonicalizing candidate
    paths and rejecting relative paths, non-regular files, untrusted ownership,
    or group/other-writable files and parent directories before dlopen, while
    allowing packaged AppImage libraries below sticky /tmp mounts.
  • Limited OSC99 terminal notification icon dimensions before decoding or
    forwarding image data to desktop notification servers.
  • Kitty image snapshots now copy and downsample only the rendered pixel
    footprint for each placement and use fallible render-buffer allocation,
    preventing malicious terminal output from forcing full-source-image
    per-placement copies on every redraw.

Changed

  • App dialogs now use tighter shared spacing, shorter copy, and calmer inline
    actions across the command palette, shortcuts, worktree, and notification
    panels.
  • The Agent HUD now uses a calmer dense-card layout with compact actions,
    subtler status pills, and terminal-like output snippets.
  • The About dialog now uses a more compact identity layout, calmer metadata
    rows, and lighter action buttons.
  • App chrome now uses quieter top/status bars, subtler split-pane focus,
    softer per-pane tabs, and less intrusive pane/browser toolbars.
  • Sidebar navigation, popovers, badges, and terminal empty/error states now use
    calmer density, shorter copy, and less dominant status styling.
  • Settings now use a clamped, denser layout with calmer inline actions, and the
    Agents page presents one recommended integration action plus advanced
    per-component actions.
  • The welcome dialog's agent setup action now opens Settings directly on the
    Agents page, so first-time setup shows installed/update state before writing
    provider configuration files.
  • Settings no longer exposes a shell editor; advanced users can still set
    general.shell manually in config.toml, while the dialog focuses on
    ForkTTY-owned behavior and appearance.

Fixed

  • Embedded Ghostty terminals launched from the AppImage no longer leak the
    AppImage runtime environment (LD_LIBRARY_PATH, APPDIR/APPIMAGE/OWD,
    and GTK/GObject module search paths) into spawned children, so a child
    process such as git, an editor, or an agent links against the host's
    libraries instead of the AppImage's bundled copies. XDG_DATA_DIRS is left
    intact because Ghostty's own shell integration depends on it.
  • AppImage and Debian packages now include Ghostty's bundled themes, so
    embedded Ghostty panes can resolve user configs such as
    theme = Catppuccin Mocha instead of falling back to the default colors.
  • Embedded Ghostty panes now create command-spawned surfaces with a ForkTTY
    scrollback cap, preventing long agent transcripts from growing the host GTK
    process into multi-GiB memory usage without modifying the user's standalone
    Ghostty configuration file.
  • Embedded Ghostty panes now keep the cursor blink timer disabled while the
    rendered terminal state uses a steady cursor, preventing idle OpenGL redraws
    from steadily growing RSS for Ghostty configs such as
    cursor-style-blink = false.
  • The embedded Ghostty GTK library probe now builds Ghostty with the stable
    ReleaseSafe optimization profile and a linker-compatible Blueprint helper,
    avoiding local Zig/GCC .sframe linker failures and ReleaseFast
    startup crashes when running ForkTTY from cargo.
  • Refined the per-pane tab close button styling so hover changes only the X
    color instead of drawing a filled control around it.
  • Embedded Ghostty panes now focus the terminal's internal focusable widget
    after new workspace, tab, split, or pane-header selection, so typing reaches
    the newly focused pane without an extra click inside the terminal.
  • Dialogs now handle Escape in capture phase, so command palette and other
    dialogs close even when a search field or text entry has focus.
  • Embedded Ghostty panes now use a native command-spawn ABI when the bundled
    library supports it, so per-surface FORKTTY_* environment setup no longer
    appears as a typed exec /usr/bin/env ... command in every new workspace.
    Older embedding libraries now start Ghostty's default shell without the
    ForkTTY environment instead of typing a bootstrap command into the terminal.
  • Embedded Ghostty socket text reads now use a bounded GTK ABI when the
    embedding library supports it, so read_text/capture_tail requests do not
    ask Ghostty to materialize unbounded scrollback in ForkTTY before response
    truncation.
  • Embedded Ghostty scrollback tail capture (tail_text) now returns an empty
    string for a zero-column terminal instead of erroring on an out-of-bounds grid
    reference, matching the existing guard in visible_screen_rows.
  • Failed agent.hibernate close attempts now restore the previous unread bit
    and status entry instead of leaving the running surface shown as suspended.
  • Pending embedded Ghostty spawns now lose their orphan-reaper protection
    after one reconciliation if their backend surface never appears in the
    model, preventing hidden PTY/widget processes from surviving a
    spawn/model-removal race.
  • Bounded the forktty remote-helper pty stdin relay queue so
    non-draining PTY children apply backpressure instead of allowing unbounded
    memory growth.
  • Feed approval rows now use durable notification feed IDs and avoid carrying
    approval decisions across newer entries with reused transient notification
    IDs.
  • The socket CLI now writes all success output through the broken-pipe-aware
    writer, so piping a command into a consumer that closes early (for example
    forktty ping | head -1) terminates cleanly instead of panicking on the
    closed pipe.
  • List socket methods (team.list, team.inbox, team.events,
    workflow.list, workflow.replay) now clamp an explicit limit to 10000,
    matching the existing browser-history cap, so no single request can ask for an
    unbounded result set.
  • Ghostty Nushell shell integration now imports the bundled ghostty.nu module by absolute path and skips injection when that trusted module is missing, preventing workspace files from shadowing the startup import.

Added

  • Settings now includes an Agents page for installing or refreshing ForkTTY
    agent hooks and the local MCP bridge after first launch. ForkTTY also
    auto-refreshes already-managed hook/MCP entries on startup when a new build
    would update them, while leaving first-time setup explicit.
  • Embedded Ghostty panes now snapshot their scrollback tail into
    the session (on child exit, on programmatic close/restart, and via a throttled
    poll) when
    appearance.persistent_scrollback_lines > 0, matching classic panes, so a
    later session save keeps recent embedded output. Restoring that scrollback on
    respawn/session restore is wired through an optional
    ghostty_gtk_surface_restore_scrollback embedding ABI (feeds Ghostty's VT
    stream, never the child PTY). The pinned Ghostty fork now exports the symbol
    (an IO-thread inject_output mailbox message routed to
    Termio.processOutput), so an embedding library built from the current pin
    restores embedded scrollback; libraries built before it degrade to a safe
    no-op. The Ghostty GTK Probe now builds the embedding .so on Ubuntu and
    verifies an embedded pane restart preserves a pre-restart scrollback marker in
    capture_tail. See docs/ghostty-renderer-embedding-spike.md for the
    Ghostty-side design.
  • Bumped the vendored Ghostty pin to
    470d3174eb10d25e21d17eff69ffcefdd4f4f91c, which adds the
    ghostty_gtk_surface_restore_scrollback,
    ghostty_gtk_surface_new_with_working_directory_and_command, and
    ghostty_gtk_surface_read_text_limited,
    ghostty_gtk_surface_new_with_working_directory_command_and_scrollback_limit
    GTK embedding ABIs.
  • ForkTTY now pins the full upstream Ghostty source as vendor/ghostty for the
    cmux-style renderer/widget integration path; release builds package the
    vendored Ghostty GTK embedding library for the default pane renderer.
  • The Ghostty renderer spike is now documented: upstream's current public C
    surface embedding API is macOS/iOS-only, so ForkTTY's next renderer step is a
    minimal Ghostty-side GTK widget embedding API instead of more parity shims.
  • scripts/ghostty-gtk-build-probe.sh now records the reduced upstream Ghostty
    GTK build used before attempting the Linux renderer embedding patch.
  • A manual Ghostty GTK Probe GitHub Actions workflow can run that upstream
    Ghostty GTK build on Ubuntu without blocking the normal ForkTTY CI.
  • forktty ghostty-gtk-probe can auto-exit with
    FORKTTY_GHOSTTY_GTK_PROBE_EXIT_AFTER_MS, and the manual Ghostty GTK Probe
    workflow now smoke-tests the Rust GTK widget bridge under Xvfb after building
    the vendored Ghostty GTK embedding library.
  • The vendored Ghostty GTK embedding library now avoids standalone-app theme
    startup when registered inside ForkTTY's host GTK application.
  • The vendored Ghostty GTK embedding ABI now returns a sunk full widget
    reference so the Rust probe can parent the surface without premature dispose.
  • The vendored Ghostty GTK embedding context now initializes Ghostty's GTK app
    state in-place so internal runtime pointers stay valid after context setup.
  • ForkTTY can pack the vendored Ghostty GTK widget into terminal panes after
    ghostty-gtk-embed.so has been built; this is now the default renderer path,
    and terminal spawn records an error instead of falling back to the classic
    GTK/Pango/Cairo renderer if the embedded library cannot be loaded or a
    surface fails to spawn.
  • The vendored Ghostty GTK embedding ABI can create surfaces with a working
    directory override so embedded Ghostty panes start in the ForkTTY
    surface cwd.
  • The embedded Ghostty GTK pane mode can now forward ForkTTY socket
    send_text input to embedded Ghostty surfaces after the Ghostty core surface
    is initialized.
  • The embedded Ghostty GTK pane mode can now service ForkTTY socket
    read_text and capture_tail requests by reading visible/full text through
    the vendored Ghostty GTK embedding ABI.
  • Release CI now requires ghostty-gtk-embed.so before packaging, so the deb
    and AppImage ship the embedded Ghostty library for the default renderer path.
  • The embedded Ghostty renderer is now the only terminal pane renderer in the
    GTK runtime. The temporary alpha appearance.embedded_ghostty opt-out key is
    accepted on load for compatibility but omitted from new saves and ignored at
    runtime. forktty doctor flags a missing embedding library because terminal
    panes cannot open without it.
  • Embedded Ghostty panes now wire surface lifecycle into the
    ForkTTY model: title changes mirror into the model, child-process exit drops
    the surface from the ready set, sets a closed/Exited (n) status, and raises
    an abnormal-exit notification, and a Ghostty close-request tears the pane down
    cleanly so no stale pane is left behind. The embedding ABI gains
    ghostty_gtk_surface_exit_code so embedded panes report the real exit status;
    older libraries without the symbol fall back to the neutral "Closed".
  • Embedded Ghostty panes now reach copy/paste/select-all/find
    parity with classic panes: the Ctrl+Shift+C/V/A/F accelerators (and the
    command palette equivalents) route to the focused embedded surface instead of
    no-opping, with find opening Ghostty's native search overlay. The embedding
    ABI gains ghostty_gtk_surface_perform_action, which performs a Ghostty
    keybinding action by name (e.g. copy_to_clipboard, start_search); older
    libraries without the symbol degrade to a logged no-op. Mouse selection
    already works natively inside the embedded surface.
  • Embedded Ghostty panes now route ForkTTY zoom actions to
    Ghostty's native font-size actions, so Ctrl+plus, Ctrl+minus, reset zoom,
    and command-palette zoom affect embedded panes as well as classic panes.
  • Embedded Ghostty panes now have child-PID ABI plumbing for
    listening-port discovery and the socket surfaces PID field. The embedding
    ABI gains ghostty_gtk_surface_child_pid, fed by a new pid_available
    surface mailbox message that hands the IO-thread-owned pid to the GTK main
    thread race-free; ForkTTY polls the getter briefly after spawn to record the
    PID, with a Linux direct-child process fallback while the embedded surface
    finishes startup, and the ABI falls back to Ghostty's PTY foreground PID while
    the mailbox value is not yet visible.
  • The socket surface.list result, and therefore forktty surfaces --json,
    now includes live runtime fields (shell, cols, rows, and pid when
    known) in the same rows as the model metadata.
  • Embedded Ghostty panes now back ForkTTY's Agent HUD tail reads
    and inline agent replies, so agent surfaces keep showing recent output and
    accepting panel replies when the embedded renderer is enabled.
  • Embedded Ghostty panes now handle ForkTTY's reset/clear command
    by routing it to Ghostty's native clear_screen keybinding action. This
    clears the embedded surface through Ghostty; a full terminal-state reset
    still depends on Ghostty exposing a dedicated keybinding action.
  • The Ghostty GTK Probe now requires the embedded exit_code, child_pid, and
    perform_action ABI symbols, and its smoke test verifies socket
    capture-tail, embedded pane startup, and that panes expose a positive PID
    through forktty surfaces --json. It also verifies that a clean child exit
    marks the pane non-writable with a Closed status.
  • The deb and AppImage packagers now require ghostty-gtk-embed.so in
    vendor/ghostty/zig-out/lib and install it into usr/lib, so installed
    builds load the embedded Ghostty library via the binary RUNPATH
    ($ORIGIN/../lib) without needing FORKTTY_GHOSTTY_GTK_LIB.
  • Team orchestration state is now available as a provider-neutral control
    plane through team.* socket methods, forktty team-* CLI commands, and MCP
    tools, covering leader/worker metadata, task DAGs, mailbox messages,
    heartbeats, provider worker launch into tabs, pane dispatch confirmations,
    worker health/lifecycle snapshots, idle nudges, safe shutdown requests,
    summaries, and event polling without adding parity UI yet.