Releases: Lucenx9/forktty
Release list
ForkTTY 0.2.0-alpha.18
[0.2.0-alpha.18] - 2026-07-06
Added
- Team workers can now persist a bounded final
reportthrough
team.worker.upsert, CLI, and MCP; the report is returned byteam.get,
counted inteam.summary, and surfaced inteam.worker.health. task.strategy.planandtask.strategy.applyresponses now include
planner_versionso agents can record which ForkTTY planner produced or
applied a routing decision.- Task strategy apply now bootstraps an initial
plannedworkflow loop record
for plans withlayers.loop_metadata: trueand context snapshots warn with
loop_never_recordedwhen such workflows are finished without loop
adoption evidence. The bootstrap now includes pending verifier-contract gates
so loops start with explicit review/implementation/verification checks. - Task strategy apply now appends an advisory next-best-harness hint to
assignment launchability and worker launch failures, naming the highest
scored other ready harness for the same role so callers can retry without
re-planning; apply never retries or substitutes harnesses on its own. - Task strategy
harness_signalsnow accept an optionalcooldown_kind
(quota,auth,crash, ortimeout) so the soft cooldown penalty scales
with the cause instead of weighing every reason the same; unknown kinds and
kinds withoutcooldown: trueare rejected. - Task strategy planning now infers an advisory soft cooldown for a harness
from ForkTTY's own workflow history (at least two recent failed
task-strategy workflows naming that harness, cleared by a newer success),
named in plan reasons and score factors; explicitharness_signalsstill
replace inference for the harnesses they name. - Added dry-run-first
orchestration.cleanupover socket, MCP
orchestration_cleanup, andforktty cleanup orchestrationso stale
team/workflow records can be inspected and conservatively closed without
touching live worker surfaces. - Added ergonomic workflow-loop CLI wrappers:
workflow-loop-gateto merge one
gate update,workflow-loop-step-doneto mark a stage complete, and
workflow-loop-publishto record a published commit stop reason without
hand-writing the full gates array. - Added
workflow-loop-iteration-startandworkflow-loop-iteration-done
wrappers so agents can advance bounded loop passes and record the pass result
without hand-writingworkflow.loop.setpayloads. - Added read-only
forktty worktree-doctordiagnostics that report repository
and linked-worktree health without creating, pruning, merging, or removing
any worktree state. - Added a short
GETTING_STARTED.mdwalkthrough anddocs/socket-api.md
stability map so users and agents can distinguish stable-for-alpha socket
calls from public alpha orchestration surfaces. - Added
METRICS.mdwith manual attention-first UI quality targets for the
Router rail and workflow feed. - Added an Attention-first UI smoke checklist to release QA so those metrics
are exercised before alpha releases instead of remaining advisory only. - Extended
METRICS.mdand release QA with general anti-slop UI quality checks
tied to the existing GTK visual rules.
Changed
- Softened the orange status dots so they read as quiet ambient cues: warn
.rail-dots (sidebar nav, worker/health, feed, pane footers) and the
.pane-attention-dotnow render at reduced opacity instead of full-strength
orange. - Quietened neutral status indicators so only meaningful state carries colour:
the workflow-feed "live" marker is now a small green dot plus a muted label
instead of a filled green pill, and the Router status chip's idle/neutral
state is plain muted text (transparent background/border) rather than a filled
grey box — active ok/warn/err states keep their subtle tinted pill. - Consolidated the orchestration status-signal palette (rail dots, rail-strip
badges, status chips, list rows, feed status) onto the shared semantic colour
tokens: warn and error indicators now render the same warm-orange
(@ft_warning) and danger red (@ft_danger) used elsewhere instead of two
divergent gold/red hues, and the status blue is now the named@ft_info
token — one hue per meaning across the whole app. - Agent-status badges in the sidebar (
.workspace-status-badge) and pane
headers (.pane-agent-badge) are now compact squared pills (5px radius,
tighter padding, hairline border) instead of fully rounded chips: live/running
reads sober green, needs-input/attention warm orange, idle/exited neutral
grey. - Normalized corner radii to a tight 3-step scale (4px small controls, 6px
buttons/badges, 8px cards/rows/dialogs, plus full-round pills), collapsing the
previous ad-hoc mix of 4/5/6/7/8px so nested surfaces read as one system. - Aligned the workflow-feed / router status chips (live / idle / warn) to the
token system: 6px radius, neutral surface + hairline tokens, and the warm
accent for the warning state. - Refined the header count badges (notification/agent) to a compact squared
chip on the sober warm accent, replacing the red/orange full-round dots. - Unified surface borders onto a single hairline color and evened out
horizontal-padding drift, so cards, rows, and dialogs share one border weight
and spacing rhythm instead of three near-identical grays. - Unified the "needs attention / needs input" accent across the app onto the
warm-orange ForkTTY accent (#e88745/#eaa06a), replacing the inconsistent
gold and peach tints previously used by the header attention button, sidebar
needs-attention rail, needs-attention pane border/dot, inline warning status,
and agent/notification prompt states. The distinct "current" row marker and
keyboard focus rings are unchanged. - The GTK workbench now follows the agent-workspace layout end to end: the
titlebar carries a Router cluster (breadcrumb, workspace selector, Plan and
Review Plan shortcuts into the read-only Router planner) plus live team
chips; the sidebar gains TEAM, RESOURCES, and Settings/About sections; the
right-side rail shows an attention-first summary plus structured
strategy/loop/approval/worker/report/notification rows with working
Review/Deny on pending Feed approvals and a notifications Clear-all; the
workflow feed gets wall-clock timestamps, per-kind status colors, filter
tabs, and a Clear button; split panes gain a slim footer with the shell name
and agent lifecycle; and the status bar summarizes the active Router strategy
and loop. - The workflow feed now includes an
ATTENTIONtab that isolates approvals,
errors, warnings, stale/conflict signals, and needs-input rows from routine
workflow/log churn. - The sidebar Resources section now exposes only the implemented Worktrees
shortcut instead of placeholder Knowledge Base, Snippets, Environments, and
Secrets rows. - The Router rail and bottom workflow feed can now be collapsed from their
headers for temporary workspace space recovery while the Settings toggles
remain the persistent show/hide controls. - Reworked both collapsed states: the collapsed Router rail is a slim strip
with an expand chevron plus pending-approval and unread-notification badges
(and now stays collapsed even after the divider has been dragged), the rail
header no longer scrolls away with the rail body, the workflow feed
collapses with a slide animation and re-expands when a feed tab is clicked,
collapse controls use chevron icons instead of ASCII arrows, and the rail
status and feed "live" pills were restyled (status pill now colored by
state instead of always green). - Settings follows the same agent-workspace pass: Interface gains live "Show
orchestration rail" and "Show workflow feed" toggles (new
appearance.show_orchestration_rail/appearance.show_workflow_feed
config keys, default on), Worktrees links the worktree manager, Agents can
re-scan provider readiness on demand, Notifications can clear the in-app
history, and Privacy states the local-first guarantees and stored data
locations next to the telemetry toggle. team.finishnow acceptscompact/--compactto finalize teams without
echoing the full team record and mailbox bodies in the response.- Team worker health now distinguishes workers that have no heartbeat plumbing
from stale workers and uses persisted agent-session lifecycle evidence to
reportidle,needs_input, ordonewhen hooks already recorded it. - The agent skill and operating guide now make verify-loop state recording
part of the strategy contract: when an applied task-strategy plan sets
layers.loop_metadata: true, apply seeds the initial planned loop record,
and agents must update stage/iteration/gates each pass and record the stop
reason at the end soloop_summariescan restore loop position after
context compaction. - Reduced the always-sent ForkTTY MCP initialize instructions and task-strategy
tool descriptions so agents get the routing essentials without duplicating
the full operating guide; the complete guide remains available through the
MCP resource and prompt. forktty skills setupandforktty skills removenow retain only the three
newest ForkTTY-managed skill backups per target and report pruned backups,
while leaving unmanaged.bak-*directories untouched.- Task strategy planning now accepts normalized
task_kind/task_class_hint
aliases such asbugfix,feature,review, andresearch, so agents can
pass clear user intent across languages without relying on ForkTTY keyword
guessing or exact internal enum names. - Task strategy planning now treats explicit iterative goals such as repeat
verification, iterative audits, and "keep checking until clean" as
verify-loop work, and preservesreview_onlystrategy for explicit review
hints while still settinglayers.loop_metadata: true; no hidden scheduler
is started. - The Router rail loop row now shows ...
ForkTTY 0.2.0-alpha.17
ForkTTY 0.2.0-alpha.17
Added
- Added app actions exposed in the Command Palette for moving the active
workspace up or down, with toast feedback when the workspace moves or is
already at an edge. - Added a read-only task strategy planner for agents and CLI users so ForkTTY
can recommend when to use solo work, workflow loops, reviewers, teams,
worktrees, MCP, and hooks before launching visible agent work. - Added staged task strategy apply over socket, CLI, and MCP so an approved
plan can create visible workflow/team/task/message coordination state without
launching hidden workers or sending terminal input. - Added approved
task.strategy.applysubmit support for supported team plans
so ForkTTY can launch visible worker panes and dispatch role prompts through
the team mailbox, including worktree-layer plans whenworktree_namenames an
already-open ForkTTY worktree workspace. - Added Feed-backed task strategy approval requests so
task.strategy.apply
can publish a pending start-run approval, stay blocked without workflow/team
mutation, and later consume the approved request-boundapproval_id. - Added task strategy safeguards so provider selection respects configured
team provider order, reviewer strategies always include a reviewer role, and
apply recomputes structural worktree and multi-worker submit approvals instead
of trusting a client-provided plan approval list. - Added task strategy context inference so
task.strategy.plancan derive
dirty git state from the selected surface/workspace cwd when callers omit an
explicitrepo_dirtyhint, and can infer likely user-visible edit intent
from goal wording when callers omit an explicit user-visible hint. - Added an explicit task strategy planning
cwdoverride for socket, CLI, and
MCP callers whose real repository cwd differs from the selected ForkTTY pane. - Added ranked candidate strategy scores to
task.strategy.planresponses so
agents can see why ForkTTY selected a mode and which alternatives were
considered before applying a plan. - Added role-aware harness assignment scores to
task.strategy.planresponses
so ForkTTY can prefer plan-mode reviewers and worktree-cwd-capable
implementers while keeping configured provider order as a tie-break. - Added task router profiles (
balanced,fast,conservative,parallel,
andreview_heavy) sotask.strategy.plan, MCPtask_strategy_plan, and
forktty task-plan --profilecan reweight the same explainable scorer
without making users manually choose team, loop, worktree, or harness modes. - Added per-harness task routing signals so scripts and MCP agents can pass
observed cooldowns as soft assignment penalties while hard task/mode lockouts
exclude a harness from the selected plan. - Added advisory last-known-good task routing so
task.strategy.plan, MCP,
andforktty task-plancan infer prior successful strategy/harness evidence
from completed task-strategy workflows or accept explicit caller evidence,
then apply only a small explainable score bias without overriding readiness,
cooldown, lockout, task fit, or approval rules. - Added Grok Build (
grok) as a visible team/router harness with Settings,
system.capabilities,team.worker.launch, and task-strategy routing
support.
Changed
- Reordered the main menu so the standard app items stay grouped, and the
sidebar toggle now reports its shown/hidden state with a toast. - Improved dark UI shortcut contrast in custom menus and the Command Palette,
and disabled workspace move commands when the active workspace is already at
an edge. - Improved
forktty task-plan --help,forktty task-apply --help, and
forktty feed respond --helpso task-router approval flows document their
positional goals, plan JSON,cwd, and approval decisions directly.
Fixed
- Fixed
cargo auditfailures by updating the Windows notification backend
dependency so the lockfile no longer includes vulnerablequick-xmlversions. - Fixed CLI boolean parsing so commands such as
forktty task-plan --repo-dirty false --parallel falsetreat the following
true/falsetoken as the option value instead of silently leaving it in the
positional task goal. - Fixed
team.summaryand compact context snapshots so workers whose terminal
surfaces disappeared are no longer counted as active and now raise a
consistency warning. - Fixed task strategy worker prompts so launched workers are told that the
leader already applied the plan and must not calltask.strategy.apply,
launch nested workers, or create nested worktrees unless separately directed. - Fixed command argv validation so GNU
envwrappers cannot hide shell
trampolines behind-- NAME=VALUEassignments,-a/--argv0arguments,
-S/--split-stringvalues that begin with--, or attached/clustered
-Sstringand-vSstringsplit-string forms. - Fixed Feed persistence so corrupt
feed.jsonfiles are quarantined instead
of disabling the Feed on every launch, Feed saves are fsync-backed like the
other stores, and approved approval rows are retained through notification
churn so latertask.strategy.applyretries can still consume them; prompt
notification approval decisions are now preserved only for the same persisted
prompt payload so a same-millisecond id collision after restart cannot inherit
an old decision. Feed writes and recovery now also reject duplicate entry ids
or inconsistent approval state instead of saving or loading ambiguous approval
rows. - Fixed team store validation/recovery and ack idempotency so legacy duplicate
persisted message ids are repaired on load by retaining the first message
while preserving delivered/superseded terminal state, strict saves reject
invalid state, and repeated message acknowledgements do not emit duplicate
team.message.ackedevents. - Fixed team/workflow store mutation ordering so event sequence failures cannot
leave in-memory plan, task, worker, or message updates partially applied
before the store update is rejected. - Fixed team/workflow store caps so creating a new record can evict the oldest
terminaldone/closed/cancelled/finishedrecord instead of leaving the
store permanently full until manual JSON editing. - Fixed
team.finish --close-workersso a worker surface close failure leaves
team and worker store state unchanged instead of persisting partial shutdown
requests or missing-surface worker cleanup before the error. - Fixed
team.finish --close-workersso closing multiple worker panes restores
any already-closed runtime surface if a later worker surface close fails,
avoiding a half-closed visible team after an error. - Fixed
team.finish --close-workersso closing a launch-owned worker pane that
became the only pane in an inactive workspace still spawns the normal
replacement terminal surface, and leaves the worker running if that
replacement cannot be spawned. - Fixed
team.worker.shutdown --close-surfaceso a worker surface close
failure leaves the worker store state unchanged instead of persisting a
partial shutdown request. - Fixed small GTK polish issues: failed worktree merge/remove notifications now
appear as errors, multi-tab close confirmations say tab instead of pane,
sidebar pane counts ignore extra tabs, context menu shortcut/copy icon hints
are consistent, notification clear copy matches the action, and workspace
popover buttons expose accessible names. - Fixed task strategy routing so parallel research/experiment plans respect
each harness's declared parallel session capacity instead of assigning
multiple concurrent roles to a single-session harness. - Fixed task strategy routing so a single launchable harness can provide
multiple parallel research lanes when its declared session capacity permits
it, instead of degrading to a non-parallel strategy. - Fixed task strategy routing so parallel research/experiment plans do not
launch an eager synthesizer worker before researcher workers can produce
output. - Fixed task strategy routing so review-requested implementer/reviewer plans
no longer require worktree isolation in clean repositories unless dirty-repo
edit isolation actually applies. - Fixed provider capability reporting so plan-mode support is exposed through
system.capabilitiesand used by task-strategy reviewer scoring. - Fixed task strategy approval retries so an approved Feed request covering a
superset of required approvals can still satisfy the remaining approvals when
the caller also supplies explicit attestations for part of the same request. - Fixed task strategy submit retries so an existing live worker is reused only
when its harness, role, task, worktree, and active worker status match the
current deterministic assignment; blocked, idle, or needs-input workers now
returnconflictbefore any prompt dispatch. - Fixed task strategy apply so conflicting
surface_idandleader_surface_id
aliases are rejected before dirty-repo checks or workflow/team mutation. - Fixed task strategy planning so explicit
cwdcontext is limited to Git
repositories already represented by an open ForkTTY workspace, surface, or
effective project cwd. - Fixed task strategy apply so explicit
cwdlaunch targets must also be
inside a Git repository already represented by an open ForkTTY workspace,
surface, or effective project cwd before any workflow/team mutation. - Fixed task strategy apply so explicit
cwdlaunch targets are canonicalized
before worker launch, prompt generation, and submit-retry compatibility
checks, keeping retries idempotent when callers switch between symlinked and
real paths for the same open repository. - Fixed task strategy apply so camelCase workspace selector aliases such as
workspaceIdandworktreeNametarget the same workspace for dirty-repo
inference and workflow/team mutation instead of ...
ForkTTY 0.2.0-alpha.16
ForkTTY 0.2.0-alpha.16 is an alpha release focused on socket/team/workspace reliability, AppImage hook/MCP setup, clean GTK shutdown, and disabled PTY-persistence cleanup.
Highlights
Fixed
- Fixed GTK window close so the embedded Unix-socket server receives a shutdown signal instead of keeping the ForkTTY GUI/AppImage process alive after the last window is closed.
- Fixed hook and MCP setup from AppImage launches so generated ForkTTY CLI commands set
APPIMAGE_EXTRACT_AND_RUN=1, preventing short hook calls and persistent MCP servers from leaving FUSE AppImage runtime mounts behind. - Fixed AppImage terminal launches with opt-in PTY process persistence so detached
dtachbrokers do not inherit AppImage runtime file descriptors and keep the FUSE mount alive after the GTK window closes. - Fixed opt-in PTY process persistence cleanup so disabling the setting, starting with it disabled, explicitly closing/restarting a pane, or closing the GTK window after disabling persistence terminates stale ForkTTY-managed
dtachbrokers and their child process trees instead of leaving detached terminals behind. - Fixed generated OpenCode hook plugins so they contain valid JavaScript constants instead of Rust visibility prefixes.
- Fixed official CLI/MCP socket clients timing out before slower server-side operations complete or rejecting valid bounded responses larger than 1 MiB.
- Fixed
team.message.dispatchso concurrent or post-send/failed-ack retries of the same queued message do not write the prompt to a terminal twice. - Fixed duplicate
team.worker.launchcalls for the same live launch-owned worker so the second call fails before leaving an orphaned worker pane. - Fixed
workspace.closeandworktree.removerollback and surface-set races so failed or concurrent close operations cannot leave orphan terminal runtimes behind. - Fixed team and workflow store updates to coordinate through per-store lock files, preventing lost updates when multiple ForkTTY processes share a state directory, and moved socket store I/O onto Tokio's blocking pool so slow filesystems do not stall unrelated socket requests.
- Fixed
events.subscribevalidation for non-booleanreplayvalues and capped event subscribers separately from the general socket request budget. - Fixed MCP tool metadata and
SPEC.mddrift for workflow loop state and non-idempotent team heartbeat/ack operations. - Fixed Antigravity hook setup so the generated
PreInvocationentry uses Antigravity's flat lifecycle-hook handler shape instead of the nested tool-hook matcher shape, allowing ForkTTY's before-model wrapper to load.
Security
- Restricted opt-in PTY process persistence to explicitly plain interactive terminal shell spawns so project actions and team-worker provider commands cannot be wrapped in
dtachand outlive their visible pane unexpectedly.
Artifacts
forktty-0.2.0-alpha.16-x86_64.AppImageforktty-0.2.0-alpha.16-x86_64.AppImage.zsyncforktty_0.2.0.alpha.16_amd64.debSHA256SUMS
SHA256
0bc6a755b5860b849deefe32aa15ffead6909224c73c2c8605a2eb3a23366daf forktty-0.2.0-alpha.16-x86_64.AppImage98900d471e9738cf6de4263060d11facc97d78f516caca24ff52eeae72bc7b37 forktty-0.2.0-alpha.16-x86_64.AppImage.zsyncddea003b25501b49886f90b0fcc8af15a52cd797b2027f87b9e87283143f9992 forktty_0.2.0.alpha.16_amd64.deb
ForkTTY 0.2.0-alpha.15
Added
- Opt-in real PTY/process persistence for generic terminal panes via a new
general.persist_terminal_processesconfig flag (default off). When enabled
and a detach/reattach broker (dtach) is onPATH, plain interactive
terminals run under the broker so their process tree (shell, dev servers,
REPLs, editors, long-running commands) survives a GTK UI restart; a relaunch
re-attaches the same surface to its still-running processes, keyed by the
persisted surface id. Agent panes (provider resume), SSH, and browser surfaces
are unaffected, and behavior is unchanged when the flag is off or no broker is
installed. The broker socket lives under the owner-only per-user runtime dir
and ForkTTY never wraps ash -ccommand.system.capabilitiesand
forktty capabilitiesreport whether the flag is configured and whether a
broker is currently available. Explicit ForkTTY pane close/restart removes
the per-surface broker socket so a later reused surface id starts fresh
instead of re-attaching to a stale detached session. Settings > Worktrees now
exposes a "Persist terminal processes" toggle and shows whetherdtachis
available from the running ForkTTY environment. - CLI automation now includes high-level
forktty team ask/watch/finish/review
wrappers,forktty status explain/watch, acontext-snapshotalias, grouped
help/examples, and generated bash/zsh/fish completions. forktty skills setupnow installs a ForkTTY agent orchestration skill for
Agent Skills-compatible tools (~/.agents/skills) and Claude Code
(~/.claude/skills) so agents have an explicit policy for proactively using
ForkTTY MCP, hooks, context snapshots, and team workers.- Socket
context.snapshotand MCPcontext_snapshotnow provide a compact
read-only workspace snapshot with pane/surface state, status, agent health,
compact workflow/team/feed/remote summaries, and bounded untrusted terminal
tails. Full workflow and team records are opt-in. system.capabilitiesnow advertises a provider capability matrix for the
supported team/resume providers (codex,claude,pi,opencode, and
antigravity) so socket and MCP clients do not need to infer provider support
by trial and error.- Agent rows returned by
agent.list,agent.health,status.summary, and
context.snapshotnow includelifecycle_evidence, a compact diagnostic
block that correlates the persisted lifecycle, freshness timestamps, current
workspace/provider status row, permission mode, and resume-readiness reason
where available. - Socket/MCP/CLI automation now includes
system.identify/identifyfor a
compact canonical workspace/surface/effective-project-cwd read, and CLI
automation addsforktty wait agent-statusfor bounded read-only polling of
persisted agent lifecycle state through shortcontext.snapshotreads. - Pi is now a supported team/resume provider: team launch accepts
--agent pi,
agent resume usespi --session <id>,forktty skills setup pialiases the
interoperable Agent Skills target, and Pi review workers default to read-only
--tools read,grep,find,lsunless explicit Pi tool args are supplied. - Team message dispatch now supports an explicit submit mode through socket
team.message.dispatch(submit: true), MCPteam_message_dispatch, and
CLIforktty team-message-dispatch --submit, appending a carriage-return
Enter to the dispatched terminal input when the message does not already end
in carriage return. - Socket/MCP/CLI automation now includes
team.finish/team_finish/
forktty team finishto verify team state, optionally close current-runtime
launch-owned disposable worker panes, normalize missing worker surfaces, and
mark the team done in one finalization step. - Workflow automation now includes bounded closed-loop state through socket
workflow.loop.set, MCPworkflow_loop_set, and CLI
forktty workflow-loop-set: agents can record a loop recipe, stage,
iteration budget, stop reason, and verification gate counts without granting
ForkTTY any background scheduler or automatic command execution. - Team worker launch now supports configurable provider auto-selection:
Settings > Agents exposes the default provider, fallback, provider order,
disabled providers, PATH detection, and direct command overrides for
non-default harness install locations; socket/MCP/CLI launches can omit
agentor passauto, and successful launches report the selected provider
and considered candidates.
Changed
- ForkTTY config no longer emits the obsolete
general.theme_sourcekey;
existing files that still contain it continue to load, and terminal theme
preferences remain owned by Ghostty config. - Command Palette, GTK context menus, Keyboard Shortcuts, About ForkTTY, and
Settings have been polished for clearer shortcut labeling, standard menu
access (F10outside terminal focus), richer About links, and correct
initial focus when opening directly to the Agents settings page. AGENTS.mdnow reflects the current MCP/team/workflow/skill/AppImage
maintenance flow, including final-binary skill checksum verification.- Agent HUD rows now show a compact workflow loop chip when a visible agent
surface is bound to closed-loop workflow state, with gate failures and
human-attention stops highlighted without adding a separate loop panel. - Pane drag-and-drop now exposes a visible header grip and tooltip clarifying
that dragging a pane header swaps panes. - Tab drag-and-drop now starts from the tab grip instead of the whole tab,
reducing accidental drags while selecting or closing tabs. - Notification panel and Agent HUD polish now make attention states easier to
scan: notifications group prompt/current-workspace history, avoid a duplicate
global open action, and use quieter tonal cards/chips/action areas; agent
rows show the current pane, group lifecycles, surface risky permission modes,
compact ended sessions, calmer status chips, compact risky permission labels,
and inline terminal previews. - Agent-oriented workspace chrome now uses more human scan labels and targets:
running agent rows/badges read as Working, ended rows read as Done, sidebar
metadata suppresses standing permission-mode noise, workspace paths prefer a
tracked agentresume_cwdwhen it differs from the launch directory,
notification jump prioritizes unread prompts, and high-level team CLI output
reports the worker, task, surface, provider, and submit state. - GTK chrome micro-polish now aligns workspace badges, pane action hover/focus
states, sidebar actions, status shortcuts, and pane hairlines with the quieter
Agent HUD and notification panel treatment.
Fixed
- AppImages now prefer the host GTK/libadwaita stack when it is available and
keep the bundled GTK copy as a fallback/override
(FORKTTY_APPIMAGE_GTK_RUNTIME=bundled|host|auto), preventing the Ubuntu
release bundle's GTK 4.14 runtime from failing embedded Ghostty OpenGL context
creation on newer desktop stacks. - Notification cleanup now stays coherent across surfaces: clearing through the
socket or notification panel closes matching desktop notifications, sends OSC
99 close reports when the terminal requested them, and marks pending prompt
approval feed rows asdismissed; stale prompt approvals whose target
workspace/surface disappeared now reportapproval_state: "stale"and no
longer raisepending_approvalrisk flags. - Workspace/surface-targeted desktop notifications now expose a best-effort
default Open action that focuses the relevant ForkTTY surface or workspace,
while terminal notification action buttons carry accessible labels and
app-authored notification chips use the clearerApplabel. - Team message dispatch and worker shutdown submit mode now use
provider-aware input: Claude receives staged text, a short settle, and a
separate Enter, while other providers keep text plus carriage-return Enter in
one terminal input. - Context snapshots now include compact
loop_summariesrows for workflow
loops, including stale surface-binding detection and risk flags for failed
gates, blocked/needs-human stages, exhausted loop budgets, and stale
workflow surface bindings; the rows omit full workflow goals and detailed
gate notes so default snapshots stay compact. - Workflow loop iteration updates now clear prior gate results and stop reasons
unless the same request supplies replacements, preventing stale failed gates
from carrying into a new verification pass. - Workflow consistency warnings now treat
completedplan steps as terminal,
matching existing workflow records and avoiding falsedone_with_open_plan_steps
risk flags in compact context snapshots. - CLI routing now recognizes
forktty workflow-loop-setand its socket-style
aliases, so the documented wrapper reachesworkflow.loop.setinstead of
being rejected as an unknown argument. - Worktree socket/CLI/MCP operations now ignore hook-reported agent
resume_cwd
metadata for repository authorization and only trust visible workspace roots
plus the recorded cwd of open surfaces, preventing spoofed hook metadata from
authorizing hidden worktree operations in unopened repositories. - Team worker launch no longer copies a leader's hook-reported
resume_cwdinto
the new worker surface cwd, preventing spoofed agent metadata from being
promoted into the worktree authorization boundary through a visible worker
tab. - CLI routing now accepts socket-style
worktree.*andproject.action.*
aliases in addition to the documented dash/colon forms, keeping low-level
worktree and project-action wrappers consistent with other socket methods. team.summarynow flags active teams that have no active workers, open tasks,
or pending messages asactive_without_open_work, so stale orchestration
records are visible before an agent mistakes...
ForkTTY 0.2.0-alpha.14
[0.2.0-alpha.14] - 2026-06-19
Fixed
- Embedded Ghostty terminal panes no longer force GTK's
cairosoftware
renderer, which leaked multi-GiB of live,malloc_trim-immune heap while
compositing the embedded GhosttyGtkGLAreaevery frame (most visible during
long full-screen agent TUI sessions such as Codex; idle and standalone
Ghostty were unaffected). ForkTTY now defaultsGSK_RENDERERto the GL
renderer (ngl), which composites the GLArea natively with no such growth.
An explicitGSK_RENDERERoverride is still honored for QA/debugging. - Embedded Ghostty panes no longer cap their redraw tick at ~10fps during
continuous output. That 100ms floor was a throttle against the old cairo
software-renderer leak; with the GL renderer default it only added latency,
so the tick now follows the 16ms wakeup-check cadence and GTK's frame clock. - AppImage packaging now bundles and verifies the runtime dependencies of the
embedded Ghostty GTK library itself, not only the main ForkTTY binary, so
GitHub-built AppImages do not ship smaller artifacts whose terminal panes
fail to start on distributions missing those libraries system-wide. - Embedded Ghostty panes now follow Ghostty's
scrollback-limitconfig, falling
back to Ghostty's bounded default budget (10 MB per surface) instead of
disabling retained history, so mouse-wheel scrollback works in freshly opened
terminal panes. - Embedded Ghostty panes now pack the raw Ghostty surface inside a GTK scrolled
window and honor Ghostty'sscrollbar = system|neverconfig, so retained
scrollback has the same visible vertical scrollbar behavior as standalone
Ghostty. - Agent health, explicit resume, and restore-time auto-resume now preserve
hook-reportedbypassPermissionssessions for Codex and Claude Code by
rebuilding argv with the providers' documented dangerous-mode flags
(codex --dangerously-bypass-approvals-and-sandbox resume ...and
claude --dangerously-skip-permissions --resume ...) instead of silently
resuming those panes back in prompted mode.
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 beforedlopen, while
allowing packaged AppImage libraries below sticky/tmpmounts. - 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
- Settings and newly saved configs no longer expose Ghostty-owned terminal
appearance/runtime controls (font_family,font_size,scrollback_lines,
terminal_audible_bell,terminal_renderer,terminal_theme). Those TOML
keys still load for compatibility, but ForkTTY now leaves font, theme, bell,
and terminal rendering behavior to Ghostty's config and keeps only
ForkTTY-owned settings in the visible UI. - ForkTTY documentation, package metadata, first-run privacy link, and the
anonymous telemetry endpoint now use the canonicalhttps://forktty.dev
domain. - Documented the
.debruntime baseline as Debian 13/Trixie+ and Ubuntu
24.04 LTS+, and added a repeatablepiupartsinstall/purge release check. - Clarified privacy/security documentation around the anonymous daily ping,
update checks, and packaged source/license availability. - 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.shellmanually inconfig.toml, while the dialog focuses on
ForkTTY-owned behavior and appearance.
Fixed
- Embedded Ghostty panes now disable cursor blinking in the embedded runtime
and drain Ghostty's app mailbox from a wakeup callback instead of polling
ghostty_gtk_context_tick()while idle, preventing background memory growth
even when no terminal output is being rendered. - Embedded Ghostty panes now coalesce continuous wakeups before ticking
Ghostty's GTK app mailbox, avoiding redundant GTK runtime work during bursty
terminal output. - AppImages now prefer the bundled
usr/lib/ghostty-gtk-embed.sobefore any
development checkout undervendor/ghostty, so package smoke tests and user
runs exercise the same embedded Ghostty library unless explicitly overridden
withFORKTTY_GHOSTTY_GTK_LIB. - First-launch onboarding now describes the default workspace as the user's
home directory instead of the process current directory, matching the actual
startup behavior. - AppImages now bundle
libgtk4-layer-shell.sobeside the embedded Ghostty
GTK library, and Debian packages now declarelibgtk4-layer-shell0, so
terminal panes can start on systems such as Fedora that do not have
gtk4-layer-shell installed globally. - AppRun now always uses the bundled GTK/libadwaita userspace stack, while
still leaving glibc, fontconfig/text shaping, display-server libraries, and
GPU drivers host-side, so AppImages no longer depend on host GTK packages. - Debian and AppImage packaging now include ForkTTY copyright/license text and
third-party notices for the vendored Ghostty runtime artifacts. - 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_DIRSis 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 Mochainstead of falling back to the default colors. - 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
ReleaseSafeoptimization profile and a linker-compatible Blueprint helper,
avoiding local Zig/GCC.sframelinker failures andReleaseFast
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
Escapein 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-surfaceFORKTTY_*environment setup no longer
appears as a typedexec /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, soread_text/capture_tailrequests 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 invisible_screen_rows. - Failed
agent.hibernateclose 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 ptystdin 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 ...
ForkTTY 0.2.0-alpha.13
[0.2.0-alpha.13] - 2026-06-16
Security
- Stop hooks now preserve agent permission-mode warnings when the provider has a later session-end cleanup, while providers without session-end hooks still clear the warning on final stop.
- Terminal smooth-scroll handling now rejects non-finite deltas and caps per-event line replay, preventing oversized synthetic scroll events from monopolizing the UI thread while mouse tracking is active.
- Browser automation now injects and evaluates its driver in an isolated WebKit script world, preventing visited pages from detecting or tampering with
window.__forktty. - Chromium cookie import now verifies the version-24+ encrypted host digest before accepting decrypted values, rejecting malformed or cross-host cookie rows.
- Agent resume PTY spawns now resolve bare provider commands using only absolute
PATHentries before applying the recorded session cwd, preventing relative/emptyPATHentries from executing project-local binaries during restore or resume. - Socket hook correlation now rejects
hook_session_idvalues larger than the metadata text limit before caching them, preventing a local client from retaining many near-request-size session IDs in memory. - Socket-triggered notification dispatch and custom notification command reaping now use bounded queues instead of spawning unbounded OS threads per
notification.create, preventing a local client from exhausting threads by flooding notifications.
Added
forktty doctornow accepts--hooks,--socket, and--packagingscopes for running only the relevant local diagnostics.- First launch now shows a one-time welcome dialog: an informed (default-on) telemetry toggle linking to the privacy notice, and a one-click "Set up agent integration" button that runs
hooks setupandmcp setup. The first anonymous ping is deferred until this dialog is dismissed, so the toggle is always seen before any data leaves the machine; the welcome is recorded in$XDG_STATE_HOME/forktty/welcome-seen.jsonand the update check is skipped on that first launch. - The GTK app now sends at most one anonymous daily usage ping when
telemetry.anonymous_ping = true(the default). The payload contains only schema/kind/app/version/date, can be disabled in Settings or config, and crash uploads remain unimplemented. - The GTK app now checks GitHub Releases at most once per day when
updates.auto_check = true, shows update availability in-app, opens the release page for non-AppImage installs, and can self-update writable AppImages after explicit confirmation by downloading the AppImage plusSHA256SUMS, verifying SHA256, and atomically replacing the current file. - Release AppImages can now embed AppImage update information and ship a matching
.zsyncasset whenAPPIMAGE_UPDATE_INFO=1is used during packaging; release CI enables this and includes.zsyncinSHA256SUMS. - Agent HUD rows now include a Forget action with Undo, so stale tracked sessions can be removed from the HUD without closing the terminal or deleting provider data.
- Agent HUD rows now show an accent unread dot when an agent has produced output you have not viewed since last focusing it, and float those rows up within their lifecycle group — so a finished (idle) agent whose result is still unseen stands out instead of sinking to the bottom of the list.
Fixed
- The terminal pane header now keeps the Close Pane button on the far right of split-pane headers instead of clustering it beside the split and new-tab actions.
- Worktree list/status reporting now treats registered worktree paths replaced by files, symlinks, or invalid directories as unknown instead of clean/dirty.
- Command palette and Settings selection states now use neutral row highlights instead of heavy accent rails.
- Settings toggles are now smaller and use a subtler checked state.
- Settings sidebar navigation is now more compact, with item descriptions kept in tooltips and accessibility labels instead of visible subtitles.
- Settings pages now use shorter page and section copy, hiding redundant section descriptions.
- Settings, Agent HUD, and Notifications now expose a maximize/restore titlebar control and enforce minimum window sizes, while Command Palette windows stay fixed-size.
- Settings now labels the privacy and reset page as Privacy instead of Advanced.
- Agent HUD now relies on its titlebar close button and Esc instead of showing a duplicate Close footer button.
- Agent HUD now opens shorter when sessions are present, keeps its empty state unclipped, uses flatter rows, and gives row actions clearer visual hierarchy.
- Worktree merge selected by worktree name now merges that worktree's branch even when an unrelated local branch shares the worktree's derived name (e.g. worktree
feat-afor branchfeat/aalongside a separatefeat-abranch), matching the worktree the cleanliness check already validates instead of silently merging the wrong branch. - Config loading now normalizes a
notification_commandthat tokenizes to zero words (for example an inline shell comment like"# disabled") to an empty command instead of rejecting it and quarantining the entire config, so a benign command value no longer resets every other setting to defaults. - Nested worktree creation now appends
.worktrees/to.git/info/excludeeven when the existing exclude file contains non-UTF-8 bytes, instead of failing before creating the worktree. - Agent session-end hooks now mark the persisted agent binding as ended when clearing its live status, so agents whose providers emit a session-end event no longer remain shown as running in the Agent HUD.
- Chromium bookmark import, browser bookmark loading, and browser profile metadata loading now reject or skip non-regular files before reading, preventing local FIFO/device paths from blocking the import or profile workflows.
- Socket metadata calls now reject stale explicit
surface_idvalues even whenworkspace_idis valid, oversized request lines return the documentedpayload_too_largecode, and invalid parameter errors use the documentedinvalid_paramcode. - Config recovery now quarantines config paths that resolve to FIFOs without blocking application startup.
- Worktree create now propagates branch lookup errors other than
NotFoundinstead of treating every libgit2 failure as a missing branch. - Creating or attaching a worktree whose registration survived an external deletion of its working directory now prunes the stale registration and recreates the worktree in place, instead of failing with an unresolved-path error;
createadopts the existing branch in this case and never deletes a pre-existing branch during cleanup. ProfileStore::savenow creates thebrowser_profilesdirectory with owner-only (0700) permissions instead of inheriting the umask, so profile metadata is not world-readable on multi-user systems when the directory is first created via the socket API.ProfileStore::savenow hardens an existingbrowser_profilesdirectory owned by the current uid/gid by removing group/other permission bits before writing profile metadata.- Browser import spooling now uses anonymous (unlinked) temp files instead of named temp files, so spooled pre-read data is reclaimed automatically if the process is killed mid-import.
- Browser imports now spool pre-read source data to temporary files instead of retaining every selected profile in memory, preventing large all-source imports from exhausting memory while preserving all-or-nothing read validation before writes begin.
- Update checks now honor HTTP-date
Retry-Afterheaders from GitHub rate-limit responses instead of retrying before the requested deadline. - Restarting an agent pane now resumes the agent session (provider resume argv and recorded cwd) instead of relaunching a plain shell, matching the session-restore and worktree spawn paths.
- Session restore now quarantines a session file containing invalid UTF-8 instead of returning an error that crashed startup on every launch.
- The first-run welcome dialog now stays open when persisting a telemetry opt-out fails (e.g. a read-only config directory), so it cannot silently fall back to the default-enabled ping without giving the user a chance to fix permissions or re-enable telemetry.
- Saving browser bookmarks now creates the profile directory with owner-only (
0700) permissions instead of inheriting the umask, matching the history database directory, so bookmark URLs are not exposed when a profile's first write is a bookmark. - Bookmark entries now bound the stored URL and title to the same size caps as history visits, preventing an oversized imported bookmark from growing
bookmarks.jsonuntil it becomes unreadable. - Shell trampoline detection now keeps scanning after shell options that take a value, so
bash -o vi -c ...andbash --rcfile file -c ...notification commands are rejected instead of bypassing the-cguard. - Shell trampoline detection now recognizes PowerShell's command grammar, so
pwsh -Command ...,pwsh -EncodedCommand ..., andpwsh -CommandWithArgs ...notification commands (and their-c/-e/-ec/-cwaaliases) are rejected instead of bypassing the shell-command guard. PtySession::read_untilnow reportsUnexpectedEofwhen a child exits before the requested bytes arrive, instead of returning partial output as success.forktty hooks testnow sanitizes socket error text before rendering human-readable failures, preventing local socket responses from injecting terminal control sequences.- Browser import is now limited to the in-app Settings workflow and is no longer advertised or accepted over the socket/CLI automation boundary, preventing local socket clients from using ForkTTY to read external browser profile data.
- Notification command validation now rejects
rbash -cshell trampolines instead of allowing restricted Bash aliases to bypass the shell-command guard. - Session ...
ForkTTY 0.2.0-alpha.12
[0.2.0-alpha.12] - 2026-06-13
Added
- Terminal panes now show terse toasts for copy/paste failures and flash an accent border for visual bell events.
- Terminal panes now show a minimal overlay scrollback indicator while viewing history.
- Terminal content now has balanced 6px inner padding so text does not touch pane edges.
- Split terminal panes now dim unfocused panes slightly so the focused pane is easier to pick out.
- Ctrl+click opens links: OSC 8 hyperlinks and plain
http(s):///file://URLs in the output (also when wrapped across lines). Hovering with Ctrl held shows a pointer cursor and underlines the target. - Middle-click pastes the PRIMARY selection (select text, middle-click to paste — the standard Linux flow); Shift+middle-click pastes even inside mouse-tracking apps.
- Shift+PageUp/PageDown page through the terminal scrollback, Shift+Home/End jump to its start/end; inside full-screen apps (vim, htop) the keys keep going to the app.
- Typing or pasting in a scrolled-up terminal now snaps the viewport back to the bottom, like other terminals; output arriving while you read scrollback still leaves the viewport where it is.
- Agent hook status updates now persist a per-surface agent session binding (
agent+ providersession_id) whenmetadata.set_statuscarrieshook_session_id, plus the provider session cwd asresume_cwdwhen available, giving future resume work stable session state instead of a runtime-only hook cache. - Persisted agent session bindings now carry lifecycle state (
running,idle,needs_input,ended, orunknown) derived from hook events, giving future hibernation/reclaim work an explicit ended-vs-idle signal. - Persisted agent session bindings now track hook-derived
last_activity_ms, so automation can reason about idle age without scraping provider files. agent.list,forktty agents, and the read-only MCP toolagent_listnow expose persisted per-surface agent session ids, resume cwd, lifecycle, and last activity, so resume/HUD automation can discover Codex/Claude/Gemini/OpenCode/Antigravity sessions without scrapingsession-v2.json.agent.health,forktty agent-health, and MCPagent_healthnow report whether persisted agent sessions have a supported argv-only resume command and provider executable on PATH before attempting a resume.agent.reclaim.plan,forktty agent-reclaim-plan, and MCPagent_reclaim_plannow provide a read-only reclaim plan that classifies old idle, locally-resumable agent sessions as candidates and protects running/input-needed/ended/recent/not-ready sessions with explicit reasons.agent.resume,forktty resume-agent, and MCPagent_resumenow resume a persisted Codex, Claude Code, Gemini, OpenCode, or Antigravity session in a new ForkTTY tab using provider-specific argv-only commands.- Restored terminal surfaces with a persisted supported agent session now respawn through the provider's argv-only resume command instead of opening a plain shell after a ForkTTY restart; Codex sessions with a persisted hook cwd, or a cwd found in Codex's local
session_metaJSONL, usecodex resume -C <cwd> <id>to avoid Codex's resume-directory prompt when the pane cwd differs from the session cwd, and providers without a cwd flag such as Claude Code are spawned with the recorded cwd as their process directory. status.summary,forktty statusline, and MCPstatus_summarynow provide a compact read-only workspace summary with persisted agent sessions, status entries, and progress entries for agent statusline/HUD integrations.- The GTK app now has an Agent HUD in the titlebar and command palette, showing persisted agent sessions across workspaces with lifecycle, last activity, cwd/session context, needs-input highlighting, focus, and resume actions.
- The Agent HUD updates live while open (one-second model re-snapshot that rebuilds rows only when they changed), shows each agent's last terminal output line refreshed in place (generation-gated so idle agents cost nothing), and its rows are keyboard-activatable — Enter or a click on a row focuses that agent's pane.
- Agent HUD needs-input rows now show what the agent is actually waiting on (the hook prompt message, e.g. a permission request) instead of the raw terminal tail, and gain an inline reply entry that types the answer (plus Enter) straight into the agent's terminal without leaving the HUD; the list never rebuilds while a reply is being typed.
- The MCP server now exposes a
forktty://agent/operating-guideresource and aforktty_operating_guideprompt, plus matching initialize instructions, so agents can discover when ForkTTY tools are useful and when to keep working normally. surface.read_text,surface.capture_tail,topology.tree, CLIforktty read-screen/capture-tail/tree, and MCPsurface_read_text/surface_capture_tail/topology_treenow give agents read-only terminal inspection primitives before they focus or drive another pane.forktty --json hooks doctor <agent>andforktty --json hooks test <agent>are now a stable machine-readable API (documented in SPEC.md): versioned report with an overallok, per-method{method, ok, error?}results forhooks test(which keeps running after a failed method instead of aborting, so cleanup still happens and the report is complete), and exit code 0/1 reflecting overall health for CI gating. The Codex trust state stays a first-class field of the doctor report.- The worktree open-workspace boundary rejection now carries the structured error code
precondition_failed(documented in SPEC.md), and MCP tool errors with a known recovery carry machine-readableremedyandsuggested_toolfields instructuredContent— the boundary error points atworkspace_create, so an agent can recover without parsing prose.
Changed
- Touchpad scrolling in terminal panes now accumulates smooth deltas instead of forcing chunky wheel ticks.
- The declared Rust MSRV is now 1.96, matching the current
rusqlite/libsqlite3-sysdependency chain required by the workspace lockfile. - The competitive gap inventory now includes the non-browser cmux gaps plus the additional control-plane gaps found in oh-my-codex and oh-my-claudecode: workflow state/artifacts, team runtime, HUD/statusline export, and agent/skill catalogs.
- Gemini CLI integrations are now legacy opt-in: default
forktty hooks setupandforktty mcp setupskip Gemini and prefer Antigravity, while explicit Gemini setup/remove/doctor/test and persisted Gemini resume compatibility remain supported. - Claude Code session-start context now includes the same concise ForkTTY tool-use policy as the MCP operating guide: use ForkTTY for panes, agents, worktrees, status, or cross-surface text, but avoid tool calls for ordinary single-repo edits.
Fixed
- Agent resume now preserves hook-reported
bypassPermissionsmode for Claude Code and Codex sessions: Claude resumes with--dangerously-skip-permissions, and Codex/yolo resumes with--dangerously-bypass-approvals-and-sandbox. - Copying a soft-wrapped line (a long command or paragraph the terminal wrapped to fit the width) no longer inserts a spurious newline at each wrap point: selection copy, the no-selection viewport copy, and select-all now rejoin soft-wrapped rows into their logical line, so pasting a wrapped command back into a shell runs it as one line instead of splitting it.
- Selecting text by clicking an unfocused terminal pane no longer leaves the selection stuck following the pointer: the focus gesture claiming that first click used to cancel the selection drag without a release, stranding the
selectingflag, so the highlight kept extending on every mouse move with no button held. The drag now finalizes on gesture cancel and whenever button 1 is no longer physically down. - Dragging a left-click selection in an agent pane (deferred local drag) no longer aborts the app with a
RefCell already borrowedpanic in the motion handler. - Terminal pane edge polish: double/triple-clicks and Ctrl+click/Ctrl+hover a few pixels into a pane's trailing gutter now select the last row/word and resolve last-row links instead of doing nothing; the pane being searched no longer dims while its search entry holds focus; middle-click or paste with an empty clipboard no longer shows a spurious "Paste failed" toast; and copying with an active selection still works when the terminal backend fails to render a frame.
- Wayland touchpad scrolling in terminal panes no longer overscrolls roughly 30x: smooth-scroll deltas arrive in surface (logical pixel) units on Wayland and are now converted through the pane's cell height, while X11 smooth deltas and wheel ticks keep the 3-lines-per-tick mapping.
- Scrolling inside mouse-tracking applications (vim, htop, tmux) now forwards one wheel press per three accumulated lines — matching physical-wheel speed — instead of one press per line, and hi-resolution wheels' fractional ticks accumulate into whole presses/lines instead of overscrolling on every fraction of a notch.
- Mouse events in terminal padding now clamp to the nearest grid edge instead of reporting past the last cell to mouse-tracking applications.
- Terminal copy failures no longer clear the existing clipboard contents, and the scrollback indicator no longer risks a panic during very small transient GTK allocations.
- Terminal resize no longer aborts inside libghostty when GTK briefly reports a one-row allocation after wrapped output.
- Terminal resize no longer aborts inside libghostty when maximizing a window with wrapped scrollback; the vendored Ghostty build now uses a temporary cursor-preservation pin and bounded wrap-count walks during column reflow.
- Terminal mouse selection, Ctrl+click link detection, and mouse-tracking coordinates now account for the terminal widget's CSS padding, so highlighted/copied text lines up with the visible character grid.
- Agent terminal panes now keep plain cli...
ForkTTY 0.2.0-alpha.9
Changed
- The Settings dialog was reorganized and rebuilt with standard GNOME preference rows: the terminal palette now lives on the Terminal page next to font and scrollback, the Alerts page is named Notifications, enum options (palette, window mode, sidebar position, worktree layout, font family) use combo rows with explicit value mapping instead of free-form combo boxes, font size and scrollback use spin rows with the validated bounds, the font picker is searchable, and an invalid shell or notification command now marks the row in red in addition to the error toast.
- Dropped the vendored
libghostty-vt-syscopy: upstream libghostty-rs now makes the zig optimize mode follow the Cargo profile (Uzaaft/libghostty-rs#55), so both libghostty crates are pinned to upstream master via[patch.crates-io], withLIBGHOSTTY_VT_SYS_OPTIMIZE=ReleaseSafepinned in.cargo/config.tomlso debug and test builds keep the optimized VT parser. The lines-to-bytes scrollback conversion stays on our side (upstream C API issue, Uzaaft/libghostty-rs#56).
Added
- Double-click selects the word under the pointer (ghostty's default word boundaries, so paths like
/tmp/a.txtselect whole) and triple-click selects the visual row; both publish to the PRIMARY selection like a finished drag and work with Shift inside mouse-tracking apps. - Dragging a selection past the top or bottom edge of a pane now autoscrolls the viewport (faster the further the pointer goes) and keeps extending the selection; the selection is re-anchored under the scroll instead of being dropped.
- Panics now also append message, location, and backtrace to
$XDG_STATE_HOME/forktty/panic.logbefore the process dies, so field crashes (which abort inside GTK signal trampolines) no longer require coredump symbolization to diagnose. - The session state is now guarded by a lock file: a second running instance (e.g. a deb-installed and an AppImage forktty that DBus could not deduplicate) refuses to start instead of silently fighting the first one's session autosave.
Fixed
- An empty or malformed OSC 99 sequence no longer leaves a debug-formatted "Terminal metadata" status entry in the sidebar; it is ignored.
- Terminal pixel-size reports now keep the measured cell dimensions after pane-only cell resizes instead of reverting to the 10x20 startup fallback.
- Terminal OSC 110/111/104 color resets now restore ForkTTY's configured theme defaults instead of falling back to libghostty's built-in black/background palette.
- Dead-key and compose-key input now has the GTK input-method handoff documented at the terminal key fallback, clarifying why committed text is not duplicated by fallback key encoding.
- The search bar's match counter no longer shows a stale "current/total" after new terminal output removes the match highlight; it resets to 0/0 until the next step.
- Two processes quarantining the same corrupt profile/bookmark store at the same time can no longer overwrite each other's backup file.
- The sidebar toggle and the periodic PR lookup no longer read the config file on the GTK main thread, and the 2s session autosave no longer builds a debug dump of the whole session to detect changes.
- An
events.subscribeclient that stops reading is now disconnected after 10s instead of holding one of the 64 socket connection slots forever; enough stuck subscribers used to silently deny the socket to agent hooks. - The event stream now reports a surface whose owning workspace changes (session-restore repair) by re-asserting it as removed + added; subscribers' per-workspace surface lists used to go silently stale.
forktty eventsflushes every event line, so piped consumers (| jq,| while read) see events as they happen instead of in 8KB bursts; when the server drops events because the consumer lags, a warning now also lands on stderr.
CI
- CI now verifies on every push that the binary carries the RUNPATH it needs to find the bundled libghostty, and the release smoke test runs the packaged binaries exactly the way the alpha.7 field failures did: the deb tree and the extracted AppImage's inner binary without any
LD_LIBRARY_PATH, plus theFORKTTY_APPIMAGEexports in AppRun.
Downloads: the AppImage is the primary download for this alpha; the .deb remains available for Debian/Ubuntu. Supported distros: see docs/QA.md. SHA256SUMS is attached — verify with sha256sum -c SHA256SUMS.
Upgrading from v0.2.0-alpha.7 or older AppImages: re-run forktty hooks setup so agent hooks point at the stable launcher path.
ForkTTY 0.2.0-alpha.11
Added
- MCP tools now declare spec tool annotations (
readOnlyHint,destructiveHint,idempotentHint,openWorldHint) so clients can surface risk before invoking: list/status tools are read-only,worktree_removeis flagged destructive,status_set/surface_focusare idempotent, and every tool is closed-world (local instance only). - New MCP tool
workspace_create(working_dir + optional name): agents can open a workspace on a repository themselves, which is the precondition the worktree tools enforce — precondition error,workspace_create, retry, without leaving MCP.
Changed
- Every socket CLI subcommand now answers
--helpwith its accepted options (generated from the same allow-list validation uses), andcreate-workspaceaccepts--cwdas an alias for--working-dir, matching the worktree commands' spelling. - The worktree open-workspace boundary rejection now names the open workspace roots and the
forktty create-workspace --working-dir <repo>remedy instead of a bare "cwd must be inside the git repository of an open workspace"; the MCP worktree tool descriptions state the precondition up front and SPEC.md documents the boundary as deliberate.
Fixed
- Worktree socket operations no longer run their git work on the socket server's async runtime:
worktree.create/removeexecute the repo's setup/teardown hook (up to 30s) and every worktree method walks the repository on disk, which pinned tokio workers and could starve other socket connections (agent hook status updates timing out) while worktrees were being created or removed in parallel. The git2 work, the hooks, the open-workspace boundary validation, and the config read now run on the blocking pool. - Creating a notification through the socket (
notification.createfrom the CLI, MCP server, or agent hooks) no longer kills the connection without a response when desktop notifications are enabled: the desktop notifier blocks on its own async runtime, which panics inside the socket server's runtime ("Cannot start a runtime from within a runtime"); dispatch now runs on a dedicated thread. - MCP list tools (
workspace_list,surface_list,worktree_list) no longer fail with strict MCP clients (including Claude Code): the socket returns bare JSON arrays for list methods and the server passed them straight through asstructuredContent, which the MCP spec requires to be an object. Non-object results are now wrapped as{"result": ...}.
Downloads: the AppImage is the primary download for this alpha; the .deb remains available for Debian/Ubuntu. Supported distros: see docs/QA.md. SHA256SUMS is attached — verify with sha256sum -c SHA256SUMS.
This release hardens the socket/MCP/hooks integration shipped in alpha.10: every bug found during the post-release MCP and hooks verification is fixed here. If you use the MCP server with Claude Code, the list tools now work; notification.create no longer drops the connection.
ForkTTY 0.2.0-alpha.10
Fixed
- The pty master and slave are now opened with
O_CLOEXECatomically (posix_openpt) instead of setting the flag afteropenpty(): a process forked on another thread in that window (worktree hooks, notification commands) inherited the descriptors and kept the pty alive past its session. Slave duplicates for the child's stdio useF_DUPFD_CLOEXECfor the same reason. - Release binaries no longer inherit the CPU feature set of the CI build machine: libghostty's zig build now targets the generic x86-64 baseline (
-Dcpu=baseline, via a vendored one-line patch invendor/libghostty-rs). The first alpha.10 cut was built on an AVX-512 runner and its statically linkedmemsetcrashed every non-AVX-512 machine with SIGILL at startup; the same lottery silently applied to every release since alpha.7.
Added
forktty mcpnow runs a local stdio MCP server exposing ForkTTY workspaces, surfaces, worktrees, notifications, and status metadata as typed tools;forktty mcp setup/removeregisters the server for Codex, Claude Code, Gemini CLI, and Antigravity while preserving foreign MCP servers (Codexconfig.tomlis edited in place, keeping comments and formatting). Claude Code session-start hooks now include ForkTTY workspace/branch context and a short MCP/CLI capability cheat sheet.- Agent hooks for Antigravity CLI (
agy, Google's Gemini CLI successor):forktty hooks setup antigravityinstalls a ForkTTY-owned"forktty"group in~/.gemini/config/hooks.jsonfor the verifiedPreInvocation/PreToolUse/PostToolUseevents, plus generated wrapper scripts (Antigravity executes a hook command as one bare executable path, without arguments or a shell). Sessions are correlated viaconversationId, hook responses use the strict-protojson-safe{}, andhooks doctor antigravityreports the launcher state from the generated scripts. Gemini CLI hooks remain supported. forktty hooks doctor codexnow reportstrustCheck: Codex requires per-hook trust approval (recorded under[hooks.state]in itsconfig.toml) before running installed hooks, so the doctor lists events with no approval record yet and points at/hooksinside Codex.
Changed
forktty hooks setup claudenow installs lifecycle hooks by default and omits the blocking per-toolPreToolUse/PostToolUse/PostToolUseFailure/PostToolBatchhooks; useforktty hooks setup --full claudeto restore the previous full profile. Existing installs keep working, and re-running setup migrates Claude hooks to the lifecycle default unless--fullis passed.- Chromium bookmark import now deserializes only the bookmark fields ForkTTY uses, avoiding large extra allocations for ignored browser metadata.
Security
- Pasted text is now encoded with libghostty's paste encoder, which neutralizes control bytes in the payload: clipboard content containing
\x1b[201~can no longer terminate the bracketed-paste wrapper early and inject the remainder as typed input (including command execution in a shell). - A socket client that sends a request and then stops reading the response is now disconnected after a write timeout instead of holding one of the 64 connection slots forever; enough stuck clients used to deny the socket to agent hooks.
Fixed
- Agent hook status updates that lose
FORKTTY_WORKSPACE_ID/FORKTTY_SURFACE_IDafter session start (for example through tmux, ssh, or containers) can now be attributed back to the originating pane byhook_session_idwhen the socket server has seen that session with explicit targets. - "Merge Worktree" now works when invoked from inside a linked worktree (it used to always fail with "Cannot resolve admin directory"), and fast-forward merges update the main checkout's files instead of only moving the branch ref.
- Large pastes (bigger than the kernel pty buffer, ~12KB) are no longer silently truncated; the terminal now waits for the child to drain its input, with a 10s safety timeout. Automatic VT query replies sent over the same path can no longer be cut off mid-sequence either.
- Splitting panes beyond the persistable depth (6 nested splits) is refused instead of silently breaking every subsequent session autosave and losing the layout on restart.
- Ctrl with non-letter keys (Space,
[,\,],^,_,?) now sends the standard C0 control codes instead of nothing. - In maximize mode, focus changes that don't alter the pane tree (command palette "Focus Next Pane", socket
surface.focus) now switch the visible pane instead of leaving a stale one on screen. - The Close Pane confirmation now closes the pane it was opened for, even if a socket client switched the active workspace while the dialog was open.
- Piped CLI output (
forktty list --json | head -1and similar) no longer panics with exit 101 and a panic.log entry when the consumer closes the pipe early. - "Reset Terminal" no longer reverts the pane to libghostty's default colors; the configured theme is re-applied and stale paste/focus mode state is cleared.
- A configured shell or notification command that is temporarily missing from disk no longer quarantines the whole config and resets every setting to defaults; the value is normalized (default shell / cleared command) on load instead.
- The socket server keeps serving through transient
accept()failures such as file-descriptor exhaustion (EMFILE/ENFILE) instead of shutting down for the rest of the app's lifetime. - Two concurrent closes of the last workspace (or a close racing a worktree removal) no longer leave a duplicate replacement workspace.
- Replacing a pane or workspace context menu no longer risks a re-entrant
RefCellcrash from the popover's synchronousclosedsignal. - Saving a setting from the Settings dialog no longer reverts config changes made outside the dialog while it was open (e.g. the F9 sidebar toggle); each change is rebased onto the config on disk.
forktty doctor --socket/--verbose/--debugnow explains thatdoctorruns locally and that the socket doctor takes global flags first (forktty --json doctor); the CLI help documents the reachable spelling.- Hook event ordering now uses CLOCK_BOOTTIME instead of the wall clock, so hook status updates are no longer silently dropped after the system clock steps backwards; orders from different clock sources are no longer compared against each other.
forktty hookswith a missing or typoed subcommand now exits with a helpful error instead of printing hook continue-JSON and exiting 0.worktree-statusrejects combining a positional path with--path/--cwdinstead of silently ignoring the positional, matching its sibling commands.forktty --json doctorandforktty hooks setupno longer hang forever when an inspected config path is a FIFO.- Socket connections from the CLI and agent hooks are bounded by a connect timeout instead of hanging when the app's accept backlog is full.
- A poisoned model lock no longer makes the socket event stream broadcast false removal events for every workspace and surface.
- Workspace cwd validation no longer runs git repository discovery while holding the model lock shared with the UI thread, and the startup socket probe now has an overall deadline instead of only per-read timeouts.
- Shell-trampoline detection for the notification command now catches clustered flags (
bash -lc), separated flags (bash -x -c), andenv-wrapped shells (env bash -c). - A child process flooding its terminal can no longer hold the UI in a single unbounded read; terminal reads are capped at 1MiB per pump tick.
Downloads: the AppImage is the primary download for this alpha; the .deb remains available for Debian/Ubuntu. Supported distros: see docs/QA.md. SHA256SUMS is attached — verify with sha256sum -c SHA256SUMS.
Agent integration: forktty mcp setup registers the new stdio MCP server for Codex, Claude Code, Gemini CLI, and Antigravity. forktty hooks setup claude now installs the lifecycle hook profile by default — pass --full to keep the previous per-tool profile.