- Rust 78.4%
- Shell 21.6%
Add 'tools/fix-doc.sh' to generate documentation repair reports from a target document and one or more source-of-truth files or directories. Changes: - add 'tools/fix-doc.sh' with argument validation, repository-root path resolution, structured context rendering, and '.generated/fix-doc-<UUIDv7>' report output - support overrides for 'REPO_ROOT', 'GENERATED_FILE_PREFIX', 'TAI_BIN', 'TAI_MODEL', and 'PROMPT' - render line-numbered documentation and reference file context before invoking 'terminal-ai' - invoke 'tools/show-fix.sh' after generating documentation fix reports - update 'tools/generate-commit-msg.sh' to use configurable 'TAI_MODEL' with default 'gpt-5.5' - refresh 'docs/TOOLS.md' to document 'fix-doc.sh', current tool behavior, environment variables, generated artifact prefixes, dependencies, and workflows Changelog: - new documentation-fix workflow: './tools/fix-doc.sh docs/TOOLS.md tools' - generated documentation reports now use the 'fix-doc' prefix - commit-message generation now uses 'TAI_MODEL' instead of a hard-coded model string |
||
|---|---|---|
| bin | ||
| docs | ||
| src | ||
| tools | ||
| utils | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| install.sh | ||
| README.md | ||
terminal-ai
A pipeline-safe terminal AI client that records conversations as structured Markdown transcripts. Each exchange is written independently to three output channels, each with its own rendering policy, so the same binary pipes cleanly between shell tools while archiving full metadata for later replay.
cargo build --release
Runtime dependencies: curl (HTTP), sha256sum (message IDs), date (timestamps). All standard on Linux.
What it does
Three output channels
Every turn is rendered independently to each enabled sink:
| Channel | Purpose | Default format |
|---|---|---|
stdout |
Clean AI response for pipelines | Content only |
transcript |
Append-only archival log | Header + indent + --- |
artifact |
Explicit per-run output file | Configurable |
stderr is a fourth channel reserved for metadata, errors, and interactive prompts.
It never carries conversation content.
# Count words in a response without contamination
terminal-ai "list ten unix commands" | wc -w
# Full transcript format on stdout for inspection
TAI_STDOUT_HEADER=1 TAI_STDOUT_INDENT=1 TAI_STDOUT_SEP=1 terminal-ai --dry-run "test"
Message IDs and conversation threading
Every turn is identified by a deterministic hash of who spoke and when, paired with the ID of the turn it responds to. This forms a directed graph across the transcript without a database.
SpeechID := HASH8(Speaker, Timestamp)
AudienceID := parent SpeechID | HASH8("NULL") for roots
MessageID := "<SpeechID>-<AudienceID>"
--parent-id attaches a new turn to an existing prior speech, enabling branching
and multi-pass workflows across separate invocations.
See docs/concepts/message-ids.md for the full graph model.
Build
cargo build --release # production binary
cargo build # debug binary (used by generate-commit-msg.sh for dogfooding)
Cargo workspace: Cargo.toml at repo root. Single binary: terminal-ai.
Use
Prompt sources
Prompts are resolved in order:
- Trailing CLI words:
terminal-ai "explain monads" --separator:terminal-ai -- explain monads- Piped stdin:
echo "explain monads" | terminal-ai - Interactive: invoked with no arguments in a TTY
Multi-line input via xargs -0:
cat context.txt | xargs -0 terminal-ai "summarise this"
Pipeline usage
stdout is content-only by default. Pipe freely:
terminal-ai "list ten unix commands" | fzf
terminal-ai "generate a config" | tee ./out.conf
terminal-ai "question" | head -n1 # exits cleanly with code 0
Backend switching
Any OpenAI-compatible endpoint. Bearer header is sent only when OPENAI_API_KEY is set:
TAI_BASE_URL=http://localhost:8080 terminal-ai "…" # llama.cpp, keyless
TAI_BASE_URL=https://api.deepseek.com OPENAI_API_KEY=sk-… terminal-ai "…"
TAI_BASE_URL=https://api.openai.com OPENAI_API_KEY=sk-… terminal-ai "…"
Transcripts record the model name reported by the backend, so switching backends is attributable without any other change.
Output control
Fine-grained suppression and formatting via -o:
terminal-ai -o NO_USER_TRANSCRIPT "question" # suppress user turn from log
terminal-ai -o CONTENT_ONLY_STDOUT "question" # no header/sep on stdout
terminal-ai -o NO_METADATA "question" # drop usage metadata from all channels
terminal-ai -o NO_AI_STDOUT,NO_USER_TRANSCRIPT … # combined, comma-separated
Full token grammar: docs/CONFIGURATION.md#output-control.
Transcript inspection
Transcripts are append-only dated Markdown files under $XDG_DATA_HOME/terminal-ai/transcripts/default/.
grep '^\[' ~/.local/share/terminal-ai/transcripts/default/$(date --rfc-3339=date).md
Configure
Resolution order, highest to lowest:
CLI flag → process env → TAI_ENV_FILE / --env-file → config.env → .default.env → default
Core variables:
| Variable | CLI flag | Default | Purpose |
|---|---|---|---|
TAI_MODEL |
-m, --model |
gpt-5.4 |
Model name |
TAI_BASE_URL |
-b, --base-url |
https://api.openai.com |
API base URL |
OPENAI_API_KEY |
— | — | Bearer token |
TAI_TRANSCRIPT_DIR |
--transcript-dir |
~/.local/share/…/default |
Transcript directory |
TAI_OUTPUT_FILE |
-O, --output-file |
— | Artifact output path |
TAI_SPEAKER_USER |
— | USER |
User turn label |
TAI_SPEAKER_AI |
— | model name from response | AI turn label override |
TAI_NO_TRANSCRIPT |
--no-transcript |
false |
Disable transcript writing |
Full reference: docs/CONFIGURATION.md.
Develop
Commit workflow
- Stage a self-contained unit with GitUI
./tools/generate-commit-msg.sh— pipesgit diff --cachedto debug binary- Review with
./tools/view-last-commit-msg.sh - Commit
git commit -m $(./tools/view-last-commit-msg.sh
Generated files land in .generated/ with UUIDv7 names. Never commit .generated/.
LLM-assisted fixup
./tools/fix.sh # clippy → AI → .generated/fix-<uuid>
./tools/fix-tools.sh # shellcheck on tools/ → AI → .generated/shellcheck-<uuid>
./tools/show-fix.sh # view latest fix report (mdless)
./tools/show-fix.sh --pipe # or pipe it
Both fixup tools use the release binary. The commit message tool uses the debug binary to surface regressions early.