Skip to content

Overview

Canonical source: README.md. This page is refreshed from the Finch repository when the website builds.

Finch is an experimental terminal agent runtime and coding assistant written in Rust. It provides an interactive REPL, provider-backed chat, code and shell tools with an approval boundary, local persistence, an MCP client, a typed Lisp/Co-Forth runtime, and named shared Brain sessions.

Finch is under active development. This README describes the current main branch, not a promise that every configured provider, local model, or experimental collaboration path is production ready. See Current limitations before relying on it.

Finch aims to bring capabilities that are currently split across terminal coding agents and always-on personal-agent systems under one user-controlled runtime. The intended problem space includes tools built around Codex, Claude, Grok, Muse, and OpenCode, as well as OpenClaw-style assistants that can remain available on a spare computer. Finch is not yet a drop-in replacement for those products.

The long-term design combines:

  • provider-independent coding and general agent workflows;
  • named, durable Brains that can survive frontend disconnects and machine restarts;
  • cloud providers, supported subscription authentication, local models, and explicit fallbacks;
  • repository skills and MCP integrations behind the same typed capability boundary;
  • semantic, accessible desktop automation instead of coordinate-driven GUI control;
  • local or hosted perception for voice, images, documents, and bounded text summaries;
  • attached terminal, editor, remote, and lightweight always-on frontends over one auditable event history.
Differentiator What it is intended to provide Current status
Typed Lisp and Co-Forth programs Agents can express multi-step computation and effects as programs that the runtime can validate and execute, instead of relying only on opaque one-tool-at-a-time calls. The typed runtimes and direct --lisp, --forth, and --exec interfaces exist; provider wire conformance and broader agent use are still evolving.
Durable named Brains One named conversation, event history, and persistent typed VM can survive frontend disconnects and daemon restarts. Implemented foundations with experimental reconnect, background-work, and collaboration workflows.
One capability boundary Code tools, MCP tools, future skills, remote peers, and desktop automation are meant to share typed authority, approval, audit, and revocation rules. Tool approval and MCP client paths exist; skills and wider automation integration remain planned work.
Provider and account portability Use cloud APIs, supported subscriptions, remote Finch nodes, or local models without changing the surrounding workflow or concealing which backend ran it. Multiple profiles exist; subscription support, model-level conformance, and explicit fallback behavior remain active work.
Local models and perception Keep suitable generation, speech transcription, OCR, image description, and context compression on user-controlled hardware, with explicit cloud fallback when requested. Daemon chat accepts an explicit GGUF through llama.cpp; frontend memory owns its separate required model defaults and download. Broader media support is not established.
Accessibility-native automation Operate applications through semantic roles, labels, and domain identifiers so automation remains usable and auditable without pixel coordinates. A design invariant and long-term integration target, not a complete personal-assistant feature today.

This direction is incremental. Current interfaces are described below; planned work belongs in the issue tracker and the dated development roadmap. Configuration types and design documents are not evidence that an integration works end to end.

The most reliable way to try the current code is to build a clean checkout. Release artifacts and runtime CI target Apple Silicon macOS and x86-64 Linux. The primary Windows CI contract checks the pinned Rust 1.98.0 rustfmt result; narrowly scoped component probes may compile selected portable sources, but neither constitutes Windows Finch runtime support. Install Rustup, Git, and the Cap’n Proto compiler first; the checkout selects that pinned toolchain.

macOS (Apple Silicon):

Terminal window
xcode-select --install
brew install capnp
git clone https://github.com/darwin-finch/finch.git
cd finch
cargo build --release --bin finch
./target/release/finch setup
./target/release/finch --cloud-only

Ubuntu/Debian Linux (x86-64):

Terminal window
sudo apt-get update
sudo apt-get install -y build-essential capnproto pkg-config libssl-dev
git clone https://github.com/darwin-finch/finch.git
cd finch
cargo build --release --bin finch
./target/release/finch setup
./target/release/finch --cloud-only

finch setup writes provider profiles and settings to ~/.finch/config.toml. The setup UI currently offers API-key profiles for Anthropic, OpenAI, xAI, Google Gemini, Mistral, and Groq, as well as local-model configuration. Use a provider model returned by the setup catalog or enter one explicitly; model availability changes independently of Finch.

GitHub release assets currently exist for Apple Silicon macOS and x86-64 Linux, but they can lag behind main. Release and installer reliability are being tracked in #119 and #144, so this first truthful refresh does not recommend the one-line installer as the canonical path.

These commands are defined by the current CLI:

finch interactive terminal UI
finch attach <name> resume a named Brain by its canonical event stream
finch --raw interactive line-oriented UI
finch --cloud-only skip local-model loading and the daemon
finch query "explain this" run one provider-backed query
finch setup configure provider profiles and settings
finch daemon foreground HTTP server on 127.0.0.1:8000 by default
finch daemon-start background daemon on 127.0.0.1:11435 by default
finch daemon-status report background-daemon status
finch daemon-stop stop the background daemon
finch --forth "1 2 +" evaluate typed Co-Forth without an LLM
finch --lisp "(+ 1 2)" evaluate typed Finch Lisp without an LLM
finch --exec path/to/file execute a typed Finch script
finch brain ls list named Brains (name, turns, size, attached, agents)
finch brain ls --json list named Brains as JSON summaries
finch brain rm <name> archive a named Brain (stop the daemon first)

Run finch --help and finch <command> --help for the full generated CLI reference. In the REPL, /help shows the slash commands present in that build. /model overlays a model on the active Brain (same credentials). /provider <name> binds that Brain to a configured provider entry. /status inspects the effective identity. --model is one-shot for this invocation and does not persist; /model does.

Typing @ at a token boundary opens a keyboard-navigable file picker. Selecting a file or directory inserts a visible @path mention and attaches a snapshot of its contents to the turn. Email addresses and \@ stay ordinary prompt text. Slash commands remain actions; @ is not a shell escape.

Tests and live smokes involving Brains must not be invoked directly. Give the process a disposable Finch home with the guarded wrapper (credentials needed by a live smoke should be supplied explicitly through environment variables):

Terminal window
./scripts/test_brains.sh env FINCH_LIVE_TESTS=1 cargo test --test live -- --ignored

The wrapper deletes the temporary store on success or failure and fails if the real ~/.finch/brains manifest changes.

A named Brain keeps one ordered conversation and one persistent typed Lisp/Co-Forth VM across multiple terminals and daemon restarts. Resume it with finch attach <name>.

Finch can inspect files, search source, propose changes, run commands, and call configured MCP tools. Approval is policy-dependent: known read-only operations may run without a prompt, while mutating or otherwise sensitive operations normally require review or are denied. Enabling an auto-approval setting changes that boundary. The implementation contract is documented in src/tools/EXECUTION.md; treat generated diffs and commands as untrusted until reviewed.

The authoritative configuration types live in src/config/settings.rs and src/config/provider.rs. A minimal API-key profile looks like:

[[providers]]
type = "claude"
name = "work"
api_key = "sk-ant-..."

Provider profiles may have user-defined names and model overrides. The code also contains profile types for Ollama, a remote Finch daemon, and local inference. Configuration support is not the same as end-to-end conformance: provider routing and model selection are still being reconciled in #51, #74, #98, and #104.

ChatGPT consumer subscriptions authenticate through Finch’s device-login flow and a Finch-native HTTP transport (finch auth login; see docs/OAUTH.md and docs/CHATGPT_SUBSCRIPTION_TRANSPORT.md). That flow is a compatibility boundary, not an OpenAI-supported third-party integration. Legacy Codex app-server chatgpt_subscription configuration is rejected with migration guidance; subscription authentication must not be inferred from OpenAI API-key support.

Muse Spark 1.3 can be configured through the direct, origin-bound Meta Model API profile with a named MODEL_API_KEY; see docs/META_MODEL_API.md. This is not OpenCode Zen or the Muse Code harness, and it does not claim local Muse Spark weights.

A hand-written type = "claude_cli_backend" entry drives the official claude CLI as a subscription subprocess instead of metered API billing. It is never offered by the setup wizard, it disables the CLI’s own tools so Finch’s permission system stays the only execution authority, and it carries real ToS/enforcement risk because Anthropic has enforced account suspensions against CLI-wrapper usage — the details and the measured wire contract are in docs/MULTI_PROVIDER_CONFIG.md. Configuring it is an explicit acceptance of that risk.

Daemon local chat loads either a Finch-managed, pinned Hugging Face GGUF or a user-selected GGUF file through llama.cpp. Managed downloads are resumed, size/checksum verified, and shown as one temporary status-bar entry. ONNX and Candle are not chat providers. Normal startup rejects configurations naming those removed engines without changing them. finch setup first creates a private adjacent backup, removes only the affected local [[providers]] block (or legacy [backend] block) and obsolete [coreml] sections, and preserves unrelated providers, credentials, settings, and comments before opening the editor to add the GGUF replacement. Local artifacts can be large. A configured local profile does not currently guarantee that a query is routed locally; local bootstrap, selection, and provider parity remain experimental under #74 and #98. The daemon currently requires at least one configured cloud provider as a fallback alongside local models. Use --cloud-only when you need to disable daemon local-chat loading.

The removed ONNX and Candle local-chat implementations were last available in commit 0607ccfad8ba790a236f701aa7d25f77488332d7. They were retired on 2026-09-22 because neither path provided a reliable supported chat runtime: ONNX/CoreML repeatedly crashed the daemon during Qwen session construction, while Candle’s Metal path lacked kernels required by the supported model families and produced wrong, absent, or impractically slow output. The replacement llama.cpp/GGUF path had completed real buffered, streamed, and CPU generation on the target MacBook before the cutover. The historical commit is for source archaeology, not a supported installation recommendation. Frontend memory remains a separate path: it uses its own fixed managed bge-small-en-v1.5 Q8_0 GGUF through llama.cpp rather than the user-selected chat GGUF, with a hashed-n-gram fallback while that artifact is unavailable.

finch daemon binds the foreground HTTP server to 127.0.0.1:8000 unless --bind is supplied. The separately managed background daemon uses 127.0.0.1:11435. The server implements POST /v1/chat/completions, GET /v1/models, POST /v1/messages, health/metrics endpoints, and Finch-specific feedback, node, and Brain routes. It does not implement the complete OpenAI API or the Responses API. Integration conformance is tracked in #130, #133, and #134.

When explicitly enabled, remote Brain collaboration uses a distinct TLS listener whose configured default is 0.0.0.0:11436. That listener exposes a restricted Brain route set; it is not the OpenAI-compatible endpoint.

Using the daemon as a local provider proxy

Section titled “Using the daemon as a local provider proxy”

POST /v1/chat/completions accepts OpenAI-shaped requests and answers them through whichever provider Finch is configured to use, so any tool that speaks that shape can reach every provider Finch can reach, without running a second service.

That translation is not built for the proxy. Finch already converts between provider wire formats because it drives several from one interface; the endpoint is that existing code with a different front door. It is the same job a standalone proxy such as LiteLLM does, and the reason it is nearly free here is that the hard part already had to exist.

Point a client at the daemon’s address — 127.0.0.1:8000 for finch daemon, 127.0.0.1:11435 for the background daemon, or whatever server.bind_address says.

It is unauthenticated by default. server.auth_enabled is false out of the box, which means any caller that can reach the port can spend your provider quota. To require a key, set this in ~/.finch/config.toml:

[server]
auth_enabled = true
api_keys = ["your-key-here"]

Exactly one non-empty key is accepted; the daemon refuses to start with zero or several. Callers send it as Authorization: Bearer your-key-here. The key is stored in plaintext in that file, so its protection is the file’s permissions and nothing more.

The endpoint is a compatible surface, not the complete OpenAI API, and provider coverage through it is exactly Finch’s provider coverage — which is configuration, not conformance evidence.

Finch can start configured stdio MCP servers and import their tools. It does not expose an MCP server. See the MCP client guide for configuration and troubleshooting.

The typed Lisp/Co-Forth runtime and named Brain persistence have extensive implementation and test coverage, but their user workflows are experimental. A Brain is a named, durable conversation and program environment owned by the daemon; local and remote attachment have different transport and authority boundaries. Subagent and remote-collaboration behavior is still evolving under #57, #107, #140, #145, and #146.

Use direct typed-runtime commands for bounded experiments:

Terminal window
./target/release/finch --forth "1 2 +" --json
./target/release/finch --lisp "(+ 1 2)" --json

Finch stores configuration and application state under ~/.finch/, including SQLite memory, sessions, named Brains, feedback, and approval patterns as applicable. Explicit good/bad response feedback is private durable metadata; it does not authorize or trigger training. Legacy training queues and adapters may be preserved but are not processed automatically.

Local storage does not make a cloud-backed session offline: prompts, selected context, and tool results sent to a configured cloud provider leave the machine and are governed by that provider. Configured MCP servers and remote Finch peers can also receive data as directed by their tools and capabilities. Finch has no automatic LoRA training path; see #139.

  • Finch is experimental and is not presented as release-ready or production-ready.
  • Provider and local-model behavior is not yet uniform; verify the exact profile and model you use.
  • ChatGPT subscription/device auth uses Finch’s device-login flow and its Finch-native transport (docs/OAUTH.md, docs/CHATGPT_SUBSCRIPTION_TRANSPORT.md); it is a compatibility boundary, not an OpenAI-supported third-party integration, and carries no live-model claim for any unreleased or unverified model.
  • The server supports a small endpoint subset, not the full OpenAI API and not /v1/responses.
  • Image-input/output support is not documented as available.
  • Finch does not automatically update itself, train LoRA adapters, or turn feedback into training.
  • Brain, remote collaboration, typed-agent, and subagent workflows remain experimental.

The issue tracker is the source for planned work. In particular, do not treat design documents as implemented behavior unless current source or tests say so.

After installing the prerequisites from Quick start from source:

Source builds use the repository-pinned Rust 1.98.0 toolchain. See docs/RUST_TOOLCHAIN.md for the tested-toolchain and MSRV policy.

Terminal window
cargo fmt --all -- --check
cargo check --lib --bins --tests
cargo test
python3 scripts/check_docs.py

Some full builds and tests are memory-intensive. Narrow commands to the module under change when appropriate, then rely on CI for the supported platform matrix. See CONTRIBUTING.md before submitting work and docs/README.md for the documentation map.

FINCH_STARTUP_TIMINGS publishes a per-phase startup report. It is off by default and costs nothing when unset.

Terminal window
FINCH_STARTUP_TIMINGS=~/startup.txt finch # write the report to a file
FINCH_STARTUP_TIMINGS=1 finch # write it to stderr (also: stderr)
RUST_LOG=finch::startup=debug finch # per-phase tracing events instead
FINCH_STARTUP_SLOW_BUDGET_MS=25 finch # warn about any phase over 25 ms

A phase over its budget (150 ms by default) is marked SLOW in the report and warns on the terminal, naming the phase and how long it took. FINCH_STARTUP_SLOW_BUDGET_MS lowers that budget, which is how the warning gets exercised without loading the machine; an unparseable value leaves the default in force.

When the daemon is in use, the daemon_http_connect phase now nests the GET /health probes (daemon_health_probe, with category=healthy, unhealthy or unreachable) and the unconditional two-second wait before the one retry (daemon_retry_backoff) as separate entries — so a slow launch says whether the daemon was slow or whether a healthy daemon merely missed one 500 ms probe window and cost this launch the flat floor. They need different fixes.

The report lists each phase and instant mark in start order with its offset from t0, its duration, and how many phases enclose it (depth — phases nest, so the ms column does not sum). It ends with accounted_ms, unaccounted_ms, and time_to_ready_ms.

Two things it is careful about. time_to_ready_ms runs from the first statement of main’s async body to the first instant a typed key is acted upon — not to the first painted frame, which happens on a render tick after it; process spawn and dynamic loading are before t0. And the report carries phase names, durations, counts and fixed categories only: no Brain name, path, prompt or credential can appear in it, which is what makes it safe to paste into a bug report.

scripts/bench_startup_time_to_ready.sh [runs] [brains] runs the same measurement repeatedly under disposable HOMEs and reports median, p90, min and max with the machine and commit attached. It is a benchmark, not a gate.

Finch was created and is maintained by Shammah Chancellor. Substantial portions of the project have been developed with assistance from Anthropic Claude and OpenAI Codex. Those products are development tools, not legal authors, maintainers, people, or GitHub identities. Commit authorship should identify the human responsible for the change; optional assistance trailers must be truthful. Existing contributor displays are a consequence of historical commit metadata and cannot be repaired without rewriting history, which this project does not do for attribution cleanup.

See CONTRIBUTING.md for the attribution policy.

Finch is source-available under the PolyForm Noncommercial License 1.0.0. Review the license text for the authoritative terms. Commercial licensing information is available at https://polar.sh/darwin-finch.