versenilvis/IRIS

A shell auto-completion tool for your terminal

Go

1,303

254 commits

updated Oct 9, 2026

See the code

README

logo

macOS Linux
versenilvis%2FIRIS | Trendshift

Status License: 0BSD Documentation PRs Welcome

Comparison · Install · Shortcuts · Configuration · Reporting bugs

IRIS (Intelligent Real-time Input Suggestion) - A shell auto-completion tool that works like code editor's IntelliSense

Ghostty terminal showcase 👻 Ghostty terminal

IRIS is built on top of TTY, so it runs everywhere. It just needs a terminal!

Run iris wherever you already work; your local machine, a remote server, or anywhere you can ssh. Each suggestion menu renders directly inline inside your real terminal session, not an app's imitation of one, so it never breaks full-screen TUIs or terminal formatting. Automatically index your aliases and shell history to suggest commands that match your actual workflow in real time. Change configurations and propagate them instantly without restarting your shell. One single local native Go binary, not an app: no gui, no electron, no mac-only wrapper, no account, no telemetry. (if you've used fig: it's that, rebuilt to run purely on TTY)

AI suggestions

output IRIS has AI suggestions like your code editor (API key/Local)

Why IRIS instead of Fig

[!IMPORTANT] Fig was officially sunset in September 2024 and migrated to Amazon Q Developer (which requires cloud authentication and proprietary bloat) IRIS is the lightweight, open-source, zero-telemetry alternative built purely on native Go and TTY with no accounts, no GUI app, and no background daemons required

How it compares

FeatureIRISFig
PlatformsLinux, macOSmacOS only
EngineNative Go (TTY)Electron
StartupNear-zero overheadLow overhead
UIInline overlayGUI popover
Remote SSHTTY-native, portablemacOS GUI-bound
Tmux✓Limited
Linux virtual terminals✓-
MemoryLightweightElectron runtime

Why not shell autocomplete plugins?

Shell plugins are great, but they also come with trade-offs. And also, not everyone use Zsh or Fish especially on SSH.

FeatureIRISShell plugins
InstallationSingle binaryPlugin manager required
Shell supportMost shells supportedUsually shell-specific
StartupNo shell initializationIncreases shell startup time
SSHOne configPer-shell config
Tmux✓Depends on the shell
Linux virtual terminals✓Depends on the shell

Install

Dependencies

  • OS: Linux or macOS
  • Terminal emulator with ANSI color support
  • Go 1.24 or newer (if building from source)

[!WARNING] Currently, Windows is not supported

Method 1: Package managers

Arch Linux (AUR)

IRIS is available on the Arch User Repository. You can install it using your favorite AUR helper:

yay -S iris-autocomplete

OR

paru -S iris-autocomplete
macOS / Linux (Homebrew)

Install IRIS via Homebrew tap:

brew install versenilvis/iris/iris
Nix Flakes

If you are using Nix Flakes, you can consume this module directly without building it manually.

  1. In your flake.nix inputs, add:

    iris.url = "github:versenilvis/iris/main";
    
  2. Then, use one of the following options to add IRIS to your system:

    Option A: Try without installing (ephemeral)

    nix run github:versenilvis/iris
    

    Option B: Install to your user profile

    nix profile add github:versenilvis/iris
    

    Option C: Using Home Manager (Ensure you pass inputs to modules via extraSpecialArgs)

    home.packages = [ inputs.iris.packages.${pkgs.system}.default ];
    

    Option D: Without Home Manager (NixOS System) (Ensure you pass inputs to modules via specialArgs)

    environment.systemPackages = [ inputs.iris.packages.${pkgs.system}.default ];
    
Debian / Ubuntu (.deb)
curl -sLO https://github.com/versenilvis/iris/releases/latest/download/iris_linux_amd64.deb
sudo dpkg -i iris_linux_amd64.deb
rm iris_linux_amd64.deb

(For ARM64 architecture, replace amd64 with arm64)

Fedora / RHEL (.rpm)
curl -sLO https://github.com/versenilvis/iris/releases/latest/download/iris_linux_amd64.rpm
sudo rpm -i iris_linux_amd64.rpm
rm iris_linux_amd64.rpm

(For ARM64 architecture, replace amd64 with arm64)

Aqua

If you use aqua, you can install IRIS by adding it to your aqua.yaml:

packages:
  - name: versenilvis/iris

Then run aqua i.

asdf

If you use asdf, you can install IRIS via its plugin:

asdf plugin add iris https://github.com/versenilvis/asdf-iris.git
asdf install iris latest
asdf set -u iris latest
asdf current iris
curl -sSL https://raw.githubusercontent.com/versenilvis/iris/main/scripts/install.sh | sh

Method 3: Go install

go install github.com/versenilvis/iris/cmd/iris@latest

Method 4: Build from source (for developers)

git clone https://github.com/versenilvis/iris.git
cd iris
just reload

Update

iris update

Checks for and installs the latest release. To see what's changed first:

iris changelog       # latest release
iris changelog -n 3  # last 3 releases

IRIS can also check for and install updates on its own - see updater.auto-update in the configuration guide below.

Uninstall

To completely uninstall IRIS, remove all configurations, and clean up your shell integration files, simply run:

iris uninstall

Shell setup

[!WARNING] IRIS may cause visual conflicts and keybinding overlaps with other shell autosuggestion plugins or third-party completion tools. To prevent this, please disable them safely (e.g., zsh-autosuggestions, zsh-autocomplete, atuin, flyline, ...)

[!NOTE] This is already added from installation script, but if your shell config is missing it, please add manually

To automatically start IRIS every time you open a new shell session, add the init command to your shell config:

Zsh (~/.zshrc):

eval "$(iris init zsh)"

Bash (~/.bashrc):

eval "$(iris init bash)"

Fish (~/.config/fish/config.fish):

iris init fish | source

Configuration guide

IRIS uses a clean TOML configuration file located at ~/.config/iris/config.toml

Creating & viewing config

iris config init
iris config show

Custom config location

config.toml and theme.toml are read from $XDG_CONFIG_HOME/iris, falling back to ~/.config/iris. Point IRIS elsewhere with the --config-dir flag or the IRIS_CONFIG_DIR environment variable:

iris --config-dir ~/iris-profiles/work
IRIS_CONFIG_DIR=~/iris-profiles/work iris

The flag wins over the variable, and both win over XDG_CONFIG_HOME. iris config init, iris theme init and iris setup write into the chosen directory.

[!IMPORTANT] Use the environment variable for a whole session. Your shell rc starts IRIS with a bare exec iris, which drops any flags you typed earlier, while the environment survives. It is also what NixOS and other declarative setups should set.

The directory must exist, since a path that points nowhere is almost always a typo. The files inside are optional: an empty directory plus iris config init is the normal way to start a new profile.

State and history (~/.local/share/iris) are not affected, so profiles share the remembered mode and frecency ranking.

Sample config.toml

[core]
version = 1                    # config schema version
shell = ""                     # "zsh", "bash", "fish", or empty for auto-detect
shell-login = false            # run shell as a login shell (also: iris --shell-login)
mode = "last"                  # "last", "spec", or "history"
debug = false                  # verbose logging to iris.log (also: iris -d)
expand-alias = true            # expand aliases before matching
auto-execute = false           # run suggestion immediately instead of inserting it
atuin-history = 0              # 0 = shell history, 1 = atuin, 2 = both
atuin-db-path = ""             # path to atuin's history.db, empty = use default
cobra-probe-enabled = true     # fall back to probing cobra binaries for completions
navigate-closed = "history"    # menu closed: "history" browses iris history, "shell" hands the key to the shell (atuin)

[ui]
style = "modern"       # "modern" or "classic"
ghost-text = 1         # 0 = off, 1 = menu + ghost text, 2 = ghost text only
hidden-files = false   # include dotfiles in suggestions
max-suggestions = 100  # max suggestions ranked before display
max-height = 6         # max visible rows in the menu
max-width = 0          # menu width: columns (80) or a share ("80%"), 0 = default
nerd-fonts = true      # use nerd-font icons

[keybindings]
toggle-mode = "ctrl+r"     # switch spec/history mode
toggle-menu = "shift+tab"  # show or hide the suggestion menu
select = "tab"             # accept the selected suggestion
navigate-up = "up"         # select up, or open history if empty
navigate-down = "down"     # select down, or open history if empty
navigate-right = "right"   # accept ghost text

[git]
filter-active-branch = true  # exclude current branch from suggestions
deduplicate-branches = true  # merge same-name local/remote branches

[updater]
check-on-startup = true  # check for updates on startup
channel = "stable"       # "stable" or "nightly"
check-interval = "24h"   # min time between update checks
auto-update = 0          # 0 = off, 1 = auto-install, 2 = confirm first

[zoxide]
extend-cd = false  # complete `cd` from zoxide's database, not just the current directory

[ai]
enabled = false
provider = "groq"  # "groq" or "ollama"
debounce_ms = 400  # ms to wait before querying the AI

# please use free subscription, that is enough for your daily usage
[ai.providers.groq]
endpoint = "https://api.groq.com/openai/v1/chat/completions"
api_key_env = "GROQ_API_KEY"       # or set api_key directly
model = "llama-3.3-70b-versatile"
timeout_ms = 3000                  # ms before giving up

[ai.providers.ollama]
endpoint = "http://localhost:11434/v1/chat/completions"
model = "qwen2.5-coder"
timeout_ms = 5000  # ms before giving up

[!NOTE] Using api_key_env is recommended over hardcoding api_key in plain text to keep credentials out of configuration files.

[!NOTE] ghost-text used to be a boolean. Existing configs keep working: true is read as 1 and false as 0, so there is nothing to change on upgrade.

Default shortcuts

ShortcutActionDescription
Shift + TabToggle menuShow or hide the suggestion menu.
EscHide menuTemporarily hide the menu until the next key press.
TabAccept suggestionInsert the currently selected suggestion into the prompt.
EnterExecute commandClose the menu and send the current command to the shell.
↑Navigate up / historyMove the selection up, or open command history when the prompt is empty.
↓Navigate down / historyMove the selection down, or open command history when the prompt is empty.
→Accept ghost textAccept the faded ghost text suggestion when the menu is open.
← / →Move cursorMove the cursor inside the input buffer. Disabled when the prompt is empty
Ctrl + RSwitch modeToggle between spec and history mode.
Ctrl + ABeginning of lineMove the cursor to the start of the command line.
Ctrl + EEnd of lineMove the cursor to the end of the command line.
Ctrl + LClear screenClear the terminal while preserving the input buffer and redrawing the menu.
Ctrl + UClear commandRemove the entire current command and close the menu.
Ctrl + CCancel commandSend SIGINT, clear the input buffer, and close the menu.
Ctrl + WDelete wordDelete the word immediately before the cursor.

[!NOTE] With Ctrl + A, Ctrl + E, Ctrl + W, Ctrl + U, Ctrl + L, and Ctrl + C: they belong to your shell by default. IRIS handles them directly in raw mode so your cursor and menu stay in sync

Theme

Kitty terminal showcase 😺 Kitty terminal

[!TIP] We keep all available theme templates in the themes/ directory Feel free to create your own theme or contribute a new color scheme by adding it to this directory

IRIS has theme TOML configuration file located at ~/.config/iris/theme.toml

Creating theme config

iris theme init

theme.toml lives beside config.toml, so --config-dir and IRIS_CONFIG_DIR relocate it too.

Default theme

IRIS automatically falls back to the default theme if theme.toml is missing, empty, or contains missing configuration options

border = "#a277ff"
accent = "#61ffca"
muted = "#6d6a7f"
text = "#edecee"
text_sel = "#ffffff"
key = "#a277ff"
match = "#61ffca"
desc = "#9692a8"
desc_sel = "#edecee"
sel_bg = "#3d375e"
sel_text = "#110f18"
scroll_info = "#a277ff"
ghost_text = "#4B4A4C"
sys = "#1e1d28"
sys_sel = "#a277ff"
hist = "#1a2d36"
hist_sel = "#61ffca"
alias = "#2a2342"
alias_sel = "#a277ff"

[!NOTE] IRIS also has 2 basic styles

Modern styleClassic style
specspec
historyhistory

Custom completion specs

Adds support for user-defined shell completion specs via two new CLI commands:

  • iris spec init [name]: scaffolds a .jsonc spec file in the user's specs directory with a ready-to-edit template
  • iris spec path: prints (and creates) the specs directory so users can open it directly

Spec files are picked up automatically on startup and merged with built-in specs, so custom completions work without any extra config.

Commands example

# create a new spec for "mycli"
iris spec init mycli
# → initialized spec file at ~/.config/iris/specs/mycli.jsonc

# open the specs folder
cd $(iris spec path)

Spec format example (JSONC)

{
  // $schema enables autocomplete and validation in VS Code / Zed
  "$schema": "https://raw.githubusercontent.com/versenilvis/iris/main/spec/schema.json",

  // command name must match the binary on PATH
  "name": "mycli",

  // optional short aliases for the same binary (e.g. "mc" → "mycli")
  "aliases": ["mc"],

  "description": "Demo custom completion spec",

  // top-level flags shared by all subcommands
  "options": [
    {
      "name": "--verbose",
      "aliases": ["-v"],
      "description": "Enable verbose output"
    },
    {
      "name": "--config",
      "aliases": ["-c"],
      "description": "Path to config file"
    }
  ],

  "subcommands": [
    {
      "name": "run",
      "description": "Run a script or entry file",
      // generator: suggest files by extension (array) or "file" / "dir" keywords
      "generator": [".go", ".js", ".ts", ".py"]
    },
    {
      "name": "service",
      "description": "Manage background services",
      // nested subcommands are supported at any depth
      "subcommands": [
        {
          "name": "start",
          "description": "Start the service daemon",
          "options": [
            { "name": "--daemon", "aliases": ["-d"], "description": "Run in background" }
          ]
        },
        { "name": "stop", "description": "Stop the running service" },
        { "name": "restart", "description": "Restart the service" }
      ]
    },
    {
      "name": "deploy",
      "description": "Deploy to an environment",
      "options": [
        { "name": "--dry-run", "description": "Simulate without making changes" },
        { "name": "--env", "aliases": ["-e"], "description": "Target environment" }
      ]
    }
  ]
}

[!NOTE]

  • $schema enables autocomplete and inline validation in VS Code, Zed, and any LSP-aware editor, no plugin needed
  • JSONC is fully supported: // line comments, /* */ block comments, and trailing commas are all stripped before parsing
  • Multiple commands per file are supported, use an array [{...}, {...}] or a {"specs": [...]} wrapper, each file is independent, so you can split specs however you like:
specs/
 ab.jsonc   ← defines commands "a" and "b"
 c.jsonc    ← defines command "c" only

All three commands are registered and work normally!

Reporting bugs

[!NOTE] When submitting a bug report, please include:

  • A detailed description of the bug and steps to reproduce it
  • Relevant log files captured while running in debug mode

Run IRIS with debug mode:

iris -d

or config.toml:

debug=true

[!IMPORTANT] Since IRIS logs everything you type, you should only enable debug mode when you need to report bugs

If IRIS crashes, it will automatically save a crash log and show the path on your terminal (~/.iris/crash.log). Or you can find the path to the latest crash log by running:

iris crash-log

Please include this file when reporting a crash.

Developer documentation

For system architecture overview, engine design, and contribution guide, please refer to the Developer documentation.

License

This project is licensed under the 0BSD License - no strings attached. Meaning you can do whatever you want with it.

For those who fork it and want to publish a new version or something else; if you can, a credit or co-author mention is always welcome :) (though never required).

Thank you!

Feedback

I'd love to hear your feedback

Feel free to reach out via:

versenilvis/IRIS

A shell auto-completion tool for your terminal

Go

1,303

254 commits

updated Oct 9, 2026

See the code

README

logo

macOS Linux
versenilvis%2FIRIS | Trendshift

Status License: 0BSD Documentation PRs Welcome

Comparison · Install · Shortcuts · Configuration · Reporting bugs

IRIS (Intelligent Real-time Input Suggestion) - A shell auto-completion tool that works like code editor's IntelliSense

Ghostty terminal showcase 👻 Ghostty terminal

IRIS is built on top of TTY, so it runs everywhere. It just needs a terminal!

Run iris wherever you already work; your local machine, a remote server, or anywhere you can ssh. Each suggestion menu renders directly inline inside your real terminal session, not an app's imitation of one, so it never breaks full-screen TUIs or terminal formatting. Automatically index your aliases and shell history to suggest commands that match your actual workflow in real time. Change configurations and propagate them instantly without restarting your shell. One single local native Go binary, not an app: no gui, no electron, no mac-only wrapper, no account, no telemetry. (if you've used fig: it's that, rebuilt to run purely on TTY)

AI suggestions

output IRIS has AI suggestions like your code editor (API key/Local)

Why IRIS instead of Fig

[!IMPORTANT] Fig was officially sunset in September 2024 and migrated to Amazon Q Developer (which requires cloud authentication and proprietary bloat) IRIS is the lightweight, open-source, zero-telemetry alternative built purely on native Go and TTY with no accounts, no GUI app, and no background daemons required

How it compares

FeatureIRISFig
PlatformsLinux, macOSmacOS only
EngineNative Go (TTY)Electron
StartupNear-zero overheadLow overhead
UIInline overlayGUI popover
Remote SSHTTY-native, portablemacOS GUI-bound
Tmux✓Limited
Linux virtual terminals✓-
MemoryLightweightElectron runtime

Why not shell autocomplete plugins?

Shell plugins are great, but they also come with trade-offs. And also, not everyone use Zsh or Fish especially on SSH.

FeatureIRISShell plugins
InstallationSingle binaryPlugin manager required
Shell supportMost shells supportedUsually shell-specific
StartupNo shell initializationIncreases shell startup time
SSHOne configPer-shell config
Tmux✓Depends on the shell
Linux virtual terminals✓Depends on the shell

Install

Dependencies

  • OS: Linux or macOS
  • Terminal emulator with ANSI color support
  • Go 1.24 or newer (if building from source)

[!WARNING] Currently, Windows is not supported

Method 1: Package managers

Arch Linux (AUR)

IRIS is available on the Arch User Repository. You can install it using your favorite AUR helper:

yay -S iris-autocomplete

OR

paru -S iris-autocomplete
macOS / Linux (Homebrew)

Install IRIS via Homebrew tap:

brew install versenilvis/iris/iris
Nix Flakes

If you are using Nix Flakes, you can consume this module directly without building it manually.

  1. In your flake.nix inputs, add:

    iris.url = "github:versenilvis/iris/main";
    
  2. Then, use one of the following options to add IRIS to your system:

    Option A: Try without installing (ephemeral)

    nix run github:versenilvis/iris
    

    Option B: Install to your user profile

    nix profile add github:versenilvis/iris
    

    Option C: Using Home Manager (Ensure you pass inputs to modules via extraSpecialArgs)

    home.packages = [ inputs.iris.packages.${pkgs.system}.default ];
    

    Option D: Without Home Manager (NixOS System) (Ensure you pass inputs to modules via specialArgs)

    environment.systemPackages = [ inputs.iris.packages.${pkgs.system}.default ];
    
Debian / Ubuntu (.deb)
curl -sLO https://github.com/versenilvis/iris/releases/latest/download/iris_linux_amd64.deb
sudo dpkg -i iris_linux_amd64.deb
rm iris_linux_amd64.deb

(For ARM64 architecture, replace amd64 with arm64)

Fedora / RHEL (.rpm)
curl -sLO https://github.com/versenilvis/iris/releases/latest/download/iris_linux_amd64.rpm
sudo rpm -i iris_linux_amd64.rpm
rm iris_linux_amd64.rpm

(For ARM64 architecture, replace amd64 with arm64)

Aqua

If you use aqua, you can install IRIS by adding it to your aqua.yaml:

packages:
  - name: versenilvis/iris

Then run aqua i.

asdf

If you use asdf, you can install IRIS via its plugin:

asdf plugin add iris https://github.com/versenilvis/asdf-iris.git
asdf install iris latest
asdf set -u iris latest
asdf current iris
curl -sSL https://raw.githubusercontent.com/versenilvis/iris/main/scripts/install.sh | sh

Method 3: Go install

go install github.com/versenilvis/iris/cmd/iris@latest

Method 4: Build from source (for developers)

git clone https://github.com/versenilvis/iris.git
cd iris
just reload

Update

iris update

Checks for and installs the latest release. To see what's changed first:

iris changelog       # latest release
iris changelog -n 3  # last 3 releases

IRIS can also check for and install updates on its own - see updater.auto-update in the configuration guide below.

Uninstall

To completely uninstall IRIS, remove all configurations, and clean up your shell integration files, simply run:

iris uninstall

Shell setup

[!WARNING] IRIS may cause visual conflicts and keybinding overlaps with other shell autosuggestion plugins or third-party completion tools. To prevent this, please disable them safely (e.g., zsh-autosuggestions, zsh-autocomplete, atuin, flyline, ...)

[!NOTE] This is already added from installation script, but if your shell config is missing it, please add manually

To automatically start IRIS every time you open a new shell session, add the init command to your shell config:

Zsh (~/.zshrc):

eval "$(iris init zsh)"

Bash (~/.bashrc):

eval "$(iris init bash)"

Fish (~/.config/fish/config.fish):

iris init fish | source

Configuration guide

IRIS uses a clean TOML configuration file located at ~/.config/iris/config.toml

Creating & viewing config

iris config init
iris config show

Custom config location

config.toml and theme.toml are read from $XDG_CONFIG_HOME/iris, falling back to ~/.config/iris. Point IRIS elsewhere with the --config-dir flag or the IRIS_CONFIG_DIR environment variable:

iris --config-dir ~/iris-profiles/work
IRIS_CONFIG_DIR=~/iris-profiles/work iris

The flag wins over the variable, and both win over XDG_CONFIG_HOME. iris config init, iris theme init and iris setup write into the chosen directory.

[!IMPORTANT] Use the environment variable for a whole session. Your shell rc starts IRIS with a bare exec iris, which drops any flags you typed earlier, while the environment survives. It is also what NixOS and other declarative setups should set.

The directory must exist, since a path that points nowhere is almost always a typo. The files inside are optional: an empty directory plus iris config init is the normal way to start a new profile.

State and history (~/.local/share/iris) are not affected, so profiles share the remembered mode and frecency ranking.

Sample config.toml

[core]
version = 1                    # config schema version
shell = ""                     # "zsh", "bash", "fish", or empty for auto-detect
shell-login = false            # run shell as a login shell (also: iris --shell-login)
mode = "last"                  # "last", "spec", or "history"
debug = false                  # verbose logging to iris.log (also: iris -d)
expand-alias = true            # expand aliases before matching
auto-execute = false           # run suggestion immediately instead of inserting it
atuin-history = 0              # 0 = shell history, 1 = atuin, 2 = both
atuin-db-path = ""             # path to atuin's history.db, empty = use default
cobra-probe-enabled = true     # fall back to probing cobra binaries for completions
navigate-closed = "history"    # menu closed: "history" browses iris history, "shell" hands the key to the shell (atuin)

[ui]
style = "modern"       # "modern" or "classic"
ghost-text = 1         # 0 = off, 1 = menu + ghost text, 2 = ghost text only
hidden-files = false   # include dotfiles in suggestions
max-suggestions = 100  # max suggestions ranked before display
max-height = 6         # max visible rows in the menu
max-width = 0          # menu width: columns (80) or a share ("80%"), 0 = default
nerd-fonts = true      # use nerd-font icons

[keybindings]
toggle-mode = "ctrl+r"     # switch spec/history mode
toggle-menu = "shift+tab"  # show or hide the suggestion menu
select = "tab"             # accept the selected suggestion
navigate-up = "up"         # select up, or open history if empty
navigate-down = "down"     # select down, or open history if empty
navigate-right = "right"   # accept ghost text

[git]
filter-active-branch = true  # exclude current branch from suggestions
deduplicate-branches = true  # merge same-name local/remote branches

[updater]
check-on-startup = true  # check for updates on startup
channel = "stable"       # "stable" or "nightly"
check-interval = "24h"   # min time between update checks
auto-update = 0          # 0 = off, 1 = auto-install, 2 = confirm first

[zoxide]
extend-cd = false  # complete `cd` from zoxide's database, not just the current directory

[ai]
enabled = false
provider = "groq"  # "groq" or "ollama"
debounce_ms = 400  # ms to wait before querying the AI

# please use free subscription, that is enough for your daily usage
[ai.providers.groq]
endpoint = "https://api.groq.com/openai/v1/chat/completions"
api_key_env = "GROQ_API_KEY"       # or set api_key directly
model = "llama-3.3-70b-versatile"
timeout_ms = 3000                  # ms before giving up

[ai.providers.ollama]
endpoint = "http://localhost:11434/v1/chat/completions"
model = "qwen2.5-coder"
timeout_ms = 5000  # ms before giving up

[!NOTE] Using api_key_env is recommended over hardcoding api_key in plain text to keep credentials out of configuration files.

[!NOTE] ghost-text used to be a boolean. Existing configs keep working: true is read as 1 and false as 0, so there is nothing to change on upgrade.

Default shortcuts

ShortcutActionDescription
Shift + TabToggle menuShow or hide the suggestion menu.
EscHide menuTemporarily hide the menu until the next key press.
TabAccept suggestionInsert the currently selected suggestion into the prompt.
EnterExecute commandClose the menu and send the current command to the shell.
↑Navigate up / historyMove the selection up, or open command history when the prompt is empty.
↓Navigate down / historyMove the selection down, or open command history when the prompt is empty.
→Accept ghost textAccept the faded ghost text suggestion when the menu is open.
← / →Move cursorMove the cursor inside the input buffer. Disabled when the prompt is empty
Ctrl + RSwitch modeToggle between spec and history mode.
Ctrl + ABeginning of lineMove the cursor to the start of the command line.
Ctrl + EEnd of lineMove the cursor to the end of the command line.
Ctrl + LClear screenClear the terminal while preserving the input buffer and redrawing the menu.
Ctrl + UClear commandRemove the entire current command and close the menu.
Ctrl + CCancel commandSend SIGINT, clear the input buffer, and close the menu.
Ctrl + WDelete wordDelete the word immediately before the cursor.

[!NOTE] With Ctrl + A, Ctrl + E, Ctrl + W, Ctrl + U, Ctrl + L, and Ctrl + C: they belong to your shell by default. IRIS handles them directly in raw mode so your cursor and menu stay in sync

Theme

Kitty terminal showcase 😺 Kitty terminal

[!TIP] We keep all available theme templates in the themes/ directory Feel free to create your own theme or contribute a new color scheme by adding it to this directory

IRIS has theme TOML configuration file located at ~/.config/iris/theme.toml

Creating theme config

iris theme init

theme.toml lives beside config.toml, so --config-dir and IRIS_CONFIG_DIR relocate it too.

Default theme

IRIS automatically falls back to the default theme if theme.toml is missing, empty, or contains missing configuration options

border = "#a277ff"
accent = "#61ffca"
muted = "#6d6a7f"
text = "#edecee"
text_sel = "#ffffff"
key = "#a277ff"
match = "#61ffca"
desc = "#9692a8"
desc_sel = "#edecee"
sel_bg = "#3d375e"
sel_text = "#110f18"
scroll_info = "#a277ff"
ghost_text = "#4B4A4C"
sys = "#1e1d28"
sys_sel = "#a277ff"
hist = "#1a2d36"
hist_sel = "#61ffca"
alias = "#2a2342"
alias_sel = "#a277ff"

[!NOTE] IRIS also has 2 basic styles

Modern styleClassic style
specspec
historyhistory

Custom completion specs

Adds support for user-defined shell completion specs via two new CLI commands:

  • iris spec init [name]: scaffolds a .jsonc spec file in the user's specs directory with a ready-to-edit template
  • iris spec path: prints (and creates) the specs directory so users can open it directly

Spec files are picked up automatically on startup and merged with built-in specs, so custom completions work without any extra config.

Commands example

# create a new spec for "mycli"
iris spec init mycli
# → initialized spec file at ~/.config/iris/specs/mycli.jsonc

# open the specs folder
cd $(iris spec path)

Spec format example (JSONC)

{
  // $schema enables autocomplete and validation in VS Code / Zed
  "$schema": "https://raw.githubusercontent.com/versenilvis/iris/main/spec/schema.json",

  // command name must match the binary on PATH
  "name": "mycli",

  // optional short aliases for the same binary (e.g. "mc" → "mycli")
  "aliases": ["mc"],

  "description": "Demo custom completion spec",

  // top-level flags shared by all subcommands
  "options": [
    {
      "name": "--verbose",
      "aliases": ["-v"],
      "description": "Enable verbose output"
    },
    {
      "name": "--config",
      "aliases": ["-c"],
      "description": "Path to config file"
    }
  ],

  "subcommands": [
    {
      "name": "run",
      "description": "Run a script or entry file",
      // generator: suggest files by extension (array) or "file" / "dir" keywords
      "generator": [".go", ".js", ".ts", ".py"]
    },
    {
      "name": "service",
      "description": "Manage background services",
      // nested subcommands are supported at any depth
      "subcommands": [
        {
          "name": "start",
          "description": "Start the service daemon",
          "options": [
            { "name": "--daemon", "aliases": ["-d"], "description": "Run in background" }
          ]
        },
        { "name": "stop", "description": "Stop the running service" },
        { "name": "restart", "description": "Restart the service" }
      ]
    },
    {
      "name": "deploy",
      "description": "Deploy to an environment",
      "options": [
        { "name": "--dry-run", "description": "Simulate without making changes" },
        { "name": "--env", "aliases": ["-e"], "description": "Target environment" }
      ]
    }
  ]
}

[!NOTE]

  • $schema enables autocomplete and inline validation in VS Code, Zed, and any LSP-aware editor, no plugin needed
  • JSONC is fully supported: // line comments, /* */ block comments, and trailing commas are all stripped before parsing
  • Multiple commands per file are supported, use an array [{...}, {...}] or a {"specs": [...]} wrapper, each file is independent, so you can split specs however you like:
specs/
 ab.jsonc   ← defines commands "a" and "b"
 c.jsonc    ← defines command "c" only

All three commands are registered and work normally!

Reporting bugs

[!NOTE] When submitting a bug report, please include:

  • A detailed description of the bug and steps to reproduce it
  • Relevant log files captured while running in debug mode

Run IRIS with debug mode:

iris -d

or config.toml:

debug=true

[!IMPORTANT] Since IRIS logs everything you type, you should only enable debug mode when you need to report bugs

If IRIS crashes, it will automatically save a crash log and show the path on your terminal (~/.iris/crash.log). Or you can find the path to the latest crash log by running:

iris crash-log

Please include this file when reporting a crash.

Developer documentation

For system architecture overview, engine design, and contribution guide, please refer to the Developer documentation.

License

This project is licensed under the 0BSD License - no strings attached. Meaning you can do whatever you want with it.

For those who fork it and want to publish a new version or something else; if you can, a credit or co-author mention is always welcome :) (though never required).

Thank you!

Feedback

I'd love to hear your feedback

Feel free to reach out via:

Project health

Latest release

v0.7.3 · Oct 9, 2026

Releases this year

49

Significant stargazers

Chris Grieser

670 followers · starred Jul 2026

luo jiyin

335 followers · starred Jul 2026

Noritaka Kobayashi

94 followers · starred Jul 2026

eitsupi

207 followers · starred Jul 2026