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.0.0.tar.gz (219.4 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.0.0-py3-none-any.whl (174.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: scribe_llm-1.0.0.tar.gz
  • Upload date:
  • Size: 219.4 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.0.0.tar.gz
Algorithm Hash digest
SHA256 dcc843c13e6642e97dfc4d8f6e19c6b258666a194bf18e8a57daba151184f48c
MD5 8ce1cf70c499dcc86bee5c26f70386a1
BLAKE2b-256 8b22b6cc9cecf902aa577af027fca7bb11088b0ab26b4f1676b66e5408e64e51

See more details on using hashes here.

Provenance

The following attestation bundles were made for scribe_llm-1.0.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.0.0-py3-none-any.whl.

File metadata

  • Download URL: scribe_llm-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 174.0 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.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 edb2c08ac350ce4efeeba0438c646dca1371b91586ee34f2dbfd3def640bbf2e
MD5 c48946618967f0e55f057d65f6464343
BLAKE2b-256 b623fcbccc9b771ac969888fbc7bf840a525e421c5fb2034160a8fd1fc653b0d

See more details on using hashes here.

Provenance

The following attestation bundles were made for scribe_llm-1.0.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