fish-mode

Fish shell for ! commands in Oh My Pi — /fish on/off toggle with autocomplete

Packages

Package details

extension

Install fish-mode from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:fish-mode
Package
fish-mode
Version
1.0.0
Published
Aug 15, 2026
Downloads
180/mo · 7/wk
Author
weinguyen
License
MIT
Types
extension
Size
11.7 KB
Dependencies
0 dependencies · 2 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

fish-mode

Route ! commands through fish shell inside Oh My Pi. Same aliases, abbreviations, functions, and completions you use in your terminal — now inside Pi.

For daily fish users. If you have personal aliases (gstgit status, gcogit checkout), abbreviations (gs expands to git status), or custom functions, and every ! command in Pi forces you back to bash — fish-mode fixes exactly that.

pi install npm:fish-mode

Demo

/fish on
  ┌─ Fish mode ON ─────────────────────────────┐
  │ ! commands run through fish                │
  └────────────────────────────────────────────┘

!git push --force-wi<Tab>
  --force-with-lease    --force-with-lease=<refname>

!gst
  On branch main
  nothing to commit, working tree clean

!echo $fish_pid
  12345

Usage

Toggle

Command Effect
/fish on Route ! commands through fish
/fish off Back to bash (default)

State is saved to .pi/fish-mode/config.json in the project directory. Survives Pi restarts.

Running commands

Type ! followed by your command as usual. When fish mode is active, everything after ! goes straight to fish -c.

!ls -la
!git log --oneline -10
!docker ps
!python3 script.py

Autocomplete

When typing on a line starting with !, press Tab to get fish-native completions. Supports:

  • Files & directories!ls <Tab> shows file list
  • Git!git che<Tab>checkout, cherry-pick
  • Docker!docker cont<Tab>container
  • Any completion fish knows — including from plugins like fisher, oh-my-fish

Completions fall back to Pi's default provider when the line doesn't start with ! or fish mode is off.


How it works

Command routing

fish-mode listens to user_bash events. Every time you type a command in Pi:

  1. Check if fish mode is active
  2. Check if the command starts with !
  3. If yes → strip !, run the rest through fish -c
  4. Return stdout + stderr to Pi for display

Debounce

user_bash fires on every keystroke, not just on Enter. Typing !fastfetch fires 10 times: !f, !fa, !fas, ... Without debounce, each keystroke would execute a command.

fish-mode uses counter-based debounce (150ms): each event increments a counter, waits 150ms, and skips if the counter changed (meaning you're still typing). Only the final command — when you stop typing for 150ms — gets executed.

Autocomplete provider

On session start (session_start), fish-mode registers an autocomplete provider wrapping the default one:

  1. Line starts with ! and fish mode is active → calls fish -c "complete -C '<line>'" for fish-native completions
  2. Otherwise → falls back to Pi's default provider

The provider is registered only once per session to avoid leaks on session restart.

State persistence

Uses atomic write (write .tmp file then rename) to prevent config corruption on mid-write crash.


Requirements

  • fish shell ≥ 3.0 (apt install fish, brew install fish, pacman -S fish, ...)
  • Oh My Pi

If fish is not installed, the extension still loads but stays inactive. /fish on will show an error notification.


FAQ

Does this change Pi's default shell? No. Only ! commands are affected. Everything else uses bash as normal.

Do fish aliases work? Yes. fish -c loads your full fish config: ~/.config/fish/config.fish, aliases, abbreviations, functions — everything.

Do fish abbreviations work? Yes, but only when you press Space or Enter after the abbreviation — same as in a real fish terminal.

Does state survive restarts? Yes. State is saved to disk and persists across Pi restarts.

Is it slow? Negligibly. The user_bash handler only spawns a subprocess when fish mode is active and the command starts with !. Autocomplete calls fish but has a 500ms timeout.

Does it work with fish plugins (fisher, oh-my-fish, tide, ...)? Yes. fish -c loads your entire fish config, including all installed plugins.

Are multi-line commands supported? No. Single-line ! commands only.

How do I uninstall? /fish off to disable. To fully remove: delete the symlink from the extensions folder and remove .pi/fish-mode/config.json.


License

MIT