Skip to content

feat: add fish shell integration#123

Merged
arzafran merged 4 commits into
mainfrom
port/fish-shell-integration
Jul 14, 2026
Merged

feat: add fish shell integration#123
arzafran merged 4 commits into
mainfrom
port/fish-shell-integration

Conversation

@arzafran

Copy link
Copy Markdown
Member

What this does

Programa now supports fish as a login shell, not just bash and zsh. If your default shell is fish, opening a terminal in Programa now reports which tab/pane you're in, kicks off port detection, tracks whether the shell is busy or idle, and stays in sync with the app the same way bash and zsh sessions already do.

Summary

  • Added Resources/shell-integration/fish/config.fish, re-implemented from scratch against our v2 JSON-RPC socket protocol (we removed the old v1 line protocol a while back, so this isn't a straight port of upstream's fish script). It covers TTY reporting, port-scan kicks, shell activity state, a keyboard-protocol/TERM reset on every prompt, and tmux environment sync, matching the same feature set our bash/zsh scripts expose over both the direct unix socket and the remote-relay CLI path.
  • Wired fish detection into Sources/GhosttyTerminalView.swift's shell bootstrap: fish has no ZDOTDIR-style hook, so when the login shell is fish we launch it with --init-command 'source "$PROGRAMA_FISH_INTEGRATION_FILE"' instead, mirroring how zsh gets a ZDOTDIR wrapper and bash gets a PROMPT_COMMAND bootstrap.
  • Added FishShellIntegrationHandoffTests to programaTests/GhosttyConfigTests.swift, mirroring the existing ZshShellIntegrationHandoffTests style: it spawns real fish processes against the bundled script and checks the actual JSON-RPC frames and tmux commands produced. Every test skips cleanly (not a failure) if fish isn't installed on the machine running the tests.
  • Deliberately left out of this pass: cwd/git-branch tracking, PR polling, and the claude/grok CLI wrapper shim that bash/zsh also do — those are separate follow-ups, not part of this feature set.

Test Plan

  • PROGRAMA_SKIP_ZIG_BUILD=1 xcodebuild -scheme programa-unit -only-testing:programaTests/FishShellIntegrationHandoffTests -only-testing:programaTests/ZshShellIntegrationHandoffTests test — 26 tests, 0 failures (6 fish tests skip on this machine since fish isn't installed here; confirmed via command -v fish)
  • Manual test on a machine with fish installed as the login shell

arzafran added 4 commits July 13, 2026 18:19
Adds Resources/shell-integration/fish/config.fish, speaking our v2
JSON-RPC socket protocol (surface.report_tty, surface.ports_kick,
surface.report_shell_state) the same way the bash and zsh integration
scripts already do. Covers TTY reporting, port-scan kicks, shell
activity state, keyboard-protocol/TERM reset on each prompt, and tmux
environment sync, both over the direct unix socket and through the
remote relay CLI. Ends with a guard that chain-loads the user's real
fish config when we haven't already (only relevant for a future
remote-bootstrap path; local launches already ran the user's normal
fish startup before this file loads).
When the user's login shell is fish, launch it with
--init-command 'source $PROGRAMA_FISH_INTEGRATION_FILE' pointing at
the bundled fish/config.fish, matching how zsh gets a ZDOTDIR wrapper
and bash gets a PROMPT_COMMAND bootstrap. Fish has no ZDOTDIR
equivalent, so this overrides the startup command instead (only when
the caller didn't already request an explicit command).
Adds FishShellIntegrationHandoffTests, mirroring the existing
ZshShellIntegrationHandoffTests style: spawns real fish processes
against the bundled config.fish and asserts on the actual v2
JSON-RPC frames and tmux commands it produces (TTY reporting via
socket and relay, ports-kick via relay, tmux env publish, and the
forced keyboard-protocol reset sequence). Every test skips cleanly
via XCTSkip when fish isn't installed on the host instead of failing.
…ration

# Conflicts:
#	Sources/GhosttyTerminalView.swift
@arzafran
arzafran merged commit 17d1b02 into main Jul 14, 2026
4 of 7 checks passed
@arzafran
arzafran deleted the port/fish-shell-integration branch July 20, 2026 15:30
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