Universal TUI agent for autonomous research and writing, powered by llama.cpp
Project description
Scribe
๐ English ยท ็ฎไฝไธญๆ
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:
- 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)
- 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) - Grounding is measured, not asserted.
scribe benchreports 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 benchruns a judge-scored fitness suite and the deterministic SPI grounding metric - Safe Code Mode โ
/codewith a destructive-command gate, Python AST gate, bubblewrap sandbox, and git checkpoint/rollback - Internet Research โ
web_search+web_fetchtools; 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 wiki distillcurates 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 status --jsoncontract - Project Vaults โ
scribe initgives 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` command
The PyPI distribution is named
scribe-llm(the import package and CLI stayscribe).
From source (๐ง Linux / ๐ macOS)
# Clone the repository
git clone https://github.com/pedjaurosevic/scribe-ai.git
cd scribe-ai
# Run the install script: installs the package (editable), creates the
# config, and scaffolds ~/scribe-workspace.
./scripts/install.sh
๐ช Windows (WSL)
scribe chat and the scribe 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).
- Open your WSL terminal (e.g., Ubuntu).
- Run the Linux installation commands shown above.
- 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 pullupdates Scribe in place.
Quick Start
- Start your llama-server:
./scripts/start-server.sh
- Start Scribe:
scribe chat
- 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 chat # Interactive TUI chat (streaming by default)
scribe chat --textual # Full-screen Textual UI (experimental)
scribe chat --resume TAG # Resume a past session (no TAG = last one)
scribe web # Book Studio web UI at http://localhost:8765 (localhost-only by default)
scribe web --host 0.0.0.0 # Expose on the network (prints a warning โ the UI has a shell terminal)
scribe memory recall "query" # Recall from semantic memory
scribe rag search "query" # Hybrid search (FTS5 + vectors); --semantic-only to opt out
scribe rag ask "question" # Grounded Q&A โ answers cite sources or refuse
scribe rag reindex # Rebuild the lexical (FTS5) index
scribe session last # Show last session
scribe session list # List all sessions
scribe session search "query" # Full-text search across all session transcripts
scribe init [DIR] # Create a project-local vault (config + ./.scribe)
scribe discover [--tailscale] # Find OpenAI-compatible model servers
scribe compare "q" --a M1 --b M2 # Blind A/B two models on one prompt
scribe bench [--fitness|--spi] # Quality gate: judge fitness + SPI grounding
scribe trace [ID] [--json] # Show a session's ORORO trace
scribe pulse # Record one heartbeat (wire to a systemd timer)
scribe diary # Reflect on today's sessions
scribe remember "fact" # Add a durable fact to the WorldModel
scribe config show # Show current config
scribe status [--json] # System status (--json = machine-readable contract)
scribe evolve eval # Run the held-out fitness suite (Phase 0)
scribe mail send "Subj" "Body" # Email yourself a notification
scribe 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 mail send "Done" "The report is ready." # send a notification
scribe 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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scribe_llm-0.4.1.tar.gz.
File metadata
- Download URL: scribe_llm-0.4.1.tar.gz
- Upload date:
- Size: 184.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8e54a6b7212be6217b06fce8c45a609ef24a740f9ec36e7746669565424774f
|
|
| MD5 |
b00a0903f98e51b10dd1a2195760a0cd
|
|
| BLAKE2b-256 |
eef235de2e731725c7cca0acc26f2820be161a51a70d7782cb654ecf329a71c5
|
Provenance
The following attestation bundles were made for scribe_llm-0.4.1.tar.gz:
Publisher:
publish.yml on pedjaurosevic/scribe-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scribe_llm-0.4.1.tar.gz -
Subject digest:
c8e54a6b7212be6217b06fce8c45a609ef24a740f9ec36e7746669565424774f - Sigstore transparency entry: 1835314175
- Sigstore integration time:
-
Permalink:
pedjaurosevic/scribe-ai@e9dac97459b9746553e9cf592c920e7cff920963 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/pedjaurosevic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e9dac97459b9746553e9cf592c920e7cff920963 -
Trigger Event:
release
-
Statement type:
File details
Details for the file scribe_llm-0.4.1-py3-none-any.whl.
File metadata
- Download URL: scribe_llm-0.4.1-py3-none-any.whl
- Upload date:
- Size: 144.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f7849cc8f899bb9b443e01f273728a8d0458771ecd843b1aa57e7c9d58e8a58
|
|
| MD5 |
c40034ce8ab5829c743ab42118251d13
|
|
| BLAKE2b-256 |
64f3de78ecff1771ed603cee0f294f26832c5f186e150c8646952c53e0c34ef8
|
Provenance
The following attestation bundles were made for scribe_llm-0.4.1-py3-none-any.whl:
Publisher:
publish.yml on pedjaurosevic/scribe-ai
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scribe_llm-0.4.1-py3-none-any.whl -
Subject digest:
0f7849cc8f899bb9b443e01f273728a8d0458771ecd843b1aa57e7c9d58e8a58 - Sigstore transparency entry: 1835314322
- Sigstore integration time:
-
Permalink:
pedjaurosevic/scribe-ai@e9dac97459b9746553e9cf592c920e7cff920963 -
Branch / Tag:
refs/tags/v0.4.1 - Owner: https://github.com/pedjaurosevic
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e9dac97459b9746553e9cf592c920e7cff920963 -
Trigger Event:
release
-
Statement type: