Documentation
A light, AI-first terminal. Everything is a terminal command and every setting is a TOML file — there is no settings UI. This page is the complete reference.
Install & first launch
Grab a build from GitHub Releases (macOS 12+; Linux and Windows builds land with the next phases) — or build from source:
# zero external crates — this is the whole build
git clone https://github.com/mourad-ghafiri/aiTerminal.git
cd aiTerminal
cargo build --release
./target/release/aiTerminal
Prefer a real macOS app? One script bundles a self-contained
aiTerminal.app (binary + the builtin/ data + icon):
./tools/bundle-macos.sh # → dist/aiTerminal.app (+ a distributable .zip)
open dist/aiTerminal.app # run it — or install it:
cp -R dist/aiTerminal.app /Applications/
First launch seeds ~/.aiTerminal/ with the default config, 19 themes, 31 plugins,
keymaps, agents, flows and skills — every one an editable file. Nothing is ever overwritten
after that: your edits win.
Enable AI
AI is off until you declare a model — no vendor is assumed. Add one
[[ai.model]] to ~/.aiTerminal/config.toml:
[[ai.model]]
provider = "anthropic" # or openai · openrouter · deepseek · groq · grok
id = "claude-opus-4-8" # qwen · kimi · minimax · ollama · lmstudio · local
api_key = "sk-…" # or export the provider's env var instead
Declare several models and they form a weighted pool with automatic failover. aiTerminal never scans your machine for keys — only config or environment variables supply them.
The ~/.aiTerminal folder
~/.aiTerminal/
├── config.toml # the one config file (+ per-profile overlays)
├── profiles/ # <id>/{profile.toml, config.toml, workspace.toml}
├── themes/ # 19 builtin + yours
├── keymaps/ # keybinding layers
├── plugins/ # user-installed plugins (builtins ship with the app)
├── i18n/ # locale overrides
├── ai/
│ ├── aiTerminal.md # the global AI instructions — edit the persona
│ ├── agents/ skills/ prompts/ flows/ mcp/
│ ├── models/ # provider catalogs (12 ship)
│ ├── memory/ # BM25-ranked markdown memories
│ └── jobs/ # <id>/{job.toml, log.md}
├── logs/ cache/ shell/ crash.log
@ai — natural language → one command
❯ @ai list every port something is listening on
❯ press Enter to run (or edit)
❯ lsof -iTCP -sTCP:LISTEN -n -P
@ai reads your recent terminal session (shared as a redacted context file),
proposes exactly one command, and the guard checks it before your shell sees it:
- manual (default) — every command preloads at your prompt for review.
- auto — guard-allowed safe-listed commands run immediately; confirm-tier always drops to review; denied prints as a
#comment, never runs. - Ask a question instead and the answer streams as plain text:
@ai why is my docker build slow?
@<agent> — full agentic runs
❯ @coder "fix the failing parser test"
✦ @coder · claude-opus-4-8
∴ The test expects a trailing newline …
⚙ fs.search {"q":"parse_flow"} · 18ms · 2.1KB
⚙ fs.edit {"path":"src/…"} · 6ms · 412B
The fix: the parser dropped the final line …
✓ 8.4s · 2 tools · 12.3k in / 1.8k out
An agent is a Markdown file with TOML frontmatter — system prompt, allowed tools, step budget, skills. Five ship:
| Agent | Role |
|---|---|
@coder | Senior engineer + orchestrator — explores, makes the smallest correct edit, verifies, delegates sub-agents. |
@explorer | Fast read-only scout — maps relevant code, reports tightly. |
@reviewer | Read-only review — correctness, security, tests, design. |
@tester | Writes and runs tests; reproduces a failure, then fixes it. |
@ai | General assistant — concise answers, commands to review. |
Live chrome rides stderr, content rides stdout — so piping stays clean:
@explorer "map the auth flow" > auth-map.md works.
@flow — multi-step pipelines
❯ @flow # list available flows
❯ @flow review the PTY layer # first word names a flow → run it
❯ @flow add retry logic to fetch # free text → the default `implement` pipeline
A flow is a TOML file of steps, each a full agent run; with chain = true every
step sees the previous answers. Bundled: implement (explore → implement → verify)
and review (map → review). A failed step stops the pipeline and exits non-zero.
# ~/.aiTerminal/ai/flows/ship.toml — your own in 10 lines
description = "implement, test, and write the changelog"
chain = true
[[step]]
label = "implement"; agent = "coder"; prompt = "Implement: {{input}}"
[[step]]
label = "verify"; agent = "tester"; prompt = "Verify the change above."
@loop — iterate to a verified goal
❯ @loop "make the config tests pass" --check "cargo test -p framework config::"
🔁 loop 'coder' — up to 5 iteration(s)
▶ iteration 1/5 … ▶ iteration 2/5 …
✓ goal reached after 2 iteration(s)
Loop engineering, properly: the maker works the goal; an independent verifier
grades it — either your deterministic --check command (exit 0 = done; it passes
the guard first) or a separate read-only reviewer agent that must conclude
VERDICT: PASS. The model never grades its own work. Verifier output tails
forward into the next iteration.
| Flag | Meaning |
|---|---|
--check "<cmd>" | deterministic verifier; killed if it hangs past 10 minutes |
--max N | iteration cap (default 5) |
--budget TOKENS | total token budget across iterations |
--agent <name> | the maker (default coder) |
--bg | run the whole loop as a tracked background job |
Stop rules: success · max-cap · stalled (identical verifier output twice in a row — no progress, stop burning tokens) · budget.
@job — tracked & background tasks
❯ @job create a CHANGELOG from the last 10 commits # foreground: live + logged
❯ @job audit the deps --agent reviewer --bg # detached background run
▶ background job 1753112000-4242
❯ @job # list
background jobs (2):
▶ 1753112000-4242 running audit the deps … (2m ago · 2m)
✓ 1753111800-4101 done create a CHANGELOG … (9m ago · 45s)
Each job is a folder — job.toml (status, timestamps, exit code) +
log.md (the full streamed output; tail -f it). Background jobs are
fully detached: closing the terminal never kills them. Statuses are always honest:
running · done · failed · cancelled · died — a crashed job's record heals to
died on the next list, and @job clear prunes everything finished.
@profile · @theme · @config · @plugin
| Command | Does |
|---|---|
@profile | list profiles (● marks active) |
@profile work | switch by id or name — a running window applies it within a second |
@profile create|rename|delete|edit | manage profiles; edit opens the overlay in $EDITOR |
@theme | list the 19 themes |
@theme sunset | live restyle — window, panes, and running shells' colors |
@theme export nebula | print the full normalized TOML (start your own from it) |
@config / @config path | show effective config / the file path |
@plugin list|install|enable|disable|info | manage plugins from the prompt |
Exit codes & scripting
Every AI command tells the shell the truth, so $?, && and CI compose:
| Code | Meaning |
|---|---|
0 | completed (for @loop: the goal verified) |
1 | failed — model/transport error, step limit, tool stall; loop stalled/exhausted/out of budget |
2 | setup error — unknown agent/flow, AI not configured, guard-blocked check |
130 | interrupted — Ctrl+C cancelled cleanly (the in-flight request is killed mid-token) |
Tabs, splits & the quick switcher
- ⌘T new tab · ⌘W close · ⌘1…⌘9 jump · ⌃Tab cycle.
- ⌘D split right · ⌘⇧D split down · ⌘⌥arrows move focus · ⌘↩ zoom a pane full.
- Per-pane font zoom (⌘=/⌘-/⌘0), 10,000-line scrollback, char/word/line mouse selection, ⌘-click links and paths. ↩ with a live mouse selection copies it instead of executing.
- Command-line editing like a text field (the
lineeditplugin): ⌥/⌘ arrows jump by word / to the line ends, ⇧+arrows select on a light band (text keeps its colors), typing replaces the selection, ⌫/⌦ delete it, Esc cancels, ⌘C copies (OSC 52). Cursor: block (default), bar or underline. - ⌘P (or ⌘K) opens the switcher: type a number or fuzzy text over titles and working directories. Tabs auto-name from the running program, folder and shell — including the remote host over SSH.
- The tab bar docks top, bottom, left or right (
[behavior] tab_bar).
Profiles & session restore
A profile = a config.toml overlay (theme, AI pool, plugins, locale…) + a saved
workspace (tabs, splits, focus, per-pane zoom and cwd, window size — and the styled pane
content itself). Switching restores exactly the state you left, colors included,
silently. Autosave: 5 s after a structure change, every 30 s for content (skipped when
nothing changed).
Themes
19 ship: Midnight (default) · Graphite · Alpine · Nebula · Deep Purple · Lavender · Pink ·
Product RED · Sage · Gold · Mist Blue · Titanium · Coral · Cosmic Orange · Solar Flare ·
Sunset · Sky Blue · Starlight · Light Gold. A theme is one TOML of semantic tokens
(bg surface fg muted accent success warn error), a 16-color ANSI palette and
filetype colors that drive theme-matched ls output. Drop your own in
~/.aiTerminal/themes/ — @theme export gives you a starting point.
Keybindings
Layering, later wins: builtin default → plugin keybindings → your
~/.aiTerminal/keymaps/*.toml → config.toml [[keybinding]]:
[[keybinding]]
key = "cmd+shift+enter"
action = "zoom_pane"
Chords are layout-correct (an AZERTY ⌘⇧M matches the M keycap). ⌘⇧←/→ are deliberately unbound at the window level — they reach the shell as select-to-line-edge, like every macOS text field. The full action list ships in the docs folder of the repo.
Languages (i18n)
English and French ship; select with [appearance] locale = "fr" — per profile if
you like. Every chrome/CLI string flows through the catalog; add
~/.aiTerminal/i18n/<locale>.toml to translate or override anything.
Missing keys fall back locale → en → key, and CI enforces en/fr parity.
Shell integration
Non-destructive, and your rc files always win: zsh rides a generated ZDOTDIR
that sources your own .zshrc first; bash uses --rcfile. The master
switch is [shell] integration = false. What rides in:
- Plugin aliases, abbreviations and tab-completions
- Theme colors as
TT_*vars + matchingLS_COLORS— re-sourced live on@theme - The
@-command handlers viacommand_not_found(fires only for@-words) TT_SESSION_LOG— the redacted session context@aigrounds on
config.toml reference
| Section | Keys |
|---|---|
[appearance] | theme · locale · font_family (default Menlo) · font_size (default 15) · cursor_style (block / bar / underline) |
[behavior] | zoom · tab_bar = top|bottom|left|right · shell · scrollback (default 10000) |
[ai] | api_key · fast_model · share_terminal_context · memory · mode = manual|auto · network · [ai.balance] strategy |
[[ai.model]] | provider · id · api_key · weight · temperature · top_p · top_k · max_tokens · thinking |
[plugins] | enabled · disabled = [...] |
[shell] | integration |
[logging] | level = off|error|warn|info|debug|trace · retention_days (default 7) |
[security] | allowed_commands · denied_commands · confirm_commands · auto_safe_commands |
[[keybinding]] | key · action |
[[redact]] | pattern · replacement · scope = terminal|ai|all · literal |
@theme within a second — and ⌘, reloads instantly.Plugins
A plugin is a folder with a plugin.toml — declarative data over generic core
primitives; no plugin code runs inside the terminal process:
[plugin]
name = "my-tools"
description = "my aliases and status segment"
[aliases]
gs = "git status -sb"
[[segment]]
align = "right"; template = "🔧 {my.var}"
# plus: [[abbr]] [[completion]] [[keybinding]] [[allow_command]]
# [[deny_command]] [[confirm_command]] [[redact]] shell.zsh shell.bash
31 builtins ship (git, docker, kubernetes, rust, python, node, github, extract, jump,
autosuggest, syntax-highlight, history, lineedit, sudo, clipboard, encode, weather, web-search, …).
Trusted plugin shell snippets are sourced into your shell; third-party installs go under
~/.aiTerminal/plugins/.
Models & providers
12 provider catalogs ship as TOML under ai/models/ — Anthropic, OpenAI,
OpenRouter, DeepSeek, Groq, Grok (xAI), Qwen, Kimi (Moonshot), MiniMax, plus local Ollama,
LM Studio and a generic OpenAI-compatible local. Any model id a known provider
serves works, even if not pre-declared. Per-model capabilities (vision,
document, thinking, tools) gate what each request
carries; per-model pricing powers the token accounting in every run footer.
# a weighted pool: 3 of 4 requests to Opus, 1 to a local model
[[ai.model]]
provider = "anthropic"; id = "claude-opus-4-8"; weight = 3
[[ai.model]]
provider = "ollama"; id = "llama3"; weight = 1
Agents, skills & prompts
All plain files under ai/: agents are Markdown + frontmatter (tools, max_steps,
skills); 8 skills (code-review concise debugging git orchestration refactoring
security-review testing) splice into prompts; 3 prompt templates ship. The global
ai/aiTerminal.md is the system-prompt base for every run — edit it to
change the persona. Project-local ai/ folders shadow the global set, so a repo
can ship its own agents.
Attachments
Any @<path> token that names a real file becomes an attachment — in
@ai, agents, flows and loops alike. Images (png/jpg/gif/webp, ≤4 MB) ride as
vision blocks; PDFs as document blocks; text files inline fenced (≤48 KB, truncated
beyond); up to 16 per prompt; everything passes redaction first.
Memory & MCP
Memory: plain Markdown notes in ai/memory/, ranked by a from-scratch BM25
retriever — no database, no embeddings service. With [ai] memory = true, relevant
memories auto-inject into runs, and agents curate their own via memory.* tools.
MCP: declare Model-Context-Protocol servers under ai/mcp/; agent runs
launch them and expose their tools as mcp.<server>.<tool> beside the
native catalog.
The tool catalog
Native tools agents may call (each agent declares its own allowlist; undeclared tools are
refused): fs.* read/search/glob/write/edit (writes sandboxed to your invocation
directory) · sys.run (through the guard, output capped) · web/net/http
(SSRF-guarded, off with [ai] network=false) · git.* ·
memory.* · todo.* · task.run (parallel read-only
sub-agents) · data/queue/store · clipboard, clock, codecs and diagnostics.
Security
The AI proposes, the guard disposes.
- Command guard — three regex tiers, deny > confirm > allow. Defaults deny fork bombs,
rm -rf /,mkfs, raw disk writes; confirmsudo, force-pushes,rm -rf,curl | sh. Auto mode additionally runs only a safe-list of read-only commands. - Redaction — scoped rules (terminal / ai / all) scrub AWS·OpenAI·GitHub·Slack·Google keys, bearer tokens, JWTs, PEM blocks and
KEY=valuesecrets from everything AI-bound. The engine is step-budgeted: a pathological pattern can never hang your terminal. - Agent confinement — per-agent tool allowlists; file writes sandboxed to the invocation directory; secret-path reads blocked; sub-agents are read-only and cannot re-delegate; agent names and job ids are validated before touching the filesystem.
- Keys — never searched for on your machine; only config/env supply them; request bodies never appear in process argv.
Logging
A leveled async diagnostic logger writes one file per day under
~/.aiTerminal/logs/, auto-pruned after retention_days (default 7).
Default level is error — silence by default. Panics also append to
crash.log (rotated at 1 MiB), and the event loop drops the offending frame
instead of crashing the app.
Architecture
A four-layer Rust workspace — corelib < platform < framework < app —
with three CI gates: zero external crates in the lockfile, strict layer edges, and
unsafe confined to platform/src/os/ (every other crate root forbids
it). ~34k lines of Rust, 507 hermetic tests (all AI mocked, no network, temp homes).
The performance model: the event loop idles (~0% CPU, one wake per real change, renders paced to 60 Hz and damage-tracked to the GPU); every stream, subprocess and transcript carries a named byte cap with an over-cap regression test; every deadline kills its child; the regex engine is step-budgeted; a panic degrades to one dropped frame.
docs/ folder carries the full engineering documentation — architecture,
per-cap performance model, testing policy, packaging.
Read it on GitHub →