Ferrum

August 25, 2026 ยท View on GitHub

Ferrum is a small Rust-native coding agent for Linux with interactive and print modes.

It provides local file and shell tools, image input, JSONL sessions, AGENTS.md context loading, configurable OpenAI-compatible providers, ChatGPT/Codex OAuth, Agent Skills, and an MCP stdio bridge.

Ferrum is inspired by Pi's agent-harness ideas, but it is a separate Rust project. It does not aim to support Pi extensions, packages, themes, or SDK compatibility.

Status: active beta. Ready for day-to-day Linux coding work, still evolving.

Primary repository and binary releases: https://codeberg.org/ominiverdi/ferrum

GitHub mirror and backup binary releases: https://github.com/ominiverdi/ferrum

Features

  • Linux-native CLI
  • Print mode and interactive mode with live streamed responses
  • JSONL sessions with resume
  • AGENTS.md context loading
  • Configurable context budget and thinking level
  • Provider-supplied thinking display for supported models
  • Image input with optional terminal previews
  • Agent Skills-style instruction packages
  • MCP stdio tool bridge
  • OpenAI Codex / ChatGPT OAuth provider
  • OpenAI-compatible providers for remote APIs and local servers
  • Config-backed provider registry
  • Live model listing for supported providers
  • Built-in tools: read, writable-root-bound write/edit, structurally parsed tiered bash/wait, grep, find, ls
  • Model-facing session history tools: history_search, history_read
  • Tool exposure control with --tools and config allow/deny lists
  • Semantic UI color palette with ~/.config/ferrum/colors.toml and /colors auto|on|off
  • Interactive completion and hints for slash commands, selected command arguments, /image paths, and /skill: names

Install

Linux binary

Download the latest release asset from Codeberg.

curl -L https://codeberg.org/ominiverdi/ferrum/releases/download/v0.7.7/ferrum-v0.7.7-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo install -Dm755 ferrum-v0.7.7-x86_64-unknown-linux-gnu/ferrum /usr/local/bin/ferrum
sudo install -Dm644 ferrum-v0.7.7-x86_64-unknown-linux-gnu/docs/ferrum.1 /usr/local/share/man/man1/ferrum.1
sudo mandb 2>/dev/null || true
ferrum --help
man ferrum

Optional checksum verification:

curl -LO https://codeberg.org/ominiverdi/ferrum/releases/download/v0.7.7/ferrum-v0.7.7-x86_64-unknown-linux-gnu.tar.gz
curl -LO https://codeberg.org/ominiverdi/ferrum/releases/download/v0.7.7/ferrum-v0.7.7-x86_64-unknown-linux-gnu.tar.gz.sha256
sha256sum -c ferrum-v0.7.7-x86_64-unknown-linux-gnu.tar.gz.sha256

Debian and RPM packages are also available on the release page:

sudo apt install ./ferrum_0.7.7_amd64.deb
sudo dnf install ./ferrum-0.7.7-1.x86_64.rpm

From source

Install with Cargo:

git clone https://codeberg.org/ominiverdi/ferrum.git
cd ferrum
cargo install --locked --path .
ferrum --help

Install the local man page from a source checkout:

sudo install -Dm644 docs/ferrum.1 /usr/local/share/man/man1/ferrum.1
mandb 2>/dev/null || true
man ferrum

Quick start

Run a one-shot prompt:

ferrum -p "summarize this repo"

Pipe input as the prompt:

echo "summarize this repo" | ferrum -p

Pipe input plus extra instruction:

cat src/main.rs | ferrum -p "review this file"

Attach an image:

ferrum --image ./screenshot.png -p "describe this image"

Limit exposed tools:

ferrum --tools read grep find -p "inspect this repo"
ferrum --no-tools -p "answer without tools"

Start an interactive session:

ferrum

Start the bounded official ACP v1 stdio baseline:

ferrum acp

See docs/acp.md for supported methods and current interoperability limits.

Resume the latest interactive session:

ferrum --resume
ferrum --continue

New sessions record whether they were created by interactive, print, or ACP mode. Bare resume ignores print and ACP sessions. If no resumable tagged interactive session exists after upgrading, Ferrum resumes the newest legacy session and marks it interactive.

Use a named print-mode session for recurring jobs that need prior context:

ferrum --session port-audit --tools bash -p "compare current open ports with prior observations"

--session NAME -p ... creates NAME.jsonl on first use and resumes it on later runs. In interactive mode, --session REF opens an existing session by JSONL path or id prefix. See docs/sessions.md.

Minimal config

Ferrum reads user configuration from ~/.config/ferrum/config.toml. This is an example starting point; adjust the provider, model, and context budget for your account and backend. A project may add a restrictive .ferrum/config.toml for tool, root, skill, MCP, safety, and turn-limit policy; it cannot change providers or authentication. See docs/config.md.

An optional system prompt override can live at ~/.config/ferrum/system.md.

provider = "openai-codex"
model = "gpt-5.5"
thinking = "off"
safety = "medium"
max_context_tokens = 256000

[tools]
allow = ["read", "grep", "find", "bash", "wait"]
deny = ["write", "edit"]
writable_roots = ["."]

[providers.openai-codex]
type = "openai-codex"
base_url = "https://chatgpt.com/backend-api"
default_model = "gpt-5.5"

[providers.example-openai-compatible]
type = "openai-compatible"
base_url = "https://example.com/v1"
api_key_env = "EXAMPLE_API_KEY"
default_model = "example-model"

[models."gpt-5.5-small-context"]
actual_model = "gpt-5.5"
max_context_tokens = 6000

Login for ChatGPT/Codex OAuth:

ferrum login openai

ferrum login --help lists accepted provider spellings; openai-codex is an alias. When no provider is configured, login fetches the account's available models, asks for a default, writes the openai-codex selection to config.toml, and switches an active interactive session immediately. Use --model <MODEL> when login has no terminal, or --auth-only to save credentials without changing provider configuration. An explicitly selected provider is never overwritten.

Before login or when setup is intentionally skipped, Ferrum says explicitly that it is using the fake demo provider instead of silently presenting fake output as a normal backend.

OpenAI-compatible providers use environment-backed keys. Do not put secret values in config.toml.

Colors

Ferrum supports a small semantic UI color palette. Use color = "auto" in config.toml to colorize only on terminals, and override palette entries in ~/.config/ferrum/colors.toml:

prompt = "DeepSkyBlue1"
tool = "bold LightSkyBlue3"
error = "OrangeRed1"
diff_added = "SpringGreen1"
diff_removed = "DeepPink1"

See docs/colors.md for all palette keys and supported color values. Ferrum accepts xterm 256-color table names such as DeepSkyBlue1, Orange3, and SpringGreen1.

Reusable palettes can live in ~/.config/ferrum/color-palettes/*.toml. Ferrum ships 24 built-in palettes and seeds missing built-ins without replacing existing files. In interactive mode, /palette shows the current palette, /palettes opens the numbered, searchable palette picker, and /palette <name> validates and applies one live. /palette default restores Ferrum's built-in colors.

System prompt override

Ferrum has an embedded default system prompt. To fully override it, create:

~/.config/ferrum/system.md

Ferrum reads this file when starting or resuming a session. If the file is absent, the embedded default is used.

Supported placeholders:

{{ferrum_version}}
{{provider}}
{{model}}
{{provider_model}}
{{thinking}}
{{cwd}}
{{config_dir}}
{{max_context_tokens}}
{{max_tool_rounds}}
{{mcp_enabled}}
{{diff_mode}}

{{max_tool_rounds}} remains available to custom system prompts. Ferrum's default prompt leaves harness loop policy out of model context.

Do not put secrets in system.md. If you override the prompt, keep any runtime metadata and tool guidance you want Ferrum to preserve.

In active interactive turns, Esc aborts the current model/tool turn and returns to the prompt. Ctrl-C also aborts foreground tool execution such as wait.

Interactive commands

/help
/version
/session
/title [text]
/goal [text|clear]
/new
/sessions
/sessions all
/sessions del
/sessions new
/model [name]
/login <provider>
/usage [day|week|month]
/provider [name]
/mcp [on|off|status|list]
/thinking [off|minimal|low|medium|high|xhigh|max]
/diff [unified|compact|full|words|side_by_side]
/colors [auto|on|off]
/palette [name]
/palettes
/image <path>
/paste-image
/skills
/skill <name> [args]
/skill:<name> [args]
/compact
/quit
/exit

/new and /sessions new both start a fresh session. /sessions shows interactive sessions; /sessions all includes print, ACP, and legacy sessions. Selecting a non-interactive or legacy session marks it interactive. /model, /provider, and /palettes open numbered, searchable pickers. When configured model aliases omit provider, /provider includes a providerless entry that opens those aliases. /thinking, /safety, /diff, and /colors also open pickers when used without an argument. Enter a displayed number to select, enter text to filter labels and descriptions, or press Esc to return to the prompt without changing state. Explicit arguments such as /model gpt-5 remain available for direct selection.

/goal shows one session-scoped note, /goal <text> replaces it, and /goal clear removes it. The note is limited to 4096 bytes, persists with the session, and does not trigger model work.

Interactive mode also supports command completion and hints via Tab for slash commands, selected command arguments, /palette, /skill:, and /image paths. After the /model picker loads successfully, its provider model ids are available to /model <Tab> completion until the active provider changes.

Input beginning with / in column zero is always handled by Ferrum. Unknown slash commands are rejected locally instead of being sent to the model. Prefix slash-leading text with a space to send it as a model prompt; Ferrum removes that escape whitespace before sending it.

Shell shortcuts:

!<cmd>                              run shell command and send output to model
!!<cmd>                             run shell command and print output only
! --timeout-seconds=600 <cmd>       select a 1-600 second foreground timeout

Documentation

Safety notes

  • API keys are read from environment variables or provider OAuth storage.
  • Tools run with your local user permissions.
  • bash, write, and edit can mutate files. low grants broad current-user shell authority and bypasses writable roots; medium limits native and recognized shell mutations to configured writable roots; high rejects mutation.
  • Ferrum has no model-grantable confirmation prompt. At medium, a denied path requires a user config change or an action outside Ferrum.
  • Use /safety low|medium|high to choose structural shell execution policy for bash, wait, and shell shortcuts. It does not enable tools, and it is not a sandbox. See docs/security.md, docs/tool-authority.md, and docs/tools.md.
  • Provider, MCP, tool, repository, session, image, and filename text is treated as untrusted terminal data and sanitized before rendering. Native inspection and image paths have bounded input/output, count, cancellation, or deadline contracts documented in docs/resource-boundaries.md.
  • Use --tools and [tools] allow/deny to control which tools are exposed to the model.
  • See docs/security.md for security research notes and Ferrum's current posture.

Development

cargo fmt --check
cargo test
cargo build --release

License

MIT. See LICENSE.