docs: update docs (#43)
- macOS, Linux badge and AI suggestions showcase in README - Update user guide and docs for development
This commit is contained in:
@@ -6,10 +6,16 @@
|
||||
<!-- <h1>IRIS</h1> -->
|
||||
<p>IRIS (Intelligent Real-time Input Suggestion) - A shell auto-completion tool that works like code editor's IntelliSense</p>
|
||||
|
||||
[](https://github.com/versenilvis/IRIS/actions/workflows/release.yml)
|
||||
[](https://www.apple.com/macos/)
|
||||
[](https://www.kernel.org/)
|
||||
<br>
|
||||
<!--[](https://github.com/versenilvis/IRIS/actions/workflows/release.yml)-->
|
||||
[]()
|
||||
[](./LICENSE)
|
||||
[](./docs/README.md)
|
||||
[](./CONTRIBUTING.md)
|
||||
|
||||
<a href="#why-iris-instead-of-fig">Comparison</a> · <a href="#installation">Installation</a> · <a href="#docs">Docs</a> · <a href="#shortcuts">Shortcuts</a> · <a href="#reporting-bugs">Reporting bugs</a>
|
||||
<a href="#why-iris-instead-of-fig">Comparison</a> · <a href="#installation">Installation</a> · <a href="./docs/README.md">Docs</a> · <a href="./docs/README.md#shortcuts">Shortcuts</a> · <a href="./docs/README.md#configuration-guide">Configuration</a> · <a href="./docs/README.md#reporting-bugs">Reporting bugs</a>
|
||||
|
||||
</div>
|
||||
<div align="center">
|
||||
@@ -31,6 +37,11 @@ Run iris wherever you already work; your local machine, a remote server, or anyw
|
||||
[](./.github/CONTRIBUTING.md)
|
||||
-->
|
||||
|
||||
## AI suggestions
|
||||
<div align="center">
|
||||
<img width="1920" height="1080" alt="output" src="https://github.com/user-attachments/assets/ab80fe75-b5dd-4acd-84bb-45bca17ee3b7" />
|
||||
<i>IRIS has AI suggestions like your code editor (API key/Local)</i>
|
||||
</div>
|
||||
|
||||
## Why Iris instead of Fig
|
||||
|
||||
@@ -100,50 +111,10 @@ curl -sSL https://raw.githubusercontent.com/versenilvis/iris/main/scripts/instal
|
||||
## Docs
|
||||
|
||||
- [Getting started](./docs/README.md#getting-started): dependencies, installation methods, and shell integration setup
|
||||
- [Usage guide](./docs/README.md#usage-guide): core navigation, mode switching, instant alias expansion, and ghost text
|
||||
- [Configuration guide](./docs/README.md#configuration-guide): TOML configuration file structure, settings sections, and CLI commands
|
||||
- [Troubleshooting guide](./docs/README.md#troubleshooting-guide): debug mode, runtime log inspection, and common solutions
|
||||
- [Developer guide](./docs/development.md): system architecture overview, PTY bridge mechanics, and contribution instructions
|
||||
|
||||
## Shortcuts
|
||||
|
||||
| Shortcut | Action | Description |
|
||||
| :--------------------------------- | :---------------------- | :------------------------------------------------------------------------ |
|
||||
| <kbd>Shift</kbd> + <kbd>Tab</kbd> | Toggle menu | Show or hide the suggestion menu. |
|
||||
| <kbd>Esc</kbd> | Hide menu | Temporarily hide the menu until the next key press. |
|
||||
| <kbd>Tab</kbd> | Accept suggestion | Insert the currently selected suggestion into the prompt. |
|
||||
| <kbd>Enter</kbd> | Execute command | Close the menu and send the current command to the shell. |
|
||||
| <kbd>↑</kbd> | Navigate up / history | Move the selection up, or open command history when the prompt is empty. |
|
||||
| <kbd>↓</kbd> | Navigate down / history | Move the selection down, or open command history when the prompt is empty. |
|
||||
| <kbd>→</kbd> | Accept ghost text | Accept the faded ghost text suggestion when the menu is open. |
|
||||
| <kbd>←</kbd> / <kbd>→</kbd> | Move cursor | Move the cursor inside the input buffer. Disabled when the prompt is empty. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>R</kbd> | Switch mode | Toggle between `spec` and `history` mode. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>A</kbd> | Beginning of line | Move the cursor to the start of the command line. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>E</kbd> | End of line | Move the cursor to the end of the command line. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>L</kbd> | Clear screen | Clear the terminal while preserving the input buffer and redrawing the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>U</kbd> | Clear command | Remove the entire current command and close the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>C</kbd> | Cancel command | Send `SIGINT`, clear the input buffer, and close the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>W</kbd> | Delete word | Delete the word immediately before the cursor. |
|
||||
|
||||
> [!NOTE]
|
||||
> With <kbd>Ctrl</kbd> + <kbd>A</kbd>, <kbd>Ctrl</kbd> + <kbd>E</kbd>, <kbd>Ctrl</kbd> + <kbd>W</kbd>, <kbd>Ctrl</kbd> + <kbd>U</kbd>, <kbd>Ctrl</kbd> + <kbd>L</kbd>, and <kbd>Ctrl</kbd> + <kbd>C</kbd>: they belong to your shell by default. IRIS handles them directly in raw mode so your cursor and menu stay in sync
|
||||
|
||||
## Reporting bugs
|
||||
> [!NOTE]
|
||||
> Describing the bug you are facing, along with the relevant log
|
||||
> Enabling debug mode and then performing actions that led to the error
|
||||
|
||||
Run IRIS with debug mode:
|
||||
```bash
|
||||
iris -d
|
||||
```
|
||||
or `config.toml`:
|
||||
```toml
|
||||
debug=true
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Since IRIS logs everything you type, you should only enable debug mode when you need to report bugs**
|
||||
- [Shortcuts](./docs/README.md#shortcuts): core navigation, shortcuts table, mode switching, and ghost text
|
||||
- [Configuration guide](./docs/README.md#configuration-guide): TOML configuration settings including AI provider options
|
||||
- [Reporting bugs](./docs/README.md#reporting-bugs): debug mode, log inspection, and crash reporting
|
||||
- [Developer documentation](./docs/dev/README.md): system architecture overview, engine design, and contribution guide
|
||||
|
||||
## License
|
||||
|
||||
|
||||
+87
-176
@@ -1,252 +1,163 @@
|
||||
# IRIS documentation
|
||||
# User guide
|
||||
|
||||
Iris is a fast terminal autocomplete assistant written in Go. It wraps around your shell (Zsh, Bash, or Fish) to give you real-time command suggestions, a floating dropdown menu, and smart history search right where you type
|
||||
Iris is a fast terminal autocomplete assistant written in Go. It wraps around your shell (Zsh, Bash, or Fish) to give you real-time command suggestions, a floating dropdown menu, and smart history search right where you type.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Getting started](#getting-started)
|
||||
- [Usage guide](#usage-guide)
|
||||
- [Commands reference](#commands-reference)
|
||||
- [Shortcuts](#shortcuts)
|
||||
- [Configuration guide](#configuration-guide)
|
||||
- [Troubleshooting guide](#troubleshooting-guide)
|
||||
- [Developer guide](development.md)
|
||||
- [Reporting bugs](#reporting-bugs)
|
||||
- [Developer documentation](dev/README.md)
|
||||
|
||||
## Getting started
|
||||
|
||||
### Dependencies
|
||||
|
||||
Before installing Iris, ensure your system meets the following requirements:
|
||||
- OS: Linux or macOS
|
||||
- Terminal emulator with ANSI escape sequence support
|
||||
- Go 1.24 or newer if building from source
|
||||
- Terminal emulator with ANSI color support
|
||||
- Go 1.24 or newer (if building from source)
|
||||
|
||||
### Installation
|
||||
|
||||
You can install Iris using any of the three methods below:
|
||||
|
||||
#### Method 1: Install script (recommended)
|
||||
|
||||
Quickly download and install the precompiled binary using our install script:
|
||||
|
||||
```bash
|
||||
curl -sSL https://raw.githubusercontent.com/versenilvis/iris/main/scripts/install.sh | sh
|
||||
```
|
||||
|
||||
#### Method 2: Go install
|
||||
|
||||
If you already have Go installed on your system, install directly to your `GOBIN`:
|
||||
|
||||
```bash
|
||||
go install github.com/versenilvis/iris@latest
|
||||
```
|
||||
|
||||
Ensure that your `$GOPATH/bin` or `$HOME/go/bin` directory is added to your system `PATH`
|
||||
|
||||
#### Method 3: Build from source
|
||||
|
||||
To develop or compile Iris locally from source, install `just` command runner and execute `just reload`:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/versenilvis/iris.git
|
||||
cd iris
|
||||
just reload
|
||||
```
|
||||
|
||||
### Shell integration setup
|
||||
### Shell setup
|
||||
|
||||
To enable intelligent auto-completion and overlay rendering, connect Iris to your shell environment
|
||||
|
||||
For Zsh (`~/.zshrc`):
|
||||
Add an alias to your shell configuration file to launch Iris easily:
|
||||
|
||||
**Zsh (`~/.zshrc`):**
|
||||
```zsh
|
||||
if command -v iris >/dev/null 2>&1; then
|
||||
alias i="iris"
|
||||
fi
|
||||
```
|
||||
|
||||
For Bash (`~/.bashrc`):
|
||||
|
||||
**Bash (`~/.bashrc`):**
|
||||
```bash
|
||||
if command -v iris >/dev/null 2>&1; then
|
||||
alias i="iris"
|
||||
fi
|
||||
```
|
||||
|
||||
For Fish (`~/.config/fish/config.fish`):
|
||||
|
||||
**Fish (`~/.config/fish/config.fish`):**
|
||||
```fish
|
||||
if command -v iris >/dev/null 2>&1
|
||||
alias i="iris"
|
||||
end
|
||||
```
|
||||
|
||||
Verify your installation by running:
|
||||
## Shortcuts
|
||||
|
||||
```bash
|
||||
iris version
|
||||
```
|
||||
| Shortcut | Action | Description |
|
||||
| :--------------------------------- | :---------------------- | :------------------------------------------------------------------------ |
|
||||
| <kbd>Shift</kbd> + <kbd>Tab</kbd> | Toggle menu | Show or hide the suggestion menu. |
|
||||
| <kbd>Esc</kbd> | Hide menu | Temporarily hide the menu until the next key press. |
|
||||
| <kbd>Tab</kbd> | Accept suggestion | Insert the currently selected suggestion into the prompt. |
|
||||
| <kbd>Enter</kbd> | Execute command | Close the menu and send the current command to the shell. |
|
||||
| <kbd>↑</kbd> | Navigate up / history | Move the selection up, or open command history when the prompt is empty. |
|
||||
| <kbd>↓</kbd> | Navigate down / history | Move the selection down, or open command history when the prompt is empty.|
|
||||
| <kbd>→</kbd> | Accept ghost text | Accept the faded ghost text suggestion when the menu is open. |
|
||||
| <kbd>←</kbd> / <kbd>→</kbd> | Move cursor | Move the cursor inside the input buffer. Disabled when the prompt is empty|
|
||||
| <kbd>Ctrl</kbd> + <kbd>R</kbd> | Switch mode | Toggle between `spec` and `history` mode. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>A</kbd> | Beginning of line | Move the cursor to the start of the command line. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>E</kbd> | End of line | Move the cursor to the end of the command line. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>L</kbd> | Clear screen | Clear the terminal while preserving the input buffer and redrawing the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>U</kbd> | Clear command | Remove the entire current command and close the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>C</kbd> | Cancel command | Send `SIGINT`, clear the input buffer, and close the menu. |
|
||||
| <kbd>Ctrl</kbd> + <kbd>W</kbd> | Delete word | Delete the word immediately before the cursor. |
|
||||
|
||||
## Usage guide
|
||||
|
||||
Once inside an interactive Iris session, your shell receives powerful real-time auto-completion overlays and navigation enhancements
|
||||
|
||||
### Core navigation
|
||||
|
||||
When you type a command or query, Iris displays a floating overlay box positioned directly below your cursor with matching suggestions
|
||||
|
||||
- Up arrow (`↑`): Move the selection cursor up through the suggestion list
|
||||
- Down arrow (`↓`): Move the selection cursor down through the suggestion list
|
||||
- Tab: Insert the currently highlighted suggestion directly into your command line buffer without executing it
|
||||
- Enter: Execute the currently highlighted command immediately or submit the text typed in your prompt
|
||||
- Esc: Temporarily dismiss and hide the overlay suggestion menu for the current line
|
||||
- Shift+Tab: Permanently disable overlay suggestions until toggled back on
|
||||
|
||||
### Mode switching
|
||||
|
||||
Iris operates in two primary autocomplete modes: specification suggestions and history navigation
|
||||
|
||||
You can toggle between these modes instantly at any time by pressing `Ctrl+R`
|
||||
|
||||
- Specification mode (`spec`): Suggests available subcommands, flags, and arguments based on built-in tool specifications (such as git, npm, docker, or go)
|
||||
- History mode (`history`): Suggests previous commands from your shell history that match your typed prefix using fuzzy matching
|
||||
|
||||
When navigating with arrow keys and pressing `Ctrl+R`, Iris resets the menu selection and immediately loads suggestions for your typed query under the newly active mode
|
||||
|
||||
### Instant alias expansion
|
||||
|
||||
Iris supports POSIX and shell aliases defined in your configuration
|
||||
|
||||
When you type an alias keyword and press the `Space` key, Iris immediately expands the alias into its full command inside your command line buffer
|
||||
|
||||
### Ghost text autosuggestions
|
||||
|
||||
When ghost text is enabled, Iris displays inline completion suggestions ahead of your cursor in a muted style
|
||||
|
||||
- Right Arrow (`→`): Accept the inline ghost text suggestion and append it to your current command line buffer
|
||||
|
||||
## Commands reference
|
||||
|
||||
Iris provides a comprehensive set of CLI commands to manage shell integration, updates, configuration, and diagnostics:
|
||||
|
||||
```bash
|
||||
# start interactive autocomplete session (wrapped terminal wrapper)
|
||||
iris [flags]
|
||||
-s, --shell <shell> specify target shell environment (zsh, bash, fish)
|
||||
-d, --debug enable runtime debug logging to ~/.cache/iris/iris.log
|
||||
|
||||
# shell integration setup and initialization
|
||||
iris setup [shell] automatically configure shell integration in RC file and initialize default config
|
||||
iris init <shell> output raw shell wrapper code for manual evaluation in profile scripts
|
||||
|
||||
# configuration management
|
||||
iris config init initialize default configuration file at ~/.config/iris/config.toml
|
||||
iris config show output current active/resolved configuration in TOML format
|
||||
|
||||
# maintenance and diagnostics
|
||||
iris update check GitHub release tracks and update binary to latest release
|
||||
iris version print current semantic version string
|
||||
iris uninstall remove shell integration hooks from RC files and uninstall Iris binary
|
||||
iris crash-log display file path to the latest captured stack trace report
|
||||
iris crash-log --clear remove all stored crash logs from ~/.cache/iris/crashes
|
||||
```
|
||||
> [!NOTE]
|
||||
> With <kbd>Ctrl</kbd> + <kbd>A</kbd>, <kbd>Ctrl</kbd> + <kbd>E</kbd>, <kbd>Ctrl</kbd> + <kbd>W</kbd>, <kbd>Ctrl</kbd> + <kbd>U</kbd>, <kbd>Ctrl</kbd> + <kbd>L</kbd>, and <kbd>Ctrl</kbd> + <kbd>C</kbd>: they belong to your shell by default. IRIS handles them directly in raw mode so your cursor and menu stay in sync
|
||||
|
||||
## Configuration guide
|
||||
|
||||
Iris uses a clean TOML configuration file located at `~/.config/iris/config.toml` to customize UI presentation, suggestion behavior, and core engine settings
|
||||
Iris uses a clean TOML configuration file located at `~/.config/iris/config.toml`.
|
||||
|
||||
### Default configuration structure
|
||||
|
||||
Below is a complete sample configuration template with all available parameters and comments:
|
||||
|
||||
```toml
|
||||
# ~/.config/iris/config.toml
|
||||
# iris configuration file
|
||||
|
||||
[core]
|
||||
# schema version
|
||||
# do not edit this field manually
|
||||
version = 1
|
||||
|
||||
# override shell: "bash", "zsh", "fish", keep empty for auto detection
|
||||
shell = ""
|
||||
|
||||
# startup mode: "last", "spec", "history"
|
||||
# "last" = remember last mode used
|
||||
mode = "last"
|
||||
|
||||
# enable debug logging
|
||||
debug = false
|
||||
|
||||
[ui]
|
||||
# visual style: "modern" (icons, category pills, shortcut footer) or "classic" (minimalist, centered number, no icons)
|
||||
style = "modern"
|
||||
|
||||
# enable Nerd Fonts icons in overlay menu
|
||||
nerd-fonts = true
|
||||
|
||||
# enable inline ghost text
|
||||
ghost-text = true
|
||||
|
||||
# maximum suggestions to display
|
||||
max-suggestions = 100
|
||||
|
||||
# maximum height of the overlay
|
||||
max-height = 15
|
||||
|
||||
[git]
|
||||
# hide current branch in checkout/switch list
|
||||
filter-active-branch = true
|
||||
|
||||
# merge remote and local branches with same name
|
||||
deduplicate-branches = true
|
||||
|
||||
[updater]
|
||||
# check for updates on startup
|
||||
check-on-startup = true
|
||||
|
||||
# update channel: "stable", "nightly"
|
||||
channel = "stable"
|
||||
|
||||
# interval between update checks, e.g. "24h", "6h", "30m"
|
||||
check-interval = "24h"
|
||||
```
|
||||
|
||||
### Configuration sections
|
||||
|
||||
- `[core]`: Defines core engine settings including schema version, forced target shell (`bash`, `zsh`, `fish`), initial startup mode (`last`, `spec`, `history`), and diagnostic debug logging
|
||||
- `[ui]`: Controls visual layout such as inline ghost text autocompletion, total suggestions rendered, and maximum overlay box height
|
||||
- `[git]`: Specialized Git autocompletion behavior such as filtering out the currently active branch when switching and deduplicating local and remote branch names
|
||||
- `[updater]`: Configures automated background updates, checking frequency (`check-interval`), and release track (`channel`)
|
||||
|
||||
### CLI configuration commands
|
||||
|
||||
Iris provides built-in commands to inspect and modify settings directly from your shell:
|
||||
### Creating & viewing config
|
||||
|
||||
```bash
|
||||
iris config init
|
||||
iris config show
|
||||
```
|
||||
|
||||
## Troubleshooting guide
|
||||
### Sample `config.toml`
|
||||
|
||||
If you encounter unexpected behavior while running Iris, use the diagnostic procedures outlined below
|
||||
```toml
|
||||
[core]
|
||||
version = 1
|
||||
shell = "" # "zsh", "bash", "fish", or empty for auto-detection
|
||||
mode = "last" # "last", "spec", or "history"
|
||||
debug = false
|
||||
|
||||
### Debug mode and logging
|
||||
[ui]
|
||||
style = "modern" # "modern" or "classic"
|
||||
ghost-text = true
|
||||
max-suggestions = 100
|
||||
max-height = 15
|
||||
nerd-fonts = true
|
||||
|
||||
To inspect overlay positioning or command interception bugs in real time, launch Iris in debug mode:
|
||||
[git]
|
||||
filter-active-branch = true
|
||||
deduplicate-branches = true
|
||||
|
||||
[updater]
|
||||
check-on-startup = true
|
||||
channel = "stable" # "stable" or "nightly"
|
||||
check-interval = "24h"
|
||||
|
||||
[ai]
|
||||
enabled = false
|
||||
provider = "groq" # "groq" or "ollama"
|
||||
debounce_ms = 400
|
||||
|
||||
[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
|
||||
|
||||
[ai.providers.ollama]
|
||||
endpoint = "http://localhost:11434/v1/chat/completions"
|
||||
model = "qwen2.5-coder"
|
||||
timeout_ms = 5000
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Using `api_key_env` is recommended over hardcoding `api_key` in plain text to keep credentials out of configuration files.
|
||||
|
||||
## 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:
|
||||
```bash
|
||||
iris -d
|
||||
```
|
||||
|
||||
Runtime activities are written directly to the log file located at `~/.cache/iris/iris.log`. You can follow real-time events by running:
|
||||
|
||||
```bash
|
||||
tail -f ~/.cache/iris/iris.log
|
||||
or `config.toml`:
|
||||
```toml
|
||||
debug=true
|
||||
```
|
||||
|
||||
> [!Caution]
|
||||
> ### Common issues and solutions
|
||||
> - Overlay Position Misaligned: Multi-line shell prompts (such as Starship) emitting ANSI codes can cause offset issues. Iris automatically parses carriage returns (`\r`) and horizontal escape codes (`\033[nC`) to anchor visual columns accurately
|
||||
> - Menu Disappears When Toggling Mode: When pressing `Ctrl+R` after arrow navigation, Iris restores the original search query automatically so suggestions reload cleanly
|
||||
> - Inspecting Crash Logs: If the session terminates unexpectedly, inspect captured stack traces by running `iris crash-log`
|
||||
> [!IMPORTANT]
|
||||
> **Since IRIS logs everything you type, you should only enable debug mode when you need to report bugs**
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Iris developer & architecture documentation
|
||||
|
||||
This directory contains code architecture guides, engine design notes, and development instructions for Iris contributors.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Development workflow & runner](development.md): Environment setup, building, testing, linters, and modular `just` runner (`justfiles/`)
|
||||
- [AI engine architecture](ai.md): Internal AI completion system (`internal/ai`), providers, prompt design, and debounce strategy
|
||||
- [Scoring & frecency engine](scoring.md): Scoring mechanics (`internal/scoring`), frecency calculations, context rules, and skeleton extraction
|
||||
- [Overlay & rendering pipeline](overlay.md): PTY overlay positioning, cell width calculation, and terminal rendering
|
||||
- [PTY bridge & keystroke wrapper](root.md): Keystroke interception loop, raw mode PTY handling, and IPC scanner
|
||||
- [Spec & completion engine](spec.md): Static specifications, priority-based flag gating, and Cobra `__complete` dynamic completion
|
||||
- [File & path generator](filegen.md): File system traversal, extension filtering, and directory slash preservation
|
||||
- [History provider](history.md): Shell history indexing, search algorithms, and caching
|
||||
- [Auto updater](updater.md): Release tracking, version comparison, and atomic binary updates
|
||||
@@ -0,0 +1,29 @@
|
||||
# AI engine architecture (`internal/ai/`)
|
||||
|
||||
The AI subsystem provides real-time, context-aware command completions powered by cloud or local LLM providers (Groq, Ollama).
|
||||
|
||||
## Core components
|
||||
|
||||
- `internal/ai/client.go`: Defines the `Client` interface and handles HTTP requests to OpenAI-compatible chat completion endpoints.
|
||||
- `internal/ai/env.go`: Captures runtime context snapshots (`EnvSnapshot`) including CWD, previous command, exit code, and recent history.
|
||||
- `internal/ai/prompts.go`: Constructs system and user prompts optimized for shell command completion.
|
||||
- `root/wrapper.go`: Manages async debounce timers, request cancellation (`context.WithCancel`), and ghost text injection.
|
||||
|
||||
## Provider interface
|
||||
|
||||
All providers use a unified HTTP pattern matching OpenAI's `/v1/chat/completions` format:
|
||||
|
||||
```go
|
||||
type Client interface {
|
||||
Suggest(ctx context.Context, prompt string, env *EnvSnapshot, currentCmd string) (*AISuggestion, error)
|
||||
}
|
||||
```
|
||||
|
||||
## Request lifecycle
|
||||
|
||||
1. User types in the prompt buffer.
|
||||
2. `root/wrapper.go` triggers a debounce timer (`debounce_ms`, default 500ms).
|
||||
3. If typing continues, previous in-flight contexts are cancelled (`aiCancel()`).
|
||||
4. An `EnvSnapshot` is created capturing CWD, last executed command, and up to 3 recent history entries.
|
||||
5. Provider sends an HTTP POST request with structured JSON payload.
|
||||
6. Response is parsed and rendered as inline ghost text via `overlay.InjectAISuggestion()`.
|
||||
@@ -0,0 +1,50 @@
|
||||
# Development guide
|
||||
|
||||
This document outlines the development workflow, build system, and coding conventions for contributors working on the Iris codebase.
|
||||
|
||||
## Environment setup
|
||||
|
||||
Clone the repository and sync dependencies:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/versenilvis/iris.git
|
||||
cd iris
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
## Modular `just` command runner
|
||||
|
||||
We use `just` as our primary command runner. Recipes are organized into modular files under `justfiles/`:
|
||||
|
||||
- `justfiles/build.just` (`[build]` group): `build`, `optimized-build`, `build-release <version>`
|
||||
- `justfiles/dev.just` (`[dev]` group): `run`, `config-init`, `reload`, `copy`
|
||||
- `justfiles/test.just` (`[test]` group): `test`, `lint`, `analyze` (alias `ana`)
|
||||
- `justfiles/gen.just` (`[gen]` group): `gen-docs`
|
||||
- `justfiles/pkg.just` (`[pkg]` group): `pkg`
|
||||
- `justfiles/debug.just` (`[debug]` group): `debug`, `debug-update`, `debug-notify`, `debug-install`
|
||||
|
||||
Run `just -l` to quickly view all available recipes organized by group.
|
||||
|
||||
## Building and testing
|
||||
|
||||
### Rapid hot-reload
|
||||
|
||||
```bash
|
||||
just reload
|
||||
```
|
||||
|
||||
### Running unit tests
|
||||
|
||||
```bash
|
||||
just test
|
||||
# OR
|
||||
go test -v ./...
|
||||
```
|
||||
|
||||
### Running linter
|
||||
|
||||
```bash
|
||||
just lint
|
||||
# OR
|
||||
golangci-lint run ./...
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# Dynamic file suggestion generator (`spec/filegen.go`)
|
||||
|
||||
The `FileGenerator` is a dynamic suggestion engine bridging static command specs with your live filesystem.
|
||||
|
||||
## How it works
|
||||
|
||||
The generator is assigned to commands or options expecting file path arguments (e.g. `cat`, `go run`).
|
||||
|
||||
### Path resolution
|
||||
|
||||
Handles both local and nested paths:
|
||||
- `cat m` -> Scans `./` for entries starting with `m`.
|
||||
- `cat src/` -> Scans `src/` for all entries.
|
||||
- `cat src/main` -> Scans `src/` for entries starting with `main`.
|
||||
|
||||
### Intelligence features
|
||||
|
||||
1. **Extension filtering**: Restricts the generator to specific file extensions (e.g. `FileGenerator(".go")` for `go build`).
|
||||
2. **Directory suffixing**: When a directory is suggested, Iris appends `/` without an extra trailing space, allowing continuous folder traversal.
|
||||
3. **Descriptions**: Converts file extensions into human-readable labels (e.g. `.mp4` -> `video`, `.zip` -> `archive`).
|
||||
4. **Directory-only mode**: Commands like `cd` filter out files to display directories only.
|
||||
|
||||
## Code example
|
||||
|
||||
```go
|
||||
// registration for 'go run'
|
||||
Generator: spec.FileGenerator(".go")
|
||||
```
|
||||
|
||||
When typing `go run `, Iris scans the target directory, filters for `.go` extensions, and ignores unrelated binaries or assets.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Shell history integration (`integration/history.go`)
|
||||
|
||||
The `history` module provides `Ctrl+R` search functionality by reading the user's persistent shell command history.
|
||||
|
||||
## Features
|
||||
|
||||
- **Zsh extended support**: Parses `: <timestamp>;<command>` format common in Zsh.
|
||||
- **Lazy loading**: Reads disk only when history search is invoked, preserving instant startup performance.
|
||||
- **Fuzzy search**: Integrates with the `fuzzy` search engine for match scoring.
|
||||
- **Deduplication**: Filters duplicate commands, displaying unique entries.
|
||||
|
||||
## Data flow
|
||||
|
||||
1. User presses `Ctrl+R`.
|
||||
2. `root` sets `mode = "history"`.
|
||||
3. `SearchHistory("")` is called.
|
||||
4. If cache is empty:
|
||||
- Reads history file (`~/.zsh_history` or `~/.bash_history`).
|
||||
- Strips metadata using delimiters.
|
||||
- Populates command memory cache.
|
||||
5. Matches are scored and sorted by the search engine.
|
||||
6. Suggestions are returned to `overlay` for rendering.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Overlay rendering UI (`integration/overlay.go`)
|
||||
|
||||
The `overlay` package handles the visual representation of suggestions. It is designed to be non-destructive, drawing over the shell without corrupting the prompt or scrollback buffer.
|
||||
|
||||
## Design philosophy
|
||||
|
||||
- **ANSI ESC everywhere**: Uses ANSI escape sequences and CSI (Control Sequence Introducer) codes to manipulate terminal positioning.
|
||||
- **Save and restore**: Uses DECSC (`\0337`) and DECRC (`\0338`) escape sequences to return to prompt anchor after drawing.
|
||||
- **Fixed width**: Menu box uses a standard 72-character width (`boxWidth`) for consistent layout rendering.
|
||||
|
||||
## Technical details
|
||||
|
||||
The overlay engine manages positioning, scrolling protection, and styled cell drawing directly on the terminal grid.
|
||||
|
||||
### Terminal scrolling protection
|
||||
|
||||
When rendering near the bottom of the screen, printing new lines causes terminal scrolling which buries the active prompt. Iris prevents this by:
|
||||
|
||||
1. Moving to the prompt anchor.
|
||||
2. Printing N empty newlines to pre-allocate scroll space.
|
||||
3. Moving back up N lines.
|
||||
4. Re-saving the cursor at this stabilized location.
|
||||
|
||||
### Styling with Lipgloss
|
||||
|
||||
While Iris handles cursor positioning via raw ANSI codes, visual component styling uses Lipgloss:
|
||||
|
||||
- **Colors**: Dracula-inspired color theme (`#BD93F9`, `#6272A4`).
|
||||
- **Icons**: Fixed-width columns for category badges and completion types.
|
||||
- **Selection**: Highlights the currently active suggestion item with a distinct background (`#44475A`).
|
||||
|
||||
## Example logic
|
||||
|
||||
To render line 1 of the menu dropdown:
|
||||
|
||||
1. `\0338` (Jump to prompt anchor).
|
||||
2. `\033[2B` (Move 2 lines down).
|
||||
3. `\033[K` (Clear line buffer).
|
||||
4. Print formatted item: `│ [Icon] Command name... │`.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Iris central integration & event loop (`root/`)
|
||||
|
||||
The `root` package is the entry point and orchestration layer of Iris, handling low-level terminal PTY manipulation and the main interaction loop.
|
||||
|
||||
## How it works
|
||||
|
||||
1. **PTY wrapper**: Starts a pseudoterminal (PTY) wrapping the user's shell (`zsh`, `bash`, or `fish`). Shell is selected via `--shell` flag, config, or auto-detected by walking `/proc/<pid>/comm` up the parent process tree, falling back to `$SHELL`, and ultimately defaulting to `bash` if nothing matches.
|
||||
2. **IO interception**: Runs two pumps:
|
||||
- **Output pump**: Forwards shell output to terminal screen via synchronized `TermWrite`.
|
||||
- **Input pump**: Listens to keystrokes in raw mode, tracks typed characters in `naiveBuffer`, and triggers suggestion rendering.
|
||||
3. **State management**: Tracks active completion mode (`spec` vs `history`). Shell-specific IPC hooks (`preexec`/`precmd` for zsh, `PROMPT_COMMAND` for bash, `fish_postexec` for fish) signal command boundaries via `IRIS_CMD_STOP`.
|
||||
|
||||
## Key components
|
||||
|
||||
### `root/wrapper.go`
|
||||
Contains the core PTY loop:
|
||||
- Sets terminal to raw mode to intercept keys like `Tab`, `Esc`, or `Ctrl+C`.
|
||||
- Manages `naiveBuffer` string tracking prompt input state.
|
||||
- Handles suggestion insertion when pressing `Tab` or `Enter`.
|
||||
|
||||
### `root/term_sync.go`
|
||||
Provides `TermWrite`, a thread-safe stdout wrapper using `sync.Mutex` to prevent screen garbling when shell output and overlay rendering overlap.
|
||||
|
||||
## Example flow
|
||||
|
||||
1. User types `g`.
|
||||
2. `root` captures `g`, appends to `naiveBuffer`.
|
||||
3. `root` calls `renderOverlay()`.
|
||||
4. `renderOverlay` calls `Lookup("g")`.
|
||||
5. `overlay` renders suggestions box.
|
||||
6. User presses `Tab`.
|
||||
7. `root` inserts completion into prompt buffer.
|
||||
|
||||
## Hot-reload
|
||||
|
||||
Iris includes an atomic hot-reload mechanism for rapid local development:
|
||||
|
||||
- **Signal listener**: The root process listens for `SIGUSR1`.
|
||||
- **Process replace**: Uses `syscall.Exec` to replace the running binary in-place without killing the underlying PTY shell session.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Scoring & ranking architecture (`internal/scoring/`)
|
||||
|
||||
The scoring engine ranks suggestions by combining frecency algorithms, workflow sequence learning, and item-type priority rules.
|
||||
|
||||
## Core concepts
|
||||
|
||||
### 1. Frecency calculation (`internal/scoring/frecency.go`)
|
||||
|
||||
Frecency combines execution **frequency** with **recency** decay:
|
||||
|
||||
$$\text{Score} = \text{Frequency} \times e^{-\lambda \Delta t}$$
|
||||
|
||||
Commands executed recently receive a higher score multiplier that decays over time.
|
||||
|
||||
### 2. Workflow sequence learning (`internal/scoring/context_rules.go`)
|
||||
|
||||
Iris tracks sequential command pairs to learn common developer workflows (e.g. `git add` $\rightarrow$ `git commit`, `go build` $\rightarrow$ `./iris`). When a parent command skeleton matches the previous command, related suggestions receive a priority boost.
|
||||
|
||||
### 3. Skeleton extraction (`internal/scoring/skeleton.go`)
|
||||
|
||||
`ExtractSkeleton(cmd)` normalizes full command strings into structural skeletons by removing specific arguments and flags (e.g. `git commit -m "feat: test"` $\rightarrow$ `git commit`).
|
||||
|
||||
### 4. Spec priority & flag gating (`spec/lookup.go`)
|
||||
|
||||
Within spec completion mode:
|
||||
- Files and subcommands default to standard priority (`Priority = 30`).
|
||||
- Flags and options default to low priority (`Priority = 10`) when typing arguments.
|
||||
- When the user explicitly types `-` or `--`, flags are promoted (`Priority = 80`).
|
||||
@@ -0,0 +1,37 @@
|
||||
# Command specification & lookup engine (`spec/`)
|
||||
|
||||
The `spec` module is the language parser of Iris. It understands the relationship between commands, subcommands, and flags.
|
||||
|
||||
## Data structures
|
||||
|
||||
- **`Spec`**: Top-level command definition (e.g. `git`).
|
||||
- **`Subcommand`**: Recursively defined children (e.g. `commit` under `git`).
|
||||
- **`Generator`**: A function providing dynamic content (e.g. file paths, docker IDs).
|
||||
|
||||
## The `Lookup` algorithm
|
||||
|
||||
The core path-traversal function:
|
||||
|
||||
1. **Tokenization**: Splits `"git commit -m"` into `["git", "commit", "-m"]`. Empty tokens (from trailing space) indicate the user is ready for the next suggestion level.
|
||||
2. **Tree walking**: Starts at the root node (`git`) and matches each token against available subcommands.
|
||||
3. **Context identification**: When traversal stops (partial word or option prefix), it defines:
|
||||
- `prefix`: the path already traversed.
|
||||
- `partial`: the word currently being typed.
|
||||
4. **Result collection**: Gathers all subcommands and options matching the `partial` prefix.
|
||||
|
||||
## Example
|
||||
|
||||
Input: `git com`
|
||||
1. Tokens: `["git", "com"]`.
|
||||
2. Walk: root is `git`.
|
||||
3. Next token `com` doesn't match `commit` exactly.
|
||||
4. Stop. `partial = "com"`.
|
||||
5. Suggestions: subcommands of `git` starting with `com`.
|
||||
6. Return: `git commit`.
|
||||
|
||||
## Shell aliases & priority
|
||||
|
||||
- **Dynamic alias parsing**: Scans shell config files (`.bashrc`, `.zshrc`) for defined aliases.
|
||||
- **Highest priority**: Aliases appear above spec and system command suggestions.
|
||||
- **Token injection**: When a root command is an alias (e.g. `gr` for `go run`), Iris injects expanded tokens into the lookup engine for accurate subcommand suggestions.
|
||||
- **Display**: Shows the expanded command (e.g. `tmux a -t`) with the alias name in the description (e.g. `alias: ta`).
|
||||
@@ -0,0 +1,97 @@
|
||||
# Versioning and updates
|
||||
|
||||
Iris has a built-in update notification system designed to be non-intrusive and zero-latency
|
||||
|
||||
The update system is designed to keep Iris up to date while staying out of the way. It performs an asynchronous network check when the shell starts and notifies you exactly once per version after you run a command. This prevents redundant notifications and ensures that you only see an update message when a new release is actually available. The system also includes dedicated debugging tools to verify the notification logic without requiring real releases
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Background check**: every time you open a new terminal, Iris launches a background goroutine to check for updates
|
||||
- checks the network at most once every 6 hours to avoid GitHub API rate limiting
|
||||
- has a 5 second timeout so it never hangs on a slow or missing network connection
|
||||
- if there is no network, it fails silently with zero impact on startup
|
||||
|
||||
2. **State persistence**: state is stored in `~/.iris/update_state.json` with two fields:
|
||||
- `last_check` - unix timestamp of the last network check
|
||||
- `seen_version` - the latest version the user was already notified about
|
||||
|
||||
3. **Smart notification**:
|
||||
- the notice only appears after you run your first command (triggered by the `IRIS_CMD_STOP` IPC signal from the shell hook)
|
||||
- appears only once per session, never again even if you keep the terminal open
|
||||
- if you have already been notified about a specific version, it will not show again until a newer GitHub release tag is detected
|
||||
- when `iris update` is run successfully, the `seen_version` flag is cleared
|
||||
|
||||
## Build-time versioning
|
||||
|
||||
Iris uses Go `ldflags` to inject the version string at build time:
|
||||
|
||||
```bash
|
||||
go build -ldflags="-X github.com/versenilvis/iris/root.Version=v1.2.0" -o iris main.go
|
||||
```
|
||||
|
||||
If not provided, the version defaults to dev. The dev version will never trigger an update notification
|
||||
|
||||
## Commands
|
||||
|
||||
- `iris version` - print the current version of the running binary
|
||||
- `iris update` - manually check for and apply the latest release
|
||||
|
||||
## Debugging and testing
|
||||
|
||||
There are two separate things to test: the update command itself, and the in-session notification banner
|
||||
|
||||
### Test 1: update command
|
||||
|
||||
Tests version fetching, comparison and the output message. No full Iris session needed
|
||||
|
||||
```bash
|
||||
just build-release v0.0.1
|
||||
just debug-update v1.99.0
|
||||
```
|
||||
|
||||
Expected output
|
||||
```
|
||||
--- testing iris update command ---
|
||||
checking for updates (current: v0.0.1)...
|
||||
[IRIS] updating v0.0.1 -> v1.99.0
|
||||
running: curl -sS https://raw.githubusercontent.com/versenilvis/iris/main/scripts/install.sh | sh
|
||||
|
||||
[IRIS] restart your terminal to use the new version
|
||||
```
|
||||
|
||||
### Test 2: in-session notification banner
|
||||
|
||||
Tests the yellow notice that appears after you run your first command inside a live Iris session. Requires `iris.zsh` to be active in the inner shell so `IRIS_CMD_STOP` fires through the IPC pipe
|
||||
|
||||
```bash
|
||||
just build-release v0.0.1
|
||||
just debug-notify v1.99.0
|
||||
```
|
||||
|
||||
Inside the new session, run any command. Expected output after the command
|
||||
```
|
||||
[IRIS] new version v0.0.1 -> v1.99.0 available, run iris update to upgrade
|
||||
```
|
||||
|
||||
### Environment variables
|
||||
|
||||
| Variable | Purpose |
|
||||
| -------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `IRIS_UPDATE_URL` | override the GitHub API endpoint with a custom URL (used by `debug-update`) |
|
||||
| `IRIS_MOCK_LATEST_VERSION` | skip network entirely, resolve to this version immediately (used by `debug-notify`) |
|
||||
|
||||
### State reset
|
||||
|
||||
To force a fresh network check on next launch, delete the state file:
|
||||
|
||||
```bash
|
||||
rm ~/.iris/update_state.json
|
||||
```
|
||||
|
||||
## Implementation details
|
||||
|
||||
| File | Purpose |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------- |
|
||||
| `root/version.go` | holds the `Version` constant, defaults to `dev` |
|
||||
| `root/update.go` | all update logic: state persistence, network fetch, version compare, commands |
|
||||
| `root/wrapper.go` | wires the background check into the IPC loop, prints the notice on first `IRIS_CMD_STOP` |
|
||||
@@ -1,111 +0,0 @@
|
||||
# Development guide
|
||||
|
||||
This document outlines the architectural principles, development workflow, and mandatory coding conventions for contributors working on the Iris codebase
|
||||
|
||||
## Architecture overview
|
||||
|
||||
Iris functions as a transparent pseudoterminal (PTY) bridge sitting between the user terminal emulator and the underlying interactive shell (`zsh`, `bash`, or `fish`)
|
||||
|
||||
- PTY Bridge (`root/wrapper.go`): Intercepts keystrokes in raw mode, tracks typed queries, manages shell input/output buffers, and handles escape sequences
|
||||
- Overlay Rendering (`integration/overlay.go`): Computes visual character widths (`lipgloss.Width`), handles cursor column positioning, and draws floating menu boxes directly on the terminal grid
|
||||
- Suggestion Engine (`root/suggestions.go`): Collects, deduplicates, and sorts command completions from static specifications and fuzzy history search
|
||||
|
||||
## Development workflow
|
||||
|
||||
### Setting up environment
|
||||
|
||||
Clone the repository and verify that all dependencies are synced:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/versenilvis/iris.git
|
||||
cd iris
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### Building and reloading
|
||||
|
||||
To rapidly compile and reload your local development binary, ensure `just` is installed and run:
|
||||
|
||||
```bash
|
||||
just reload
|
||||
```
|
||||
|
||||
### Running tests
|
||||
|
||||
Run the full automated test suite without cache to verify system integrity before submitting code:
|
||||
|
||||
```bash
|
||||
go test -v -count=1 ./...
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
just test
|
||||
```
|
||||
|
||||
OR using my own test analyzer script
|
||||
```bash
|
||||
just ana
|
||||
```
|
||||
### Running linters
|
||||
|
||||
Ensure zero linting errors across the codebase:
|
||||
|
||||
```bash
|
||||
golangci-lint run ./...
|
||||
go vet ./...
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```bash
|
||||
just lint
|
||||
```
|
||||
|
||||
### Some available `just` commands
|
||||
|
||||
We use `just` as our primary command runner. Below are common shortcuts available during development:
|
||||
|
||||
- `just build`: Compile standard local binary
|
||||
- `just optimized-build`: Compile stripped, optimized binary
|
||||
- `just reload`: Compile binary and hot-reload any currently running Iris session
|
||||
- `just run`: Execute local `./iris` binary
|
||||
- `just debug`: Launch `./iris -d` in debug logging mode
|
||||
- `just test`: Execute full Go test suite
|
||||
- `just ana`: Run custom project test analyzer script
|
||||
- `just lint`: Execute static analysis and linter checks
|
||||
- `just build-release <version>`: Build versioned release binary (e.g. `just build-release v1.2.0`)
|
||||
|
||||
## Mandatory engineering rules
|
||||
|
||||
Contributors must strictly adhere to the following core UI/UX and architectural principles:
|
||||
|
||||
### Absolute positioning for overlay rendering
|
||||
|
||||
- Never rely on relative cursor movements (`\033[nA` or `\033[nD`) across multi-line inputs to draw menus, as wrapping causes severe visual jitter
|
||||
- Always compute absolute target columns (`targetCol = PromptLen + typedLen`) and use carriage return (`\r`) followed by horizontal positioning (`\033[targetColC`) to anchor the overlay box
|
||||
|
||||
### UI rules
|
||||
|
||||
- Stationary navigation vs dynamic typing: When navigating up or down through the menu (`↑` or `↓`), the overlay box position must remain fixed in place. When typing characters, the menu must shift dynamically along with the cursor column
|
||||
- Menu hiding: When clearing the input line completely or when typing up to a completed token where no further completion exists, the overlay menu must automatically hide
|
||||
- Context preservation: When moving left or right with arrow keys (`←` or `→`) or deleting characters with backspace, the engine must preserve context and re-evaluate the exact substring position to generate accurate suggestions
|
||||
- Empty buffer arrow suppression: When the command line buffer is entirely empty, pressing left or right arrow keys (`←` or `→`) must not open the menu or trigger suggestions
|
||||
- Temporary vs permanent dismissal: Pressing `Esc` hides the overlay menu temporarily for the current command line, whereas pressing `Shift+Tab` disables overlay suggestions permanently until toggled back on
|
||||
- Non-blocking navigation and context awareness: When moving the cursor back to the start of a typed command line, cursor movement must never be blocked or frozen, and the overlay menu must dynamically preserve context relative to the cursor position
|
||||
|
||||
### Responsive PTY handling and non-Blocking UI
|
||||
|
||||
- Do not block raw PTY keystroke interception loops with long operations or arbitrary debounce timers that freeze user typing
|
||||
- When handling navigation keys (up/down arrow) or mode toggles (`Ctrl+R`), update internal state synchronously and render UI feedback immediately
|
||||
|
||||
### Mode switching integrity
|
||||
|
||||
- When intercepting mode toggle keys (`Ctrl+R`), always reset navigation flags (`userNavigated = false`) and restore the original typed query buffer
|
||||
- This ensures that switching from specification suggestions to history navigation reloads clean completion lists starting from index 0
|
||||
|
||||
### Concurrency safety
|
||||
|
||||
- The PTY output read loop and keystroke interception loop run asynchronously in separate goroutines
|
||||
- Always use explicit synchronization (`sync.Mutex` or `sync.RWMutex`) when reading or modifying shared state variables such as `naiveBuffer`, `activeMode`, or `overlay.Items`
|
||||
Reference in New Issue
Block a user