Natural-language shell assistant.
Sigil turns short terminal intents into explicit, inspectable shell interactions. Ask from local context, propose one reviewed agent step, do one routine step, or run one command with captured output without leaving your prompt. Sigil is inspired by IRC-style bot commands: lightweight punctuation prefixes that let you address an assistant inline without leaving the conversation.
, what changed in this repo?
,, run the relevant tests
,,, update the docs and run checks
+ cargo test
?Sigil is alpha software. It is ready for early shell users who are comfortable with local LLM tooling, editable command handoffs, and occasional interface changes.
Most shell assistants blur together three very different operations: suggesting, executing, and explaining. Sigil keeps those routes separate.
| Verb | Glyph | What happens |
|---|---|---|
| ask | , |
Answer from local context. No shell is exposed. |
| propose | ,, |
Run the agent until it can stage reviewed shell work or return an answer. |
| do | ,,, |
Run one auto-approved agent step; exact replacements are applied directly. |
| run | + |
Run one explicit command, stream output, and record stdout/stderr snippets. |
| status | ? |
Show the current session status without calling a model. |
The result is a shell workflow with small blast radius, durable state, and a plain CLI underneath the punctuation.
Install the Python command, then install the shell binding:
uv tool install sigil-sh
sigil install zsh
sigil doctorFor Bash:
uv tool install sigil-sh
sigil install bash
sigil doctor --shell bashYou can also install with pipx:
pipx install sigil-shTo try the current main branch before a tagged release:
uv tool install git+https://github.com/rlouf/sigilThe Python package is named sigil-sh because sigil was not available as a
distribution name. The installed command is still sigil.
sigil install copies the bundled binding to ~/.sigil/shell/<shell>/ and
adds an idempotent source block to .zshrc or .bashrc. Running it again
updates the binding without duplicating the rc block.
- Python 3.11+
- zsh or Bash for shell bindings
- A local OpenAI-compatible chat completions endpoint for command generation
and Zeta-backed answer/agent routes (default
http://127.0.0.1:8080/v1/chat/completions) - The bundled
zetaruntime entrypoint installed with Sigil.sigil doctorchecks that bothsigiland its runtime service are visible on PATH.
Useful environment variables:
ZETA_MODEL_URL=http://127.0.0.1:8080/v1/chat/completions
ZETA_MODEL_NAME=local-model
ZETA_MODEL_PATH=/path/to/model.gguf
SIGIL_STATE_DIR=$HOME/.sigil
SIGIL_RUN_CAPTURE_BYTES=6000
# Optional override used by sigil doctor/runtime service discovery.
ZETA_BIN=/path/to/zetaSigil can switch Zeta model profiles for the current terminal session without
changing global environment variables. Define profiles in ~/.zeta/models.toml:
[[models]]
name = "fast"
model = "qwen2.5-coder"
url = "http://127.0.0.1:8080/v1/chat/completions"
[[models]]
name = "deep"
model = "qwen3-coder"
url = "http://127.0.0.1:8081/v1/chat/completions"Then select a profile for the active shell session:
sigil model list
sigil model use fast
, why did the last command fail?
sigil model use deep
,, refactor the failing path and run the focused tests
sigil model show
sigil model clearThe selected profile is scoped to the current SIGIL_SESSION_ID, so another
terminal keeps its own model selection. Clearing the profile returns the session
to ZETA_MODEL_NAME and ZETA_MODEL_URL.
Once the shell binding is installed, use the glyphs directly:
# Ask from local context.
, why did the last command fail?
# Propose one reviewed agent step.
,, run the relevant tests
# Run one command through Sigil's explicit capture path.
+ cargo test
# Check current Sigil status.
?
Use stdin as context:
git diff | , review risky changes
git diff --name-only | , what should I test?Read-only comma uses piped input directly because it has no execute path. Agent-step routes are driven by the prompt text and the current shell session.
# 1. Ask what changed.
, summarize this repo state
# 2. Ask Zeta to pick the next shell step.
,, run the focused tests for this change
# 3. Edit or run the staged shell command normally.
uv run pytest tests/test_shell_bindings.py
# 4. Resume the Zeta turn with the recorded shell result.
,,Sigil keeps session state under ~/.sigil/ so Zeta can resume from recent
answer turns, handoff transcripts, and command results recorded through + or a
Zeta handoff capture window.
Installed zsh and Bash bindings expose these shortcuts:
| Glyph | Name | Behavior |
|---|---|---|
, |
ask | Answer from local context. |
,, |
propose | Run until Sigil can stage reviewed shell work or return an answer. |
,,, |
do | Run auto-approved tool calls until no more are needed. |
+ |
run | Run one explicit command and capture stdout/stderr snippets. |
? |
status | Show the current session status. |
Examples:
, summarize this repo state
,, run the relevant tests
,,, fix the failing parser test
+ cargo test
?, prints a read-only answer. It does not stage commands or write to shell
history.
,, proposes the next reviewed step. The loop may call local
tools such as read, ls, grep, bash, edit, and write until the model
returns a final answer. Tool calls are shown as muted trace lines, and tool
results are summarized compactly. The full JSON result stays in the Zeta
transcript for the model.
,,, does the same tool loop without the confirmation step.
Read-only routes do not expose Bash. If an answer recommends a command, it is plain answer text, not a tool call or terminal handoff.
+ runs the command you provide through sigil run, streams stdout/stderr live,
preserves the exit status, and records bounded stdout/stderr snippets for later
failure context. It does not use a shell parser; use sh -c for pipelines,
redirection, and shell-only syntax.
To install the CLI without punctuation shortcuts:
sigil install zsh --no-glyphsEach route has a fixed effect on your system:
| Route | Effect | Rule |
|---|---|---|
, ask |
read-only | Local answer route with no Bash tool. |
,, propose |
read/write/execute | Read-only tools run directly; Bash/edit/write are staged for review. |
,,, do |
read/write/execute | Read-only tools, Bash, edit, and write run directly. |
+ run |
execute | Explicit local command execution with stdout/stderr capture. |
? status |
read-only | Current session status without calling a model. |
Sigil stores audit/debug events and per-shell continuity under ~/.sigil/.
Inspect the global event log with:
sigil eventsThe glyphs are thin shell functions over a regular CLI:
sigil ask [--follow-up] [--json] [QUESTION]
sigil run COMMAND [ARGS...]
sigil status [--json]
sigil events [--limit N] [--json] [--raw]
sigil session [show|path|list|clear] [--json]
sigil install {zsh|bash} [--install-dir DIR] [--rc FILE] [--glyphs|--no-glyphs]
sigil doctor [--shell auto|zsh|bash] [--json]
Sigil also installs a bundled zeta entrypoint. It is a service API used by
the shell bindings and Sigil routes, not the primary user interface:
zeta tools list --json
zeta tool {read|ls|grep|bash|edit|write}
zeta transcript {append|tail}
Copy-pasteable examples:
sigil ask "what changed in this repo?"
sigil run cargo test
sigil eventsSigil writes event-sourced state under ~/.sigil/ by default. Set
SIGIL_STATE_DIR to move it.
Installed Bash and zsh bindings set SIGIL_SESSION_ID once when the shell
starts, so separate terminal windows keep separate continuity. Override the
boundary with SIGIL_SESSION_ID or SIGIL_SESSION_DIR.
Inspect state without calling a model:
sigil session show
sigil session list
sigil session clear
sigil eventsSigil is:
- A command-line tool and optional shell binding.
- A shell-owned Zeta loop for one-step read/search/edit/write workflows.
- An evented state layer for shell continuity and audit history.
Sigil is not:
- A public Python library. The Python package does not expose a supported API.
- A background autonomous agent.
- A replacement for reviewing commands and model output.
sigil sh is the likely next shell-shaped surface once explicit command
execution proves itself. The shell hooks are intentionally lightweight: they can
record command metadata, but they should not invisibly interpose on every
program's terminal output. A future shell frontend would own the prompt and
transcript boundary, delegate command semantics to the user's real shell, and
decide deliberately when a command runs as structured captured output versus an
interactive terminal session.
Set up the repo:
uv sync --group devRun the checks used by CI:
uv run pre-commit run --all-files
uv run pytestApache-2.0. See LICENSE.