A rewrite of the Plan 9 rc shell in Goose for UNIX-like systems and with structured CLI args
README.md

Example initialization file #

rcrc adapts the inspected Fish configuration without changes to installed dotfiles. It defines commands and editor key bindings rather than Fish abbreviations.

Startup #

rc2 reads $home/.rcrc for login shells, as Rakitzis rc does. The -l flag or a leading - in the executable name selects login mode. An explicit -m file runs before the login initialization file. Ordinary non-login interactive shells do not automatically read a startup file. Unlike Plan 9 rc, rc2 does not read $home/lib/profile.

Run the example without installation:

./rc2 -m examples/rcrc

After you review the example, you can save your copy as ~/.rcrc. If that file already exists, merge the required sections instead of replacing it.

rc2 -m "$HOME/.rcrc"

For a login shell, run rc2 -l to read the file automatically.

Commands #

Command Action
c [directory] Select a directory with fzf and change to it. The default root is the current directory.
fe Select a file below the current directory and open it with $EDITOR.
fh [query ...] Search persistent history with fzf. Print the selected line without execution.
lfcd [arguments ...] Run lf and change to its last directory.
bm [bookmark] Change to a bookmark directory. Forward management commands to the external bm tool.
t Create a temporary directory and change to it.
paths directory Prepend an existing directory to both $path and $PATH, without duplicates.
r, n, ne Open repository or notes directories. Adjust these paths for your machine.
gp, gu, gc, gs, gb, gd, ga, glog Run the corresponding Git commands with additional arguments.

The example sets Vis, pager options, persistent history, and the user tool paths from the Fish configuration. It also supplies clone shortcuts, optional Kitty and Multipass wrappers, Plan 9 mk, and Janet paths. Unlike Fish universal variables, paths changes only the current session and its children.

The fzf commands require an installed fzf. Other wrappers require their corresponding tools. The example adds no package dependency and executes no optional tool until you call its command. It uses standard host utilities, including find, xargs, printf, tr, awk, and mktemp.

Directory and file selection use NUL-delimited fzf records. Whitespace, quotes, wildcard characters, and embedded newlines remain part of the selected path. The helpers ignore inherited FZF_DEFAULT_OPTS and FZF_DEFAULT_OPTS_FILE to keep their output protocol predictable. They apply their own layout options. Adjust _rc2_pick to change that layout. If you cancel a picker, it does not change the directory or open a file.

Editor bindings #

Key Action
Ctrl-R Replace the input with a history selection. Enter runs the selected command.
Ctrl-T Insert a quoted file or directory selection at the cursor.
Alt-C Select a directory and change to it. Preserve the input and cursor.
Ctrl-O Run lf and change to its last directory. List the new directory. Preserve the input and cursor.

The editor restores normal terminal mode before each hook. Cancellation preserves the input and cursor. These bindings require the corresponding external tools. rc2_key_bindings mirrors the setup in fish_user_key_bindings. It registers the fzf keys only when fzf exists. Ctrl-O does not require fzf. To restore these bindings after a custom change, run rc2_key_bindings.

Differences from Fish #

  • Ctrl-L clears the screen and preserves the current input and cursor. It does not clear terminal scrollback.
  • fh searches history by line, not by complete multiline command. It never evaluates the selected text.
  • fe opens an editor. Ctrl-T inserts the selected path into the input.
  • Ctrl-T selects one path at a time. It inserts at the cursor rather than replaces the current token.
  • Git shortcuts are functions. They do not expand into editable command text as Fish abbreviations do.
  • The example does not translate Fish environment files, universal variables, direnv hooks, or Fish completion scripts.
  • Use direnv exec . command for an explicit per-command environment.