Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions shell-plugin/fish/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# ForgeCode Fish Shell Plugin

A fish shell port of the ForgeCode ZSH plugin, providing the same `:` command interface for interacting with Forge directly from your shell prompt.

## Installation

### Option 1: Symlink (recommended for development)

```fish
ln -s (pwd)/forge.fish ~/.config/fish/conf.d/forge.fish
ln -s (pwd)/fish_right_prompt.fish ~/.config/fish/functions/fish_right_prompt.fish
```

### Option 2: Copy

```fish
cp forge.fish ~/.config/fish/conf.d/forge.fish
cp fish_right_prompt.fish ~/.config/fish/functions/fish_right_prompt.fish
```

Then reload fish or open a new terminal.

## Usage

Type `:` followed by a space and your prompt to send it to Forge:

```
: explain the auth flow in this codebase
```

### Commands

| Command | Alias | Description |
|---------|-------|-------------|
| `:new` | `:n` | Start a new conversation |
| `:info` | `:i` | Show session info |
| `:env` | `:e` | Show environment info |
| `:agent` | `:a` | Select/switch agent |
| `:conversation` | `:c` | List/switch conversations |
| `:conversation -` | | Toggle to previous conversation |
| `:provider` | `:p` | Select AI provider |
| `:model` | `:m` | Select model |
| `:commit` | | AI-generated commit |
| `:commit-preview` | | Preview AI commit message |
| `:suggest` | `:s` | Generate shell command from description |
| `:edit` | `:ed` | Open editor for multi-line input |
| `:tools` | `:t` | List available tools |
| `:config` | | Show current config |
| `:clone` | | Clone a conversation |
| `:copy` | | Copy last message to clipboard |
| `:dump` | `:d` | Dump conversation (supports `html`) |
| `:compact` | | Compact conversation context |
| `:retry` | `:r` | Retry last message |
| `:sync` | | Sync workspace for code search |
| `:login` | | Login to provider |
| `:logout` | | Logout from provider |
| `:doctor` | | Run environment diagnostics |
| `:kb` | | Show keyboard shortcuts |
| `:ask` | | Alias for sage agent |
| `:plan` | | Alias for muse agent |

### Tab Completion

- Type `:` then press Tab to fuzzy-search available commands via fzf
- Type `@` then press Tab to fuzzy-search files via fd + fzf

## Dependencies

- [forge](https://forgecode.dev) — the ForgeCode CLI
- [fzf](https://github.com/junegunn/fzf) — fuzzy finder (required for interactive selection)
- [fd](https://github.com/sharkdp/fd) — file finder (for `@` file completion)
- [bat](https://github.com/sharkdp/bat) — syntax highlighting in previews (optional)

## Files

- `forge.fish` — Main plugin (conf.d auto-loaded). Contains all functions, keybindings, and dispatcher.
- `fish_right_prompt.fish` — Right prompt showing active model/agent info.
- `README.md` — This file.

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `FORGE_BIN` | `forge` | Path to forge binary |
| `FORGE_MAX_COMMIT_DIFF` | `100000` | Max diff size for AI commits |
| `FORGE_EDITOR` | `$EDITOR` or `nano` | Editor for `:edit` command |
| `FORGE_SYNC_ENABLED` | `true` | Enable background workspace sync |

## Differences from ZSH Plugin

- No ZLE widget system — uses fish `bind` and `commandline` builtins
- Right prompt via `fish_right_prompt` function instead of `RPROMPT`
- Fish auto-loads from `conf.d/` and `functions/` — no manual sourcing needed
- Uses fish syntax throughout (`set`, `test`, `string match`, etc.)
98 changes: 98 additions & 0 deletions shell-plugin/fish/fish_right_prompt.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# ForgeCode Fish Right Prompt Theme
# Displays forge session info (model, agent, conversation stats)
# Converts forge's zsh-formatted rprompt output to fish-compatible ANSI
#
# If a fish_right_prompt already existed before this file was sourced,
# it is saved as _forge_original_fish_right_prompt and appended after
# the forge info.

# Save any existing right prompt before we overwrite it.
# This runs once at source time; subsequent sources are a no-op because
# the function will already be our version (not the original).
if functions -q fish_right_prompt; and not functions -q _forge_original_fish_right_prompt
# Only save if the current fish_right_prompt is NOT ours
# (i.e., it doesn't contain "_FORGE_BIN" in its body)
set -l body (functions fish_right_prompt)
if not string match -q '*_FORGE_BIN*' -- "$body"
functions -c fish_right_prompt _forge_original_fish_right_prompt
end
end

function fish_right_prompt --description "Right prompt with ForgeCode session info"
# Preserve the last command's exit status so callers/other prompt
# segments can inspect it.
set -l last_status $status

# Resolve forge binary path
set -l forge_bin
if test -n "$_FORGE_BIN"
set forge_bin "$_FORGE_BIN"
else if test -n "$FORGE_BIN"
set forge_bin "$FORGE_BIN"
else
set forge_bin "$HOME/.local/bin/forge"
end

if test -x "$forge_bin"
set -l forge_info (
env \
_FORGE_CONVERSATION_ID="$_FORGE_CONVERSATION_ID" \
_FORGE_ACTIVE_AGENT="$_FORGE_ACTIVE_AGENT" \
$forge_bin zsh rprompt 2>/dev/null \
| string collect
)

if test -n "$forge_info"
# Convert zsh prompt escapes to fish/ANSI sequences.
set -l out "$forge_info"

# Strip zsh bold markers (fish uses set_color --bold instead)
set out (string replace -a '%B' '' -- "$out")
set out (string replace -a '%b' '' -- "$out")

# ── Numeric 256-color: %F{NNN} ──────────────────────────
set out (string replace -a '%F{240}' (set_color 888888) -- "$out")
set out (string replace -a '%F{245}' (set_color 8a8a8a) -- "$out")
set out (string replace -a '%F{250}' (set_color bcbcbc) -- "$out")
set out (string replace -a '%F{255}' (set_color eeeeee) -- "$out")
set out (string replace -a '%F{196}' (set_color red) -- "$out")
set out (string replace -a '%F{208}' (set_color ff8700) -- "$out")
set out (string replace -a '%F{226}' (set_color yellow) -- "$out")
set out (string replace -a '%F{46}' (set_color green) -- "$out")
set out (string replace -a '%F{33}' (set_color blue) -- "$out")
set out (string replace -a '%F{51}' (set_color cyan) -- "$out")
set out (string replace -a '%F{201}' (set_color magenta) -- "$out")

# Fallback: any remaining %F{NNN} with numeric code
set out (string replace -ra '%F\{[0-9]+\}' (set_color 888888) -- "$out")

# ── Named colors: %F{name} ──────────────────────────────
set out (string replace -a '%F{red}' (set_color red) -- "$out")
set out (string replace -a '%F{green}' (set_color green) -- "$out")
set out (string replace -a '%F{blue}' (set_color blue) -- "$out")
set out (string replace -a '%F{yellow}' (set_color yellow) -- "$out")
set out (string replace -a '%F{cyan}' (set_color cyan) -- "$out")
set out (string replace -a '%F{magenta}' (set_color magenta) -- "$out")
set out (string replace -a '%F{white}' (set_color white) -- "$out")
set out (string replace -a '%F{black}' (set_color black) -- "$out")

# Fallback: any remaining %F{name}
set out (string replace -ra '%F\{[a-z_]+\}' (set_color normal) -- "$out")

# Reset foreground
set out (string replace -a '%f' (set_color normal) -- "$out")

printf '%s' "$out"
end
end

# Append the original right prompt if one was saved
if functions -q _forge_original_fish_right_prompt
set -l original (_forge_original_fish_right_prompt)
if test -n "$original"
printf ' %s' "$original"
end
end

return $last_status
end
Loading
Loading