Skip to main content

Scribe

๐ŸŒ English ยท ็ฎ€ไฝ“ไธญๆ–‡

CI Python 3.10+ License: MIT

Local-first chat + research + coding agent. Connects to any OpenAI-compatible server (llama.cpp, Ollama, LM Studio, or a cloud API key) and uses web search, RAG and semantic memory to research, write, and remember โ€” across sessions. Runs comfortably on a 12 GB VRAM machine with Gemma 4 12B at 128k context.

Why Scribe

Three properties that hold by construction, not by prompt-tuning:

  1. The tool call cannot break. On a llama.cpp server Scribe enforces tool calls with a GBNF grammar generated from the tool schemas โ€” a malformed call is grammatically impossible, and a model that fumbles is re-asked under the grammar. (scribe/grammar.py)
  2. Answers cite their sources, or say they can't. Grounded Q&A maps every claim to a numbered source [n], tags [CONTRADICTION] when sources disagree, and refuses to answer outside the sources. (scribe/prompts.py)
  3. Grounding is measured, not asserted. scribe-llm bench reports a deterministic Source-Presence Index (SPI) over a checksum-locked held-out suite โ€” on Gemma 4 12B it scores SPI 1.00. (scribe/evolve/spi.py)

Honest scope: GBNF and constrained decoding aren't new โ€” llama.cpp added grammars in 2023, and the same idea ships elsewhere as "structured outputs". Scribe's contribution is the integration: auto-generating the grammar from your tool schemas and wiring it as an automatic tool-call safety net for small local models. Guarantees 1โ€“3 hold on llama.cpp; other backends degrade to a best-effort text parser. The grammar guarantees a call's form, not the model's judgment (it can still pick the wrong tool โ€” it just can't emit a malformed one).

๐Ÿ“– Full overview on the project site.

Features

  • Universal LLM Adapter โ€” llama.cpp, Ollama, LM Studio, or any OpenAI-compatible cloud API (OpenRouter, Groq, ...) โ€” see docs/providers.md
  • GBNF Tool Enforcement โ€” grammar-constrained tool calls on llama.cpp; auto-repair when a model emits a malformed call
  • Grounded Q&A โ€” hybrid retrieval (FTS5 + vectors, RRF) with mandatory citations and contradiction tagging
  • Quality Gate โ€” scribe-llm bench runs a judge-scored fitness suite and the deterministic SPI grounding metric
  • Safe Code Mode โ€” /code with a destructive-command gate, Python AST gate, bubblewrap sandbox, and git checkpoint/rollback
  • Internet Research โ€” web_search + web_fetch tools; DuckDuckGo out of the box, Brave with a key
  • Writing Agent โ€” deep-research and writer skills for books, papers and reports, with sandboxed workspace file tools
  • Book Studio (web) โ€” dark, VSCode-style web editor: three resizable panes, an integrated terminal, model-drafted table of contents, chapter-by-chapter writing, and Markdown / EPUB / PDF export
  • Open Knowledge Format โ€” scribe-llm wiki distill curates sessions into portable OKF markdown (YAML frontmatter + index.md/log.md + links); SME/RAG are derived indexes over the files
  • Persistent Self โ€” a WorldModel persona injected into every prompt, plus pulse heartbeat and nightly diary
  • Observability โ€” ORORO session traces and a machine-readable scribe-llm status --json contract
  • Project Vaults โ€” scribe-llm init gives a directory its own isolated RAG/SME stores
  • Model Discovery & Blind Compare โ€” auto-find local servers; A/B two models without bias
  • Cross-Session Memory โ€” SME (Semantic Memory Engine) for seamless session continuity
  • Email Bridge โ€” get results by email and send commands from one approved address (stdlib only)
  • Language games โ€” explicit command vocabularies (Wittgenstein-inspired) for stable LLM behavior

Installation

From PyPI

pip install scribe-llm       # provides the `scribe-llm` command (alias: `scb`)

The PyPI distribution is named scribe-llm; the CLI command is scribe-llm (short alias scb). The import package stays scribe.

From source (๐Ÿง Linux / ๐ŸŽ macOS)

# Clone the repository
git clone https://github.com/pedjaurosevic/scribe-llm.git
cd scribe-llm

# Run the install script: installs the package (editable), creates the
# config, and scaffolds ~/scribe-workspace.
./scripts/install.sh

๐ŸชŸ Windows (WSL)

scribe-llm chat and the scribe-llm web Book Studio run on native Windows too; only the web UI's integrated terminal needs a POSIX PTY (it degrades gracefully without one). For the full experience, run Scribe via WSL (Windows Subsystem for Linux).

  1. Open your WSL terminal (e.g., Ubuntu).
  2. Run the Linux installation commands shown above.
  3. To configure Scribe to work with Ollama (either running natively on Windows or inside WSL), check out the WSL & Ollama Integration Guide.

Or install by hand (skip the script):

pip install -e .

Requires Python 3.10+. The install is editable, so git pull updates Scribe in place.

Quick Start

  1. Start your llama-server:
./scripts/start-server.sh
  1. Start Scribe:
scribe-llm chat
  1. Scribe will automatically recall your last session and ask if you want to continue.

Configuration

Edit ~/.config/scribe/config.toml:

[scribe]
base_url = "http://127.0.0.1:18083/v1"   # llama.cpp / Ollama / LM Studio / cloud
model = "default"                         # auto-detects the loaded model
api_key = "not-needed"                    # set a real key for cloud providers

Or use environment variables:

export SCRIBE_BASE_URL=http://localhost:11434/v1   # e.g. Ollama
export SCRIBE_MODEL=gemma4:12b
export SCRIBE_API_KEY=sk-...                       # cloud providers only

Full provider guide โ€” llama.cpp, Ollama, LM Studio, OpenRouter/Groq, plus a recipe for Gemma 4 12B with 128k context on a 12 GB GPU: docs/providers.md.

Web search needs no setup (DuckDuckGo). For Brave Search, set BRAVE_API_KEY or brave_api_key under [scribe].

CLI Commands

scribe-llm chat                    # Interactive TUI chat (streaming by default)
scribe-llm chat --textual          # Full-screen Textual UI (experimental)
scribe-llm chat --resume TAG       # Resume a past session (no TAG = last one)
scribe-llm web                     # Book Studio web UI at http://localhost:8765 (localhost-only by default)
scribe-llm web --host 0.0.0.0      # Expose on the network (prints a warning โ€” the UI has a shell terminal)

scribe-llm memory recall "query"  # Recall from semantic memory
scribe-llm rag search "query"     # Hybrid search (FTS5 + vectors); --semantic-only to opt out
scribe-llm rag ask "question"     # Grounded Q&A โ€” answers cite sources or refuse
scribe-llm rag reindex             # Rebuild the lexical (FTS5) index
scribe-llm session last            # Show last session
scribe-llm session list            # List all sessions
scribe-llm session search "query" # Full-text search across all session transcripts

scribe-llm init [DIR]              # Create a project-local vault (config + ./.scribe)
scribe-llm discover [--tailscale]  # Find OpenAI-compatible model servers
scribe-llm compare "q" --a M1 --b M2  # Blind A/B two models on one prompt
scribe-llm bench [--fitness|--spi] # Quality gate: judge fitness + SPI grounding
scribe-llm trace [ID] [--json]     # Show a session's ORORO trace

scribe-llm pulse                   # Record one heartbeat (wire to a systemd timer)
scribe-llm diary                   # Reflect on today's sessions
scribe-llm remember "fact"        # Add a durable fact to the WorldModel

scribe-llm config show             # Show current config
scribe-llm status [--json]         # System status (--json = machine-readable contract)
scribe-llm evolve eval             # Run the held-out fitness suite (Phase 0)

scribe-llm mail send "Subj" "Body" # Email yourself a notification
scribe-llm mail watch              # Accept commands by email (see below)

Email bridge

Scribe can email you results and accept commands by email โ€” using only the Python standard library (no extra dependencies).

[scribe.email]
enabled = true
address = "you@gmail.com"
approved_sender = "you@gmail.com"   # the ONLY address allowed to command Scribe
secret = "pick-a-token"             # must appear in command subjects
export SCRIBE_EMAIL_PASSWORD="your-gmail-app-password"   # never in the config file

scribe-llm mail send "Done" "The report is ready."   # send a notification
scribe-llm mail watch                                 # poll inbox, run commands, reply

To run a command, email yourself with the secret in the subject:

Subject: [scribe:pick-a-token] summarize the notes in research/

Scribe runs it with the sandboxed workspace tools (read/write/list files, no shell) and replies with the answer.

Security: commands are accepted only when both the sender matches approved_sender and the subject carries [scribe:secret]. Since From: headers can be spoofed, the secret is the real gate โ€” leave it empty to keep command intake off (sending still works). Gmail requires an App Password (with 2-Step Verification enabled).

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚              SCRIBE TUI                  โ”‚
โ”‚           (Rich-based interface)          โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚              CORE KERNEL                 โ”‚
โ”‚  Session Manager โ”‚ Skills โ”‚ Config       โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚           LLM ADAPTER LAYER              โ”‚
โ”‚    OpenAI-compatible (llama.cpp)         โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚             MEMORY LAYER                 โ”‚
โ”‚  SME (cross-session) โ”‚ RAG (documents)  โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚              TOOLS LAYER                 โ”‚
โ”‚   web_search โ”‚ web_fetch โ”‚ bash         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Philosophy

Language games (Wittgenstein-inspired). Each command word has a fixed, explicit meaning, so the model knows exactly what each action means. Reasoning, when enabled, stays in a <think> block and never leaks into the answer; by default Scribe answers directly.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

scribe_llm-1.6.0.tar.gz (252.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

scribe_llm-1.6.0-py3-none-any.whl (201.4 kB view details)

Uploaded Python 3

File details

Details for the file scribe_llm-1.6.0.tar.gz.

File metadata

  • Download URL: scribe_llm-1.6.0.tar.gz
  • Upload date:
  • Size: 252.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for scribe_llm-1.6.0.tar.gz
Algorithm Hash digest
SHA256 ff61ad0a09c24dc9385b5e4e4c478b554a9138c6359656e46092747002734b7b
MD5 30159e871957913ac7fc9f9e8d362ae3
BLAKE2b-256 1e377a98e4ef8b2d83881b0fc0e5838e1ff749605100469ed105502e45eb72f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for scribe_llm-1.6.0.tar.gz:

Publisher: publish.yml on pedjaurosevic/scribe-llm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file scribe_llm-1.6.0-py3-none-any.whl.

File metadata

  • Download URL: scribe_llm-1.6.0-py3-none-any.whl
  • Upload date:
  • Size: 201.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for scribe_llm-1.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a0f504a1cbfee53c15e18fc226bf59b40cdb4afa8859c695dbdc5f4611cf8dab
MD5 a99a66b715395961339d7a29d71e49b0
BLAKE2b-256 9f3d9a6f9ecd8033945f6583f2daba2f7eddaad1a5c1d55f4247fbe1582e152c

See more details on using hashes here.

Provenance

The following attestation bundles were made for scribe_llm-1.6.0-py3-none-any.whl:

Publisher: publish.yml on pedjaurosevic/scribe-llm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page