Skip to content

NiuTrans/ToFu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Tofu logo
Tofu
豆腐 β€” Self-Hosted AI Assistant

CI Python SQLite PostgreSQL optional License Platform

πŸ‡¨πŸ‡³ δΈ­ζ–‡ζ–‡ζ‘£

Main Interface


What is Tofu?

Tofu is a fully self-hosted AI assistant you run with a single command. It connects to any OpenAI-compatible LLM and gives you a complete AI workspace β€” from simple Q&A to autonomous multi-step agents that can search the web, edit your codebase, read papers, control your browser, and collaborate as a team of specialist agents.

Everything runs on your machine. Your data never leaves your infrastructure. One command and you're live.

What makes Tofu different:

  • One command, everything included β€” the installer sets up the runtime, dependencies, database, and browser engine for you. No Docker required (though it's supported), no manual database setup, no config files to hand-edit.
  • Bring any model β€” OpenAI, Anthropic, Gemini, DeepSeek, Qwen, GLM, local models via Ollama/vLLM, or even your existing Claude Pro/Max / ChatGPT subscription logged in directly. Add several keys and Tofu rotates and load-balances across them automatically.
  • A real agent, not just a chat box β€” it can run multi-step tasks on its own: search, read, write code, run commands, generate images, and check its own work with a Planner β†’ Worker β†’ Critic loop.
  • Truly yours β€” self-hosted, MIT-licensed, no telemetry. Your conversations, keys, and files stay on your infrastructure.
  • Everything is also an API β€” every feature in the UI is a documented HTTP endpoint, so you can script Tofu or plug it into other tools (see Headless API).

Looking to drive Tofu from an AI agent or coding assistant? This README is written for people. There's a separate set of machine-facing materials β€” see For AI Agents & Developers at the bottom.


Quick Start

Pick the row that matches your OS. Each one ends with a running server on http://localhost:15000.

OS What to do
Windows Download Tofu-Setup-x.y.z-win64.exe from the latest release and double-click.
Linux / macOS curl -fsSL https://raw.githubusercontent.com/rangehow/ToFu/main/install.sh | bash
Docker git clone https://github.com/rangehow/ToFu.git && cd ToFu && docker compose up -d

That's it. Each path handles conda/runtime, dependencies, the database, the browser engine, and starts the server β€” no flags, no follow-up steps.

Need to pre-set an API key, change the port, or recover from a failed install? See docs/INSTALL.md for all flags and troubleshooting recipes.


Connect Your LLM

Provider Settings

Click βš™οΈ Settings β†’ πŸ”— Providers and add your API keys. Tofu works with any OpenAI-compatible API:

Provider Setup
OpenAI, Anthropic, Amazon Bedrock, Google Gemini, DeepSeek, Qwen, MiniMax, GLM, Doubao, Mistral, Grok, Baidu Qianfan, OpenRouter Click ⚑ Add from template β€” one click
Ollama, vLLM, or any local model server Add as custom provider with your local endpoint
Azure OpenAI Template available with deployment-specific base URL

Multiple keys per provider β€” add several API keys and Tofu automatically rotates between them when one hits rate limits. Across providers, the smart dispatcher routes requests based on real-time latency scoring and error-rate tracking.

Or set environment variables for headless/Docker setups:

export LLM_API_KEY=sk-xxx
export LLM_BASE_URL=https://api.openai.com/v1
export LLM_MODEL=gpt-4o

Headless API

Everything you can do in the UI is also exposed as a documented HTTP API, so you can drive Tofu from scripts, agents, or your own apps without rendering the web UI.

Mounts:

Prefix Surface
/api/v1/* Tofu native β€” full feature parity with the UI (chat, conversations, tasks, agents, capabilities, keys, usage, billing, …)
/v1/... OpenAI compat β€” chat/completions, models, embeddings (drop-in for the OpenAI SDK)
/v1/messages Anthropic compat β€” Messages API (drop-in for the Anthropic SDK)
/metrics Prometheus exposition (admin-scoped)

Self-description: /api/openapi.json and /api/openapi.yaml (OpenAPI 3.1), Swagger UI at /api/docs, ReDoc at /api/redoc.

Manage keys in Settings β†’ πŸ”‘ API Keys: mint, scope (chat/admin/etc.), set per-key RPM and TPD limits, revoke, view a 30-day usage chart per key. Idempotency-Key is supported on POSTs (24-hour cache, salted by principal). Standard rate-limit headers (X-RateLimit-*, Retry-After) are returned on every response.

Client SDKs ship in clients/:

# Python β€” sync `Tofu` class + `tofu` CLI
cd clients/python && pip install -e ".[cli]"
export TOFU_API_KEY=tofu_admin_xxx TOFU_BASE_URL=http://localhost:15000
tofu chat "hello"

# TypeScript β€” Node 18+, browsers, Cloudflare Workers, Vercel Edge, Deno, Bun
cd clients/typescript && npm install

Or use any OpenAI / Anthropic SDK directly by pointing it at your Tofu base URL with your tofu_admin_* key as the API key.


Multi-Tenant Relay (paid mode)

When auth_mode=multi-user, Tofu turns into a paid AI relay station β€” one self-hosted instance, many users, each with their own wallet, billed against your upstream LLM costs.

What lights up automatically when you flip the mode (no-op in open/private):

  • Per-user wallets in micro-credits (1 credit = 1,000,000 Β΅ β‰ˆ US $0.001), backed by an append-only ledger as the source of truth β€” no floats, no rounding bugs.
  • Atomic reserve / settle on every chat request β€” pre-flight 402 on insufficient funds, post-flight settlement of actual token usage; a background janitor sweeps stale reservations every 30 minutes.
  • Customer pages β€” /login, /signup, and /dashboard (Wallet, Keys, Usage, Docs, Account). Signup gating + welcome credit in data/config/relay.json.
  • Payments β€” Stripe webhooks and Alipay async-notify, idempotent on (provider, provider_id). Configure credentials in data/config/payments.json.
  • Redeem codes β€” generate batches, hand them to users, redeem to wallet.
  • Pricing table β€” per-model unit prices (input/output/cache) hot-reloaded from data/config/pricing.json, with family-prefix fallback and an admin-tunable margin.
  • Admin console β€” a standalone /admin dashboard (Users, Pricing, Redeem Codes, Payments) reachable only with an admin-scoped key under multi-user mode.

Everything is implemented in lib/billing/ and routes/api_v1/billing.py; switch back to open or private and the tables stay empty, the customer pages stop being served, and the gate behaves as in the previous section.


Features

πŸ’¬ Chat with Any Model

Chat Interface

The core experience: pick a model from the dropdown, type a message, get a streaming response. But Tofu goes much further than a basic chat UI.

When you want to try different models on the same question β€” switch models mid-conversation. Each message remembers which model generated it, so you can compare outputs naturally. Branch any assistant message to explore alternative responses from different models or with different parameters, all in the same thread.

When you're working in Chinese but need English sources β€” enable auto-translation per conversation. Your Chinese questions are translated to English for the model, and the English response is translated back. The original is always preserved β€” click to toggle. For faster, cheaper translation, connect a dedicated machine translation provider instead of using the LLM.

When conversations get long and you lose context β€” Tofu's 3-layer compaction pipeline handles this automatically:

  1. Micro-compaction (zero cost): old tool results are replaced with summaries, keeping only the recent "hot tail"
  2. Structural truncation: thinking blocks, oversized arguments, and redundant screenshots are trimmed
  3. LLM summary (force-triggered): when context pressure is high, a cheap model evaluates each turn for relevance and compresses accordingly

When you want to organize your conversations β€” create folders in the sidebar to group related threads. Drag conversations between folders, or leave them unfiled.

When you'd rather read the reasoning in order β€” finished multi-tool replies render as an interleaved timeline: each tool call appears inline right next to the thinking and narration that led to it, so you follow the assistant's actions in the order they actually happened instead of three separate "all thinking / all tools / all answer" blocks. On by default; toggle it in Settings β†’ General β†’ "Per-tool inline timeline."

When a conversation runs long β€” a context health bar shows how much of the model's window you're using, and Tofu automatically compacts older turns so the thread keeps going without hitting the limit. You can open the compaction viewer to inspect exactly what was summarized, so nothing feels lost.


πŸŽ™οΈ Voice Input (Speech-to-Text)

When typing is slower than talking β€” dictate straight into the message box.

How to use: Click the mic button next to the composer, allow microphone access, speak, then click again to stop. Your speech is transcribed and inserted at the cursor β€” it's never auto-sent, so you review and edit before sending. It's dictation, not a spoken conversation.

The mic only appears when your browser supports recording and a speech-to-text model is configured β€” otherwise it stays hidden. To enable it, add a provider whose model has the transcription (or audio_chat) capability in Settings β†’ Providers:

Provider Models
OpenAI gpt-4o-transcribe, gpt-4o-mini-transcribe, whisper-1
Groq whisper-large-v3-turbo, whisper-large-v3 (fast, low cost)
Omni chat models Gemini / LongCat and similar, via audio_chat

Optional env tuning: TOFU_AUDIO_MAX_BYTES (default 25 MB), TOFU_AUDIO_MAX_DURATION_S (default 600 s). There's no separate voice tab β€” availability is driven entirely by the configured model.


πŸ” Web Search & Content Fetching

When the assistant needs current information β€” today's news, documentation updates, API references β€” it can search the web and read pages.

How it works: Enable the πŸ” toggle in the tool bar. The assistant searches across multiple engines in parallel (DuckDuckGo, Brave, Bing, SearXNG), deduplicates results, then fetches and extracts the most relevant pages. A content filter (LLM-powered, optional) strips navigation, ads, and boilerplate.

When you paste a URL β€” the assistant fetches it directly, handling HTML, PDFs, and plain text. For pages behind authentication, use the browser extension instead (see below).

Configuration β€” in Settings β†’ πŸ” Search & Fetch:

  • How many results to auto-fetch (default: 6)
  • Per-page timeout and max characters
  • Blocked domains the fetcher should never visit
  • Whether to use the LLM content filter (disable for speed)

πŸ› οΈ Tool Calling & Autonomous Agents

This is where Tofu becomes more than a chatbot. When you enable tools, the assistant can take multi-step actions autonomously β€” searching the web, running code, editing files, generating images β€” chaining these together to solve complex tasks.

Built-in tools:

Tool What it does
web_search Search the web (multi-engine parallel)
fetch_url Read any URL (HTML, PDF, plain text)
run_command Execute shell commands
generate_image Create or edit images (Gemini, GPT-image)
ask_human Pause and ask you a question mid-task
list_conversations / get_conversation Reference past conversations
create_memory / update_memory / delete_memory Save knowledge for future sessions
check_error_logs / resolve_error Inspect and resolve errors in project logs
Browser tools Control your browser (via extension)
Desktop tools Control your local machine (via agent)
Project tools Browse, search, edit any codebase
Scheduler tools Create recurring automated tasks
Swarm tools Spawn parallel sub-agents

When you need a quick answer with live data β€” "What's the current price of NVDA?" The assistant searches, fetches the relevant page, and answers.

When you need a multi-step workflow β€” "Research the top 5 React state management libraries, compare them, and write a recommendation document." The assistant plans the steps, executes searches, reads documentation, and synthesizes the result β€” all autonomously.

When the task is too complex for one pass β€” enable Endpoint mode (Planner β†’ Worker β†’ Critic). A planner rewrites your request into a structured brief with acceptance criteria, a worker executes it, and a critic reviews against the checklist. If the result doesn't pass, the critic sends feedback and the worker iterates β€” up to 10 rounds.

When something fails β€” the assistant retries with exponential backoff. If the primary model fails entirely, it automatically falls back to a configured backup model and retries.


πŸ’» Project Co-Pilot

Point Tofu at any codebase and it becomes a coding assistant that can read, search, edit, and run commands in your project.

Getting started: Click Project in the sidebar, enter the path to your codebase (e.g. /home/you/myproject). The assistant gains these tools:

Tool What it does
list_dir Browse directory structure with file sizes and line counts
read_files Read files (supports images, PDFs, Office docs, code β€” with line numbers)
grep_search Search across files with ripgrep (regex, context lines, count mode)
find_files Find files by glob pattern
write_file Create or overwrite files
apply_diff Surgical search-and-replace edits (batch mode for multiple edits)
insert_content Add code before/after an anchor without replacing it
run_command Execute shell commands in the project directory

When you need to understand a new codebase β€” "Give me an overview of this project's architecture." The assistant explores the directory tree, reads key files, and maps out the structure.

When you need to fix a bug β€” "The login page shows a blank screen after submitting." The assistant greps for relevant code, reads the components, identifies the issue, and applies a fix with apply_diff.

When you want safe experimentation β€” every file modification is tracked per-conversation with full undo support. Click the undo button to roll back any changes the assistant made.

Multi-root projects β€” add multiple directories as roots (e.g. frontend + backend repos). The assistant resolves namespaced paths across all roots.

Smart token management β€” the content_ref mechanism lets the assistant write a previous tool result to a file without re-generating it. This saves significant tokens on large files.


🧩 Project Brain β€” coordinate many conversations on one project

When you have several conversations open on the same project, the Project Brain makes them act like one coordinated team instead of separate, forgetful chats. Each conversation can see what the others are doing, share the same goals and decisions, and avoid stepping on each other's work β€” and the project can even pick up pending work on its own, all while staying fully visible and controllable by you.

How you use it: it's automatic whenever a conversation is in project mode (attached to a project folder) β€” no toggle to flip. You watch and steer it through the slide-in Project Brain panel, opened from the project bar (live activity, charter, board, and status tabs), plus a one-line status headline in the collab-bar. The one thing that needs you: agents can only propose changes to the shared charter β€” you click Commit or Reject.

Capability What it gives you
Charter A shared north-star doc + committed decisions every conversation follows. Changes are human-approved.
Board & epics A kanban of claimable workstreams so conversations divide work and don't duplicate it.
Activity feed A live pulse of what every conversation is doing right now.
Peer messaging One conversation can send another an advisory nudge β€” rate-limited, never interrupts mid-work.
Path leases A conversation reserves the files it's editing so siblings hold off, preventing edit collisions.
Status lane Ask the project "where are we? are we drifting?" and get a synthesized answer, plus a watch-list of concerns the brain revisits over time.
Autonomous dispatch Idle projects self-start ready, unblocked work with no hand-off.

πŸ€– Multi-Agent Swarm

Some tasks are too big for a single agent. The swarm system lets a master orchestrator plan sub-tasks and delegate them to specialist agents running in parallel.

When to use it: "Refactor this microservice into 3 separate services, update the API docs, and write migration scripts." Instead of one agent doing everything sequentially, the master spawns parallel agents for each sub-task.

How it works:

  1. The master LLM plans sub-tasks and assigns roles (coder, researcher, writer, reviewer…)
  2. A streaming DAG scheduler launches agents as soon as their dependencies complete β€” no waiting for entire waves
  3. Agents share data through an artifact store (key-value pairs visible to all agents)
  4. As agents complete, the master reviews results and can spawn follow-up agents
  5. Final results are synthesized into a coherent output

Agent roles β€” each agent gets role-specific system prompts, model tiers, and scoped tool access. A "researcher" agent gets search tools; a "coder" agent gets project tools; a "reviewer" gets read-only access.

Rate limiting β€” a shared semaphore prevents agents from overwhelming the LLM API with concurrent requests. Automatic exponential backoff on 429s.


🌐 Machine Translation

When you translate frequently and want faster, cheaper results β€” connect a dedicated machine translation provider instead of using the LLM for translation.

How it works: By default, Tofu uses a cheap LLM model for auto-translation (which understands context but is slower). When you configure a machine translation provider, all translation requests are routed directly to the MT API β€” typically 3–5Γ— faster and 10–100Γ— cheaper than LLM-based translation, with no prompt overhead.

Setup: Go to Settings β†’ 🌐 ηΏ»θ―‘ (Translation), enable machine translation, and choose a provider:

Provider Description How to get API Key
NiuTrans (小牛翻译) Chinese MT specialist, supports 300+ language pairs niutrans.com/cloud/overview
Custom Any compatible REST API Enter your endpoint and credentials

NiuTrans is the default provider with excellent Chinese↔English quality. Click "η”³θ―· API Key" in the settings card to register.

Fallback behavior:

  • No MT configured β†’ uses the cheap LLM model (default, works out of the box)
  • MT configured β†’ uses the MT API; if it fails, automatically falls back to LLM translation
  • Code block protection β†’ fenced (```...```) and inline (`...`) code blocks are extracted before translation and restored after, preventing MT from corrupting code

πŸ”€ Subscription Login (Claude Pro/Max Β· ChatGPT)

Already paying for Claude Pro/Max or a ChatGPT subscription? Log in with it and Tofu uses that subscription as a model provider β€” no separate API key, billed under your existing plan.

How it works: Go to Settings β†’ Providers and click 登录 Claude / 登录 ChatGPT. Tofu runs a PKCE OAuth flow (lib/oauth/), stores the token, and lib/oauth/outbound.py bridges the logged-in subscription into a managed provider slot β€” resolved per-request into a live token plus the required client-identity headers. From then on the subscription behaves like any other provider in the dispatcher (slot rotation, fallback, latency scoring all apply).

  • Claude requests go to the Anthropic Messages API with the Claude-Code identity headers.
  • ChatGPT (Codex) requests are auto-converted to the Responses API format.

This is a normal in-dispatch provider, not a CLI subprocess. (An earlier CLI-subprocess "backend switching" mechanism β€” lib/agent_backends/ β€” was removed in 2026-06 in favour of this simpler subscription-as-provider path.)


🌐 Browser Extension

When you need the assistant to read pages that require login β€” internal dashboards, JIRA tickets, authenticated admin panels β€” the browser extension bridges your real browser session to Tofu.

Setup:

  1. Go to chrome://extensions β†’ Enable Developer Mode
  2. Load unpacked β†’ select the browser_extension/ folder
  3. Click the extension icon β†’ enter your Tofu server URL

What it can do:

Tool Use case
browser_list_tabs See all your open tabs
browser_read_tab Extract text content (with optional CSS selector)
browser_screenshot Capture a visual screenshot
browser_navigate Open a URL
browser_click Click elements by selector or text
browser_type Type into input fields
browser_execute_js Run custom JavaScript for data extraction
browser_get_interactive_elements Discover clickable/typeable elements
browser_get_app_state Access Vue/React internal state

When the page uses Canvas/SVG rendering (charts, DAG diagrams) β€” DOM text extraction returns nothing. Use browser_screenshot for visual analysis, browser_get_app_state for data, or browser_execute_js for custom extraction.

Multiple browsers can connect simultaneously with independent command queues β€” useful if you have work and personal browser profiles.


πŸ–₯️ Desktop Agent

When you need the assistant to interact with your local machine beyond the browser β€” take full-screen screenshots, read/write local files, automate GUI clicks, manage clipboard.

Setup:

pip install pyautogui pillow psutil
python lib/desktop_agent.py --server http://your-server:15000 --allow-write --allow-exec

The agent connects to your Tofu server and exposes tools for file operations, clipboard, screenshots, GUI automation (pyautogui), and system info. All dangerous operations require explicit --allow-write / --allow-exec flags.


πŸ“„ Paper Reader (beta)

When you're reading research papers β€” arXiv PDFs, conference proceedings, internal whitepapers β€” Paper Reader turns Tofu into a dedicated research companion.

How to use: Click the πŸ“„ Paper button in the sidebar. The screen splits: PDF on the left, chat + notes on the right. Upload a PDF or paste an arXiv URL (arxiv.org/abs/XXXX.XXXXX) β€” Tofu fetches, parses, and indexes the full text so the assistant can answer questions grounded in the paper.

What it does:

  • Grounded Q&A β€” ask "what's the ablation result in Table 3?" or "explain Section 4.2" β€” the assistant cites the specific passage it's drawing from
  • Paper library β€” the left sidebar shows all papers you've read, grouped by date; switch between them without losing conversation context
  • Side-by-side reading β€” scroll the PDF while chatting; the assistant sees the page you're on
  • Notes tab β€” drop your own notes alongside the paper; they persist across sessions

⚠️ Beta: Paper Reader is actively being iterated on. Feedback welcome on GitHub Issues.

Optional: Layout-aware PDF parsing with Docling

The default PDF pipeline (pymupdf4llm) does a good job on most papers, but struggles with borderless tables and complex math formulas that are common in ML / theoretical CS papers. For those, Tofu can route through Docling (IBM) β€” a layout-aware model that uses TableFormer for tables and an internal equation model for math, producing much cleaner Markdown.

Trade-off: Docling pulls in PyTorch + ~2 GB of model weights, so it's opt-in:

pip install docling --extra-index-url https://download.pytorch.org/whl/cpu

Then enable it by setting PDF_TEXT_MODE=structured in your .env, or per-request via the form field textMode=structured on /api/pdf/parse. If Docling isn't installed when structured is requested, the server falls back to pymupdf4llm automatically β€” your uploads never break.


πŸ–ΌοΈ Image Generation

When you need visual content β€” illustrations, diagrams, logos, edited photos β€” the assistant can generate images mid-conversation.

How to use: Enable the πŸ–ΌοΈ toggle in the tool bar and describe what you want. The assistant calls generate_image with a detailed prompt.

  • Create from scratch β€” "Draw a minimalist logo of a mountain with a sunrise"
  • Edit existing images β€” upload an image and say "change the background to a beach sunset"
  • Save to project β€” specify output_path to save directly into your codebase
  • SVG conversion β€” add svg: true to auto-trace the generated PNG into a scalable vector

Multi-model dispatch cycles across Gemini and GPT image models, automatically retrying on rate limits.


🎨 Artifacts (live canvas)

When the assistant produces something you'd rather see than scroll past β€” a full HTML page, an SVG diagram, a React-style snippet, or a long document β€” it becomes an Artifact.

How it works: A clickable chip appears next to the message; open it and Tofu renders the content live in a side panel β€” HTML/SVG in a sandboxed iframe, Markdown safely sanitized. Every artifact is versioned, so you can flip between revisions, pin favorites, browse them all in the per-conversation library, and export to PDF. Great for building a small web page, a chart, or a formatted report and iterating on it in place.


πŸ”— MCP (Model Context Protocol)

When you want to connect external tool servers β€” GitHub, databases, custom APIs β€” MCP bridges them into Tofu's tool system.

How it works: MCP servers run as subprocesses and communicate via stdio/SSE (JSON-RPC 2.0). Tofu translates their tools into OpenAI function-calling format, so the LLM can discover and invoke them alongside native tools.

Setup: Go to Settings or configure in data/config/mcp_servers.json:

{
  "github": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-github"],
    "env": { "GITHUB_TOKEN": "ghp_xxx" }
  }
}

The assistant can then call tools like mcp__github__create_issue, mcp__github__search_code, etc. β€” any MCP-compatible server works.


β˜‘οΈ Daily Reports & My Day

Click the β˜‘οΈ My Day button in the sidebar to open your personal work journal β€” an LLM-powered daily dashboard.

When you want to see what you accomplished today β€” the LLM reads all your conversations for the day and clusters them into 5–15 coherent work streams (e.g. "Fix image rendering bug", "Deploy staging environment"), marking each as done, in progress, or blocked.

When you need tomorrow's plan β€” the LLM synthesizes 3–8 actionable TODO items from unfinished work. Each comes with a detailed prompt and recommended tool configuration. Click β–Ά to launch any TODO as a new conversation, pre-filled and ready to go.

Calendar view β€” month-at-a-glance with per-day conversation counts and cost heatmap. Click any date to view or generate its report.

To-do management β€” uncompleted TODOs carry forward to the next day. Add manual TODOs, toggle done/undone, or launch them as conversations. Cost tracking shows per-day and per-conversation spend in CNY.

Auto-backfill β€” a background scheduler generates yesterday's report on server boot if it's missing, and again daily at midnight.


πŸ• Scheduled Tasks

When you need something to run automatically β€” daily data pulls, periodic health checks, recurring reports β€” create a proactive agent that runs on a schedule.

How to use: Enable the πŸ• Scheduler toggle and ask: "Run a health check on my API every 6 hours" or "Every morning at 9am, summarize overnight GitHub issues." The assistant creates a cron-like task.

Task types: Shell commands, Python scripts, or LLM prompts β€” all with full tool access.

Manage tasks: Click the SCHEDULER badge in the top status bar to see all active proactive agents and their recent run logs.


πŸ”§ Self-Tuning (Daily Optimizer)

Tofu quietly watches how it's performing and proposes small improvements to itself β€” you stay in control of every change.

How it works: A nightly loop analyzes recent runs and drafts proposals (e.g. "block a spammy search domain," "adjust a default"). Click the OPTIMIZER badge in the top bar to review each one with its rationale, severity, and confidence β€” then approve, reject, revert, or hit Run now. Nothing is applied without your say-so (a small whitelist of safe tweaks can auto-apply, and everything is reversible). Turn it off entirely in Settings.


🐦 Feishu (Lark) Bot

When your team communicates in Feishu and you want AI assistance directly in group chats β€” Tofu connects as a Feishu bot via WebSocket.

Setup:

  1. Create an app at open.feishu.cn, enable Bot capability
  2. Go to Settings β†’ 🐦 Feishu β†’ enter App ID and App Secret
  3. The bot auto-connects on server restart

Features: Multi-turn conversations with full tool support (search, code, project), slash commands for model/mode switching, and conversation management β€” all within Feishu's native chat interface.


🧠 Memory System

When the assistant discovers something useful β€” a bug pattern, a project convention, your preferred coding style β€” it can save that knowledge as a memory for future sessions.

How it works: Project-scoped memories are Markdown files stored in .tofu/skills/ inside your project; global memories (shared across all projects) live in the server-side store data/memories/global/. The assistant creates them proactively or when you ask. In future conversations, relevant memories are automatically loaded into context.

Tools: create_memory, update_memory, delete_memory, merge_memories β€” the assistant manages its own knowledge base across sessions.

When to use: "Remember that our API always returns snake_case" β€” the assistant saves this convention and applies it in all future code generation for this project.


πŸ“š Skills Store

When you want to give the assistant reusable, packaged know-how β€” a set of instructions and helper scripts for a specific task β€” install a Skill.

How it works: Skills follow the open Claude / OpenClaw / AgentSkills format (a SKILL.md plus optional reference files and scripts). Go to Settings β†’ Skills to browse a Catalog of recommended packs (e.g. Anthropic's docx / xlsx / pdf / skill-creator skills) and install with one click, or drag-and-drop a local .zip. Installed skills appear under the Installed tab, where you can view or uninstall them. Bundled install.sh scripts are surfaced as hints β€” never auto-executed.


πŸ”Œ Conversation Branching

When you want to explore a different direction without losing the current thread β€” branch any assistant message.

How it works: Click the branch icon on any assistant message. A new branch opens inline, continuing from that point with its own independent history. Multiple branches can stream in parallel. Each branch can use a different model or parameters.

Use cases:

  • Compare how different models answer the same question
  • Try an alternative approach without losing the current one
  • Let one branch research while another branch implements

🐾 Tofu Pet (just for fun)

Switch to the Tofu theme and a little animated chibi-tofu mascot moves into the project bar. It wanders through a decorative scene with a real walk cycle and moods β€” thinking while a task loads, celebrating on success β€” and leaves interactive footstep effects (grass tufts, pool ripples, sky wisps). Use the Scene button (Meadow / Pool / Sky / Off) and Pet button (Tofu / Oneko) in the bar to customize it. It respects your OS "reduce motion" setting. Purely decorative β€” turn it off any time.


Settings Reference

All configuration is done through the βš™οΈ Settings panel (top-right gear icon). Changes save instantly β€” no restart needed.

Tab What you configure
βš™οΈ General Theme (Dark/Light/Tofu), temperature, max tokens, thinking depth, system prompt, per-tool inline timeline
πŸ”— Providers API keys, endpoints, model lists (incl. transcription/audio models), multi-key rotation, auto-discovery
πŸ“¦ Display Which models appear in dropdowns, default model, fallback model
πŸ” Search & Fetch Result count, timeouts, character limits, blocked domains, content filter
🌐 Translation Machine translation provider (NiuTrans / Custom), API key, endpoint
🌐 Network HTTP/HTTPS proxy, bypass domains
πŸ”€ Subscription Login Log in to Claude Pro/Max or ChatGPT and use it as a provider
🐦 Feishu App credentials, default project, allowed users
πŸ”— MCP Model Context Protocol servers (App-Store catalog + custom)
πŸ“š Skills Browse, install, and manage reusable Skill packs
🧠 Memory & Preferences Stored memories and your durable preference profile
πŸ”‘ API Keys Mint/scope/revoke headless API keys, per-key limits, auth mode
</> Advanced Price overrides, cache management, server info

Multi-tenant relay admin (Users, Pricing, Redeem Codes, Payments) now lives in a standalone /admin console rather than a Settings tab.

Environment Variables (fallback)

For headless/Docker setups, you can configure via environment variables instead of the Settings UI. Copy the template and edit:

cp .env.example .env
vim .env   # fill in your values

The .env.example file documents all supported variables. Key ones:

Variable Description Default
LLM_API_KEYS Comma-separated API keys (none)
LLM_BASE_URL API endpoint https://api.openai.com/v1
LLM_MODEL Default model gpt-4o
PORT Server port 15000
BIND_HOST Bind address 127.0.0.1 (loopback)
TOFU_AUTH_MODE Force auth mode and lock the UI: open / private / multi-user (file-driven)
TOFU_AUTO_KEY Set to 0 to skip first-boot admin-key bootstrap 1
TUNNEL_TOKEN DEPRECATED back-compat shim β€” use the API-keys system instead (disabled)
TRADING_ENABLED Enable trading module (1/0) 0
PDF_TEXT_MODE Default PDF text-extract strategy: rich (pymupdf4llm, default), structured (Docling; requires pip install docling), fast rich
PDF_VLM_BATCH_PAGES Pages per VLM call when VLM parsing is used (1–16) 4
PDF_VLM_MAX_WORKERS Cap on concurrent VLM calls (useful on shared keys to avoid 429 storms) unlimited

Priority: Settings UI > .env file > system environment > defaults. You can also export variables directly β€” .env is just a convenience.


Project Structure

β”œβ”€β”€ server.py                  Flask app entry, middleware, logging
β”œβ”€β”€ bootstrap.py               Auto-dependency repair (LLM-guided)
β”œβ”€β”€ index.html                 Main chat UI (single-page app)
β”‚
β”œβ”€β”€ lib/                       Core libraries
β”‚   β”œβ”€β”€ agent_core/            Reusable agent base (run loop, dispatch, TaskRuntime, push, profiles)
β”‚   β”œβ”€β”€ llm/                   LLM API client package (build_body / stream / cache / diagnostics)
β”‚   β”œβ”€β”€ llm_dispatch/          Multi-key multi-model smart dispatcher
β”‚   β”œβ”€β”€ database/              Dual backend β€” SQLite default, PostgreSQL auto-bootstrap
β”‚   β”œβ”€β”€ tasks_pkg/             Task orchestration & context compaction
β”‚   β”‚   β”œβ”€β”€ orchestrator.py    Main LLM ↔ tool loop
β”‚   β”‚   β”œβ”€β”€ executor.py        Tool execution engine
β”‚   β”‚   β”œβ”€β”€ endpoint.py        Planner β†’ Worker β†’ Critic loop
β”‚   β”‚   └── compaction/        3-layer context compaction (package)
β”‚   β”œβ”€β”€ tools/                 Tool definitions & schemas
β”‚   β”œβ”€β”€ swarm/                 Multi-agent orchestration
β”‚   β”œβ”€β”€ fetch/                 Content fetching & extraction
β”‚   β”œβ”€β”€ search/                Multi-engine web search
β”‚   β”œβ”€β”€ browser/               Browser extension bridge
β”‚   β”œβ”€β”€ project_mod/           Project co-pilot (scan, edit, undo)
β”‚   β”œβ”€β”€ memory/                Memory accumulation system
β”‚   β”œβ”€β”€ mcp/                   Model Context Protocol bridge
β”‚   β”œβ”€β”€ feishu/                Feishu bot integration
β”‚   β”œβ”€β”€ scheduler/             Task scheduling (cron, proactive agents)
β”‚   β”œβ”€β”€ image_gen.py           Image generation (multi-model dispatch)
β”‚   β”œβ”€β”€ mt_provider.py         Machine translation providers (NiuTrans, custom)
β”‚   β”œβ”€β”€ desktop_agent.py       Desktop automation agent
β”‚   └── ...
β”‚
β”œβ”€β”€ lib/conversations/         Project Brain β€” charter, board, feed, peer messaging, path leases, status lane
β”œβ”€β”€ routes/                    Quart Blueprints + routes/api_v1/ (headless API)
β”œβ”€β”€ lib/billing/               Multi-tenant relay billing (wallet, ledger, pricing, payments)
β”œβ”€β”€ lib/oauth/                 OAuth flows (Claude, Codex, PKCE, token store)
β”œβ”€β”€ lib/optimizer/             Nightly self-tuning loop (analyzer β†’ proposer β†’ applier)
β”œβ”€β”€ clients/                   Headless API SDKs (python/, typescript/)
β”œβ”€β”€ static/                    CSS, JS, icons
β”œβ”€β”€ browser_extension/         Chrome extension (Manifest V3)
β”œβ”€β”€ tests/                     Test suite (unit, API, E2E)
└── data/                      Runtime data (git-ignored)

Tofu runs on Quart (async Flask) via Hypercorn; existing sync route handlers run unchanged in a thread pool.


Platform Support

Feature Linux macOS Windows
Core chat & tools βœ… βœ… βœ…
SQLite (default, zero-config) βœ… βœ… βœ…
PostgreSQL auto-bootstrap (optional) βœ… βœ… βœ…
Project co-pilot βœ… βœ… βœ…
Shell commands βœ… βœ… βœ… (cmd.exe)
Desktop agent βœ… βœ… βœ…
Browser extension βœ… βœ… βœ…

Smoke test: python debug/test_cross_platform.py


Testing

# All tests
python tests/run_all.py

# Individual suites
python -m pytest tests/test_backend_unit.py
python -m pytest tests/test_api_integration.py
python -m pytest tests/test_visual_e2e.py

# Or via the Makefile (parallelized; tune with JOBS=N)
make test-unit        # fast unit tier
make test-api         # API integration tier
make test-frontend    # jsdom frontend suites
make test-all         # everything

Auth Modes & Security

Tofu has a tri-state auth model, persisted at data/config/auth.json and switchable from Settings β†’ πŸ”‘ API Keys (top of the tab):

Mode Gate Use case
open (DEFAULT) Pass-through; synthetic local-admin context Personal install, frontend-only, loopback-bound
private Bearer / x-api-key / cookie / ?token= required; HTML hint page on / Single multi-device operator
multi-user Same gate as private, plus per-user wallets + signup pages Paid relay station serving many users

Default bind is 127.0.0.1 β€” the API is not reachable from the LAN unless you pass --host 0.0.0.0 or BIND_HOST=0.0.0.0. Combined with open-by-default mode, personal use just works locally without exposure.

First-boot bootstrap (private/multi-user only) β€” when the api_keys store is empty and TUNNEL_TOKEN is unset, Tofu mints one tofu_admin_<hex> key on startup, prints the plaintext + a one-shot ?token=<...> URL to stderr, and writes the plaintext to data/config/.first_run_token (chmod 0600). Disable with TOFU_AUTO_KEY=0.

Token transports (priority): Authorization: Bearer β†’ x-api-key (Anthropic SDK) β†’ tofu_session HttpOnly cookie β†’ ?token= query string (consumed + stripped β†’ cookie, private mode only).

TOFU_AUTH_MODE=<mode> environment variable locks the mode β€” the UI radios are disabled and a 409 error_kind=env_locked is returned on PUT /api/v1/auth/mode.

Other security notes:

  • No secrets in source β€” all credentials loaded from environment variables or Settings UI.
  • Tool execution β€” the assistant can run shell commands and edit files; dangerous patterns are blocked, but use with appropriate caution.
  • Desktop agent β€” requires explicit --allow-write / --allow-exec flags.
  • TUNNEL_TOKEN is a deprecated back-compat shim and prints a warning at boot β€” migrate to the API-keys system.

For AI Agents & Developers

This README is written for people. If you're driving Tofu from a coding assistant, building on top of it, or contributing code, the machine-facing materials live here:

Document What it covers
CLAUDE.md Project intelligence & mandatory rules for AI-assisted code changes (logging discipline, code style, change-approval gates, the frontend/backend boundary).
JOURNAL.md The project's evolution journal β€” what was tried, why it changed, current status.
docs/ARCHITECTURE.md Full directory map + Mermaid architecture diagram (and docs/architecture.html for the visual version).
docs/HEADLESS_API.md Complete headless-API reference (the /api/v1/*, OpenAI, and Anthropic surfaces).
docs/CUSTOM_TOOLS.md Β· docs/TOOL_PLUGINS.md Adding your own tools and plugin blueprints.
docs/PROJECT_BRAIN.md Deep dive on cross-conversation coordination.
/api/openapi.json Β· /api/docs Live OpenAPI 3.1 spec + Swagger UI served by a running instance.

Contributing

See CONTRIBUTING.md for the full guide. Quick version:

  1. Fork β†’ feature branch
  2. python healthcheck.py && python tests/run_all.py
  3. Submit a pull request

License

MIT

About

Self-hosted AI assistant with tool use, multi-agent orchestration, coding copilot and a lightweight Flask + vanilla JS stack.

Resources

Contributing

Stars

121 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors