Skip to main content

Anchor

Find, fit, and benchmark local models with ease

License MIT macOS Apple Silicon Rust 2021 Tauri 2 React 19 Ollama backend

Status: early-stage. Signed builds ship from Releases and the app updates itself, but interfaces and internals still change often.

About

Anchor is a compact native macOS tool for finding, checking and testing local AI models. It sits on top of Ollama and handles the orchestration that makes local models actually usable: discovering and installing models, checking whether one will fit your machine before you pull it, trying what you have installed, benchmarking real throughput on your own hardware, and configuring how models behave — all from one place, no terminal required.

Anchor orchestrates existing runtimes: Ollama for interactive inference and serving benchmarks, plus an optional isolated MLX-LM worker for real-text benchmarks.

Anchor also owns the Ollama server lifecycle: it starts ollama serve on launch and shuts it down on quit, so you never need the menubar app or a terminal.

Built for developers, students, researchers, and small business operators who want capable AI running locally without touching a command line. Apple Silicon is the primary target.

Here for the benchmark numbers? Read how Anchor measures performance, including the timing boundaries, validation checks, and limits of comparisons.

Install

Requirement: Ollama must be installed. Anchor starts and stops the server for you, but it does not bundle the inference engine.

Desktop app

Download the latest .dmg from Releases and drag Anchor to Applications. It is signed and notarized, so it opens without a Gatekeeper prompt, and it updates itself from then on.

Open Models → Add model, pick a suggested model or browse the Ollama library, inspect its memory estimate, and download it. Select an installed model and choose Try model to start a chat at the chosen context. Past chats stay in SQLite and are listed by anchor chat ls.

No API keys are required. Inference and saved history work locally after setup when Ollama is configured on this Mac. Model downloads, fresh library data, update checks and external sharing use the network.

CLI

The CLI is packaged for PyPI as anchr, with the executable named anchor. After the first PyPI release, install it on macOS Apple Silicon with:

uv tool install anchr
anchor

Update with uv tool upgrade anchr. First-release account setup and cli-v* tag publishing are documented in CLI publishing.

Features

Try

A quick streaming chat with any installed model, with reasoning/thinking output rendered separately from the answer. Stop a generation mid-stream and keep the partial answer, or regenerate the last turn. New chat starts a fresh thread; every chat persists in SQLite (readable with anchor chat ls|show) and carries its inference preset. Before Anchor loads a model that isn't already resident, it checks whether swapping it in would blow your memory budget and asks first rather than letting Ollama choke.

Chat

Exploring models

  • Model hub — every installed Ollama model in one place, cached to SQLite so the list is instant on launch. Download with inline progress, remove, and inspect per-model detail: parameter count, quantization, context window, and file size.
  • Suggested models — a curated catalog with real GGUF architecture metadata, filterable by name, publisher or use case and sorted by what fits this Mac.
  • Browse the full library — every model and tag on ollama.com, not just the curated catalog, for when you know what you want by name.
  • Side-by-side comparison — run the same prompt through two models sequentially and compare their output and measured generation speed.
Model hub Model comparison

Fit

The question every other feature answers from a different angle: will this model actually run here? First-launch hardware profiling of CPU, RAM, and GPU — Apple Silicon is special-cased via system_profiler for accurate unified-memory readings — feeds a memory-fit engine that sizes weights, KV cache, and compute buffer per (model, quantization, context length) and renders one verdict everywhere a model shows up: the catalog, search results, the compare picker, and the chat model picker can never disagree, because they all call the same estimator. Every installed and not-yet-installed model gets a full breakdown — weights / KV cache / compute buffer / OS reserve — before you spend disk space or memory finding out the hard way.

  • One context for every verdict — pick 2K to 128K in the Models header and every fit column, filter and inspector re-judges at it (capped at each model's own limit).
  • Per-quant table — the inspector lists every published quantization of the same model size with its download, estimated RAM and headroom at that context, so you can pick the variant that fits before pulling it.
  • Predicted vs observed memory — after a measurement, the inspector shows the estimate next to what Ollama actually allocated at that context.
  • Use from other apps — copyable ollama run, OpenAI-compatible base URL and a curl snippet for any installed model.
Fit

Screen recording (dark) · Screen recording (light)

Benchmarks

Run nine text workloads covering classification, summarization, explanation, creative writing, document Q&A, detailed replies, reasoning and code generation. Choose Ollama or the optional MLX runtime, select a model and use Run suite. Each scenario has its own result; Fast and Thorough control the repeat budget.

The main measurements are decode speed after the first token and TTFT, the wait from request dispatch to first output. Memory observations retain their runtime-specific scope. The live waveform shows chunks/s. Input sizes are approximate targets and output lengths are caps; actual counts and early stops are saved.

Every session keeps its configuration, raw events, counters, warmups and started attempts, including failures and cancellation. Run history keeps the reports in the app; the CLI can export and replay raw evidence offline. Missing measurements stay unavailable. Current method-v5 results use formula 2; older results remain in history. Rankings describe reported rates for the selected workload and runtime; quality equivalence and cross-runtime winner claims remain unchecked.

Read the benchmark methodology for the workload table, timing formulas, cache and memory scopes, validation coverage, runtime support limits and reproduction instructions.

Ollama's Measurement validation → Validate measurements checks token counts, cache reuse, representative generations and response completion below the results. MLX runs timing/allocator checks automatically with its suite. Benchmark setup offers 64 paired catalog entries across Ollama and MLX for text-generation benchmarks, including Qwen 3–3.8, Gemma 3/4 and Ministral 3. Runtime-specific downloads preserve an explicitly selected model across runtime switches. On Apple Silicon, install uv, choose MLX → model → Download model → Run suite. Anchor handles checkpoint files, verifies pinned checksums and creates the locked worker environment. Existing cached models and local-folder import remain available. Catalog parity does not imply identical artifacts, image/audio benchmark support or compatibility with every model in either engine; see Ollama findings and current catalog coverage and limits.

Benchmarks

Screen recording (dark) · Screen recording (light)

Storage

A real scan of Ollama's on-disk store: total blob and manifest size, savings from shared files, and blobs that aren't referenced by an installed model. The desktop scan is read-only because an active download may still need an unreferenced blob. You can still remove installed models through Ollama.

Storage

Configuration

  • Inference presets — system prompt, temperature, top-p, and context length per conversation, autosaved as you type.
  • Hardware panel — the profiled chip, memory, and core counts Anchor is basing every fit verdict on, with a manual re-profile.
  • Appearance — dark (graphite/violet) or light (cream/gold) theme, or follow the system.
  • Privacy — a standing reminder that inference, chats, and history never leave the machine.
Appearance settings

Using the CLI

anchor is the terminal front-end over the same crates — and the same database, so a trial started in either is stored in one place, and a benchmark run there lands in the app's history. New commands documented here require building current source until the next CLI release is published.

Run anchor (or anchor tui) in a terminal. Type / at the prompt to search commands, Tab to complete and Enter to run. Ollama and MLX are listed in the header. Use /runtime to choose one or type /runtime mlx directly. /model picks a local model, /models manages installed models, and /library finds downloads. /bench opens setup and asks for a model if needed. /results, /leaderboard and /sessions browse saved measurements. Type to filter lists, use arrows or Page Up/Down to move, and press Enter for the primary action or Tab for more actions. Escape returns to the previous view. In a conversation, type at the prompt and press Enter to reply; replies stream into the transcript. Confirmations accept y or n. Ctrl-C clears the prompt, and pressing it twice quits. Ctrl-L refreshes, and /help shows controls.

Jobs stay visible across navigation. /activity shows the current or last job, including benchmark progress and a summary of decode rate and time to first token. Ctrl-C stops a running job; a second press forces it. /quit confirms stopping active work before exiting. Benchmark, chat and preset drafts survive Escape until submitted. Evidence export asks for a new filename and includes prompts/output; it never overwrites an existing file. The workspace requires a real terminal; explicit commands and --json remain available for scripts. MLX provides model downloads and benchmarking; chat, comparison, memory fit and store cleanup retain their existing Ollama scope.

anchor models ls                            # installed models
anchor models browse --filter qwen          # everything on ollama.com
anchor models catalog --runtime mlx         # supported pinned MLX checkpoints
anchor models pull mlx-community/gemma-3-270m-it-4bit --runtime mlx
anchor models compare llama3.2:1b qwen3.5:9b "why is the sky blue?"
anchor fit deepseek-v2 --ctx 32768          # weights + KV cache + verdict
anchor chat -m llama3.2:1b                  # interactive; omit -m to continue with --conversation
anchor bench scenarios                      # what the suite measures
anchor bench run llama3.2:1b --repeats fast
anchor bench run llama3.2:1b --scenario classify --repeats fast
anchor bench run mlx-community/gemma-3-270m-it-4bit --runtime mlx --repeats fast
anchor bench ls --runtime mlx                # saved results, no live runtime needed
anchor bench top --scenario balanced        # rank every model on one scenario
anchor bench sessions                       # includes failed/cancelled executions
anchor bench export SESSION_ID --include-content > evidence.json
anchor bench replay evidence.json           # offline recalculation from raw evidence
anchor bench validate llama3.2:1b            # validate Ollama measurements (calibrate remains an alias)
anchor bench report SESSION_ID              # saved settings and validation reports
anchor bench calibrate llama3.2:1b --output ./calibration  # isolated DB + full synthetic evidence
node tools/calibrate-ollama.mjs ./calibration/SESSION_ID.json  # independent replay/arithmetic check
anchor storage scan
anchor settings server --start

Use --json for scripting and --host to point at a non-default Ollama. JSON stdout contains the result; progress and errors go to stderr. Interactive chat requires a prompt, --file PATH or --stdin when using JSON. One-shot chat returns its conversation ID, model, cancellation state and response/thinking/stats. Comparison returns both slot outcomes and exits nonzero if either fails. Successful commands return 0, operational failures 1, argument errors 2 and interrupted work 130; a declined deletion returns a declined result without changing data.

models ls|info|browse|pull and bench run|ls|top|samples accept --runtime ollama|mlx (default Ollama). MLX accepts a supported downloaded catalog ID or a local checkpoint directory for execution. bench top --runtime mlx requires --model or --reference to keep tokenizer/template/runtime comparisons compatible; rankings default to the balanced workload. Sessions span both runtimes unless filtered with --runtime. Ollama and MLX rates/memory remain runtime-scoped. CLI repeats retain their existing Thorough default; use --repeats fast to match the GUI default.

Create or edit a preset with anchor settings presets save ID --name NAME --system TEXT --num-ctx 8192; unspecified fields stay unchanged, and --clear system,num-ctx restores runtime defaults for those fields. anchor chat preset CONVERSATION_ID PRESET_ID assigns it; omit the preset ID to return to the default. --preset also applies when continuing a conversation. anchor chat regenerate CONVERSATION_ID replaces the newest assistant turn using its original prompt. Chat and comparison accept --file PATH or --stdin for longer prompts.

Anything that deletes — models rm, chat rm, storage clean — asks first, and takes --yes to skip the prompt. The prompt reads from stdin, so a piped or redirected invocation without --yes declines rather than proceeding; scripts need the flag. The first Ctrl-C gracefully stops chat, comparisons, downloads and benchmark/validation runs. Partial chat output is saved; completed benchmark results and interrupted execution evidence are retained. Press Ctrl-C twice to exit immediately.

The app and CLI run as separate processes over the same Rust services and database. An OS-owned work lock refuses competing inference/measurement and model unload/removal operations; ordinary reads remain available, and the lock releases when an owner exits or crashes. Other applications and raw Ollama clients do not participate in this lock, so close unrelated inference work before benchmarking.

Build from source

Prerequisites

  • macOS (Apple Silicon recommended)
  • Ollama installed
  • Rust (stable) — rustup
  • Node 20+ and pnpm 10+
  • Xcode Command Line Tools (xcode-select --install)

Run it

git clone https://github.com/amapara27/anchor.git
cd anchor
pnpm install
pnpm dev                                   # app in dev mode
cargo install --path crates/anchor-cli     # the CLI, from source

Anchor profiles your hardware on first use.

pnpm build produces an unsigned local bundle. Signed, notarized releases are cut with pnpm release:mac, which needs a Developer ID certificate and an App Store Connect API key.

Architecture

A pnpm + Cargo monorepo. Domain logic lives in the crates; both front-ends — the Tauri layer and the CLI — are thin wrappers over them, which keeps everything testable without a webview.

anchor/
├── apps/desktop/
│   ├── src/                # React + Tailwind v4 frontend (TypeScript)
│   └── src-tauri/          # Tauri 2 shell — thin command wrappers only
└── crates/
    ├── anchor-cli/         # `anchor` terminal front-end over the same crates + database
    ├── anchor-core/        # shared domain types, the curated catalog + the memory-fit engine; UI- and Tauri-free
    ├── anchor-hub/         # model registry, SQLite, Ollama REST, server lifecycle
    └── anchor-system/      # macOS hardware profiling via system_profiler
Layer Technology
Frontend React 19, Tailwind v4, Vite
App framework Tauri 2
Backend Rust, Tokio, reqwest
Inference Ollama REST API
Storage SQLite via rusqlite, versioned migrations
Hardware system_profiler subprocess

All state — the registry, conversations and benchmark runs — lives under the app's data directory (~/Library/Application Support/…/registry.db). Inference and stored chats remain local when Ollama uses its default local host. A remote OLLAMA_HOST receives your prompts. Downloads, fresh library/metadata requests, update checks and explicit sharing can use the network; the app has no automatic telemetry path.

Development

pnpm dev                                     # run the app (Vite on :1420)
pnpm --filter @anchor/desktop build          # typecheck + frontend build (fast, no Rust)
cargo run -p anchor-cli -- models ls         # run the CLI from the workspace
pnpm test:e2e                                # full app, including real Ollama + MLX
pnpm test:e2e --surface cli                  # CLI-only full acceptance, real Ollama + MLX
pnpm test:e2e --surface cli --profile fixtures # CLI fixtures, no GUI or model downloads
pnpm test:e2e --profile fixtures             # model-free local workflows + native app
pnpm test:e2e --profile ci                   # build, persistence, measurements, CLI, browser, release refusal
pnpm test:e2e --only native                  # targeted reproduction + required build

Testing map and agent repair loop documents every stage, important code owners, failure artifacts, targeted reruns and manual limits. This single runner replaces the unit-test/self-check entry points and is used by CI. Reports live in .internal/testing/; failed, blocked and narrower passes stay distinct.

Full local acceptance requires Apple Silicon/macOS, Rust, pnpm, uv, Ollama, network access and Playwright Chromium (pnpm --filter @anchor/desktop exec playwright install chromium). Fixture scopes use isolated HTTP/database/filesystem data; full acceptance also downloads small models into disposable caches and exercises actual runtime/GPU paths. Your installed models and normal app database are untouched. Signing, notarization and actual updater installation remain separate manual checks.

Opt-in MLX E2E reads a local checkpoint on an Apple GPU: set ANCHOR_MLX_E2E_MODEL to its directory and run cargo test -p anchor-hub --test mlx_suite_e2e -- --ignored --nocapture. With the same variable, pnpm --filter @anchor/desktop test:e2e:native also checks the real GUI → uv worker → GPU → SQLite path and Stop. Real-text suite artifacts stay in .internal/benchmarking/mlx-suite-validation/; the separate legacy synthetic harness is exercised with --test mlx_e2e and retains artifacts in .internal/benchmarking/mlx-validation/; fixture scopes remain model-free. Worker dependencies live in workers/mlx/{pyproject.toml,uv.lock}; requirements.txt is the generated hash-pinned export. Regenerate it with uv export --project workers/mlx --frozen --no-dev --no-emit-project --output-file workers/mlx/requirements.txt after changing the lock.

To exercise a first-time MLX install, run ANCHOR_MLX_DOWNLOAD_E2E=1 pnpm --filter @anchor/desktop test:e2e:native on Apple Silicon with uv and network access. This downloads Gemma 3 270M (about 191 MB) through the actual app into an empty temporary Hugging Face cache, cancels during the weight transfer using Activity, retries, independently checks every pinned checksum, and runs all nine workloads plus Stop through native IPC. It ignores ANCHOR_MLX_E2E_MODEL, preserves your usual model cache, and removes its temporary checkpoint after success. JSON results and a screenshot remain in .internal/benchmarking/mlx-download-validation/; failed runs retain their temporary directory for inspection. The separate ignored mlx_download_e2e remains a cached-file corruption/repair check, not a clean-install test. Neither live test runs in normal CI.

Conventions worth knowing before contributing:

  • Domain logic goes in crates/*, never in src-tauri or anchor-cli. Both front-ends delegate.
  • The memory-fit math exists twice on purpose: anchor_core::fit (Rust) and apps/desktop/src/lib/kv.ts + fit.ts (TS, so the context slider recomputes without IPC). Both run against shared reference fixtures through CLI and rendered inspector E2E — change both, or neither.
  • Frontend types in apps/desktop/src/types.ts mirror the Rust serde types — keep them in sync.
  • Tailwind v4 via the Vite plugin. There is no tailwind.config.js or postcss.config.js.
  • SQLite migrations are append-only: never edit a shipped V* constant, add the next one.

Currently supported

  • macOS, Apple Silicon as the primary target. Intel Macs build and run but are untested.
  • Ollama for interactive inference and serving benchmarks; optional MLX-LM text models on Apple Silicon, with runtime-scoped results and a shared curated text catalog.
  • Desktop app and CLI, sharing one database, released separately: v* tags for the app, cli-v* for the CLI.

In the pipeline

Roadmap items, not promises with dates:

  • A guided first run — hardware profile, Ollama check, and a first model chosen to fit the machine, instead of dropping you into an empty app.
  • A community benchmark leaderboard. The schema is already there (source/synced_at columns on every bench run) and every run stores a full result today — there's just no results server yet, so all comparisons are local-only for now.
  • Publishing controls for what a shared benchmark run includes, once there's somewhere to publish it to.
  • Importing models from Hugging Face — pull a GGUF straight from a repo instead of waiting for it to land in Ollama's library.
  • Windows and Linux support.
  • Additional inference engines beyond Ollama, starting with direct llama.cpp integration.
  • Compact density and a live tokens/sec readout in chat.

License

MIT

Metadata

Release files for anchr 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for anchr 1.0.0
File Interpreter ABI Platform Actions
anchr-1.0.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for anchr-1.0.0-py3-none-macosx_11_0_arm64.whl

Release files / anchr-1.0.0-py3-none-macosx_11_0_arm64.whl

Download URL anchr-1.0.0-py3-none-macosx_11_0_arm64.whl
Size 2.7 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e2445877287e81c78c739855f907d74be7f5d25c786fcc12c91a6a9523385a85
BLAKE2b-256 checksum
How to use checksums
78d5d05f9c1997f338042c9963b000514303b4270bdaba7aa8019263ccb15092
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Security for anchr 1.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

1 file in this release has been uploaded with provenance metadata.

Attestation for anchr-1.0.0-py3-none-macosx_11_0_arm64.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page