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:

@<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:

AgentRole
@coderSenior engineer + orchestrator — explores, makes the smallest correct edit, verifies, delegates sub-agents.
@explorerFast read-only scout — maps relevant code, reports tightly.
@reviewerRead-only review — correctness, security, tests, design.
@testerWrites and runs tests; reproduces a failure, then fixes it.
@aiGeneral 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.

FlagMeaning
--check "<cmd>"deterministic verifier; killed if it hangs past 10 minutes
--max Niteration cap (default 5)
--budget TOKENStotal token budget across iterations
--agent <name>the maker (default coder)
--bgrun 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

CommandDoes
@profilelist profiles (● marks active)
@profile workswitch by id or name — a running window applies it within a second
@profile create|rename|delete|editmanage profiles; edit opens the overlay in $EDITOR
@themelist the 19 themes
@theme sunsetlive restyle — window, panes, and running shells' colors
@theme export nebulaprint the full normalized TOML (start your own from it)
@config / @config pathshow effective config / the file path
@plugin list|install|enable|disable|infomanage plugins from the prompt

Exit codes & scripting

Every AI command tells the shell the truth, so $?, && and CI compose:

CodeMeaning
0completed (for @loop: the goal verified)
1failed — model/transport error, step limit, tool stall; loop stalled/exhausted/out of budget
2setup error — unknown agent/flow, AI not configured, guard-blocked check
130interrupted — Ctrl+C cancelled cleanly (the in-flight request is killed mid-token)

Tabs, splits & the quick switcher

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/*.tomlconfig.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:

config.toml reference

SectionKeys
[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
Live reload. A running window follows config edits, profile switches and @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.

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.

Want the deep details? The repo's docs/ folder carries the full engineering documentation — architecture, per-cap performance model, testing policy, packaging. Read it on GitHub →