Introduction Download Documentation BAAM About GitHub
Get started

Getting started

Biorouter is a desktop research environment that connects local models, models hosted by your institution, and commercial AI models in one interface. It runs on your machine, stores its data as plain files on disk, and talks only to the provider you choose. Setup is a few minutes: download, put the included command line tool on your PATH if you want it, connect a provider, and start a session. This guide covers biorouter 1.91.2 on macOS, Windows, and Linux.

1

Download and install

Get the build for your platform from the Download page or from GitHub Releases. Install the newest release for the latest fixes.

  • macOS: open the .dmg and drag Biorouter to /Applications. A .zip is also published for the app's automatic updater.
  • Windows: unzip Biorouter-win32-x64-*.zip and run Biorouter.exe.
  • Linux desktop: install biorouter_*_amd64.deb (Debian/Ubuntu) or Biorouter-*-1.x86_64.rpm (Fedora/RHEL).
  • Linux without a desktop (servers, HPC nodes, containers): install the command line package biorouter-cli_*_amd64.deb or biorouter-cli-*-1.x86_64.rpm. It ships the biorouter CLI, the biorouterd daemon and the web interface, with no desktop app, so you can still work in a browser by running biorouter serve.
Node is not required to run the app. Biorouter's backend is a native Rust binary (Rust 1.92). You only need Node 24+ if you install an extension whose MCP server launches through npx.
2

Put the bundled CLI on your PATH

On macOS and Windows the biorouter command line tool ships inside the desktop app, so there is no separate CLI download. It shares the same config, sessions, and settings as the app.

  • From the app: accept the Install Biorouter CLI prompt on launch. One click symlinks the bundled binary onto your PATH.
  • From a terminal: run biorouter setup-path. If the target directory is not on your PATH, it prints the exact line to add.

On Linux, install the standalone biorouter-cli package instead of running setup-path. After a desktop upgrade on macOS or Windows, run biorouter setup-path again so your PATH points at the new binary.

3

Connect your first provider

Biorouter needs a provider to function and prompts you to pick one on first launch. Choose whichever fits your trust boundary:

  • UCSF researchers: choose Versa API Azure (UCSF ChatGPT, via Azure OpenAI) or Versa API Bedrock (Anthropic models hosted by UCSF, via Amazon Bedrock). Your data stays inside UCSF's tenant.
  • Everyone else: paste an API key for Anthropic, OpenAI, Google Gemini, or another commercial provider.
  • No setup, runs locally: pick Llama Server, the llama.cpp runtime included with Biorouter. It needs no key and no separate install. Model weights download once from Hugging Face, and nothing else leaves your machine.

From a terminal you can do the same with biorouter configure and selecting Configure Providers.

4

Start your first session

Type a message in the desktop chat, or open a terminal session:

biorouter session        # interactive terminal chat
biorouter run -t "Summarize ./notes.md in 5 bullets"   # one-shot, headless

Send a short test prompt to confirm the setup works. If Biorouter replies, you are ready.

To chat, share files and run agents with your lab, open Crew in the sidebar. See Crew.

Where your data lives

Biorouter keeps everything as plain files you can inspect, back up, and version. It follows the XDG layout, so the files are spread across three directories, not one: configuration under ~/.config/biorouter/, data under ~/.local/share/biorouter/, and state under ~/.local/state/biorouter/. The desktop app and the CLI share all three.

PathHolds
~/.config/biorouter/config.yamlProviders, models, extensions, and settings
~/.config/biorouter/workflows/ and skills/Installed workflows and skills
~/.local/share/biorouter/sessions/sessions.dbConversation history in a SQLite database
~/.local/state/biorouter/logs/Log files (check these first when something fails)

Run biorouter info to print the four paths as they resolve on your machine.

Secrets never touch config.yaml

API keys and credentials are written to your operating system's credential store (macOS Keychain, Windows Credential Manager, Linux Secret Service), not to any config file. See Vaulting and security below for how that works.

On Windows all three live under one root: %APPDATA%\Block\biorouter\, with config\ and data\ beneath it. Windows has no separate state directory, so logs sit under data\ there. The Electron app state lives separately at ~/Library/Application Support/Biorouter/ on macOS.

Using Biorouter

Using the desktop app

The Biorouter desktop app (v1.91.2) is where most people do their daily work: you type a research question, watch the agent plan and call tools, and read the files, figures, and apps it produces, all in one window. This guide describes every surface of the app: the sidebar and titlebar, the chat composer and its toolbar, the tabs and split panes, the terminal inside the app, and the Home, History, and Settings pages. It assumes you have the app installed and a model provider connected. If you do not, start with Getting started.

The window layout

Every Biorouter window has three regions. Across the top is a thin titlebar with the window controls, a couple of quick actions, and the active session's name. Down the left is the sidebar, a fixed column of navigation and a list of recent chats. Everything else is the main area, which shows whichever section you have open (a chat, the Home page, History, Settings, and so on).

Session name Title bar Sidebar Chat Composer
The window: a title bar across the top, the navigation sidebar on the left, the chat on the right, and the composer floating at the bottom.

When you are in a chat, the main area is itself split from top to bottom: the scrolling transcript fills the space, and a floating composer (the box you type into) sits at the bottom. The composer is the only element in the app that carries a soft shadow; everything else is flat, separated by hairlines.

The sidebar

The sidebar is your map of the app. From top to bottom it holds Home, New chat, Crew, a collapsed Components disclosure holding the six feature destinations, a Recents list, and Settings pinned to the footer.

Home New chat Crew Components ▸ RECENTS GWAS on Type 2 Diabetes SPOKE MS query View all chat history Settings
The sidebar order: Home, then New chat and Crew, the Components disclosure (collapsed by default, holding the six feature destinations), a date grouped Recents list, and Settings at the bottom.

Navigation order

ItemWhat it opens
HomeThe landing page: greeting prompt, usage analytics, the activity heatmap, and recent chats. This is the top row in the rail.
New chatStarts a fresh, empty chat. It sits directly beneath Home.
CrewYour lab's shared workspace: channels, files and agent tasks with the people in your lab. It sits beneath New chat. See Crew.
ComponentsA disclosure holding the six feature destinations below. It is collapsed by default, and the app remembers whether you opened it.
WorkflowsSaved, reusable session templates you can run again or share. Inside Components.
SchedulerScheduled tasks that run workflows automatically on a cron schedule. Inside Components.
ExtensionsMCP extensions (pluggable tool servers). Toggle them on and off here. Inside Components.
SkillsReusable instruction sets that guide how the agent behaves. Inside Components.
KnowledgePersonal knowledge bases that the agent maintains, backed by markdown folders and git history. Inside Components.
Built appsInteractive apps the agent has built, plus their export controls. Inside Components.
RecentsChats you have touched lately, grouped by day. View all chat history at the foot of the list is the route to the full History page.
SettingsProviders and models, permission modes, themes, and the CLI install. Pinned to the footer.

Each row is 32px tall with an outline icon and a label. The active row is tinted and carries a 2px coral bar on its leading edge, the one place the accent colour appears in the sidebar.

The Recents list

Below the navigation, the Recents list shows chats you have touched lately, grouped by day (Today, then dated headings). Each row is the session's title as plain text; a small indicator appears next to a chat that is currently running. Click a row to reopen that session as a tab in the chat area. A count badge shows how many chats you have used in the past seven days, and View all chat history at the foot of the list jumps to the full History page. If the rail gets crowded, Recents has a disclosure control so you can fold it away.

Collapsing the sidebar

The sidebar is 288px wide by default and can be dragged between 216px and 360px using the resize handle on its trailing edge; the width is remembered per user. It collapses to a 60px icon rail, and the toggle in the titlebar switches between them. Below about 1120px of window width the app collapses the sidebar for you and shows it as an overlay when you need it, so the chat keeps its full measure on a narrow screen.

Titlebar controls

The titlebar carries the standard window controls plus two quick actions: a + that starts a new session, and a split/panel control for opening a new window. When the sidebar is collapsed or overlaid on macOS, the app reserves space after the traffic lights so the session name never sits under them. The session name in the titlebar is editable: renaming a chat here updates it everywhere the name appears (its tab, the Recents list, and History).

Chat and the composer

A chat is one continuous conversation. You type a request, the agent forms a plan and works through it (calling tools, writing files, drawing figures), and you read the results in the transcript. Your own turns are tinted so the eye can find them when scrolling; the agent's prose runs full width, unboxed, like a document.

Starting a session

Click New chat in the sidebar (or the + in the titlebar, or press Cmd+T). The composer opens centered and empty. Type your question or task in plain language and press Enter (or click Send). There is no special syntax: describe the task the way you would to a research assistant.

The composer toolbar

Under the text box is a row of controls. Each one is a chip you click to open a picker or to change a setting for this chat. From left to right:

Ask anything, or type / for a skill ~/project 3 2 1 gemma4 $0.12
The composer toolbar, left to right: working directory, then extensions, skills, and knowledge, then reasoning effort, model, context window, and cost, with the square Send button on the right.
#ControlWhat it does
1Working directory (folder icon + path)The folder the agent reads and writes in, with the tail of the path shown when it is long. Click to switch it. Relative paths the agent uses resolve against this directory.
2Extensions (puzzle + count)Which MCP extensions (tool servers) are active for this session. Open the picker to enable or disable them per chat.
3Skills (layers + count)Which skills (instruction sets) are in play. Open to add or drop skills for this chat.
4Knowledge (book + KB count)Which knowledge bases the agent can see and write to in this chat. Open to change the visible set.
5Reasoning effort (gauge)How hard the model should think. Shows only an icon while it is at the model's default; picking a quick or deep setting adds a label to the chip.
6Model (brain + model name)The model driving this chat. Click to switch model or provider in the middle of a conversation.
7Context window (ring gauge)How full the conversation's context window is. Its popover shows the labeled gauge and a button that compacts the conversation to free room in long chats.
8Cost (running total)The estimated spend for this session so far, updated as turns complete. Shown when cost tracking is enabled.
9Send / Stop (square accent button, right edge)Sends the message (paper plane icon), and becomes a Stop control while the agent is working.

There is no separate attach button: add files or images by pasting them or dragging them onto the composer, and their previews appear in a strip above the toolbar, each removable with its close control.

The toolbar folds when the chat is narrow

Inside a split pane, or in a small window, the whole left group collapses into a single + button ("Chat tools and settings"); only Send or Stop stays visible beside it. The + opens a popover stacking the same controls in three bands: the working directory, then extensions, skills, and knowledge, then reasoning, model, context, and cost. Nothing is removed. The controls move into the popover so the row fits.

Sending, stopping, and streaming

Press Enter or click Send to submit. Send is disabled while the box is empty. While the agent works, the button becomes a Stop control; click it to cancel the current turn. As the agent replies, text streams in with a blinking caret at the end, which disappears when the turn finishes. You can submit a message even while extensions are still loading in the background: your message lands in the transcript, the chat shows it streaming, and Stop works throughout.

Tool call lines

When the agent uses a tool, it shows up as a single line in the transcript, not a boxed card: a status icon, the tool name, a short summary of its arguments, and a duration. A spinner means the call is running, a check means it succeeded, and a warning triangle with a faint red wash means it failed. Click any tool call line to expand it and read the full arguments and results as code blocks; click again to collapse. This keeps a long chain of tool calls readable while the details stay one click away.

Editing, branching, copying, and retrying

Hover a message to reveal its actions. On your turns you get copy and edit; on the agent's turns you get copy, retry, and branch.

  • Copy puts the message text on the clipboard.
  • Edit lets you rewrite one of your earlier prompts and run the conversation again from that point.
  • Retry runs the agent's last turn again, useful if a response was cut off or you want another attempt.
  • Branch (Diverge) forks the conversation into a new session from the chosen point, so you can explore an alternative without losing the original. The branch opens as its own tab.

You can walk back through the messages with Cmd+Up and Cmd+Down to select an earlier one to edit, which is what the composer's placeholder hint refers to.

1

Switch the model during a chat

Click the model chip in the composer toolbar (the brain icon with the current model name, for example gpt-6-sol). Pick a different model, or a different provider, from the list. The next turn uses the new model; the transcript so far is unchanged.

2

Branch a conversation

Hover the agent turn you want to branch from and click Branch. Biorouter forks a new session that copies the conversation up to that point and opens it as a new tab. Continue in the branch; the original chat stays exactly as it was.

Tabs

The chat area works like a browser: every conversation is a tab in a strip along the top of the chat. Each tab is an independent session with its own transcript, model, working directory, and knowledge base selection. A tab that is actively running shows a small activity dot.

Opening tabs

  • The + at the right end of the tab strip opens a fresh blank chat in that group.
  • Cmd+T opens a new tab (a new chat) from anywhere in the chat area.
  • Clicking a row in History or Recents opens that session as a tab. Opening the same session twice reuses its existing tab rather than duplicating it, and the tab arrives already carrying the session's real name.

Renaming, closing, and reordering

Rename a chat from its titlebar name; the new name mirrors into the tab, Recents, and History. Close a tab with its × or with Cmd+W. Cycle between tabs with Ctrl+Tab (next) and Ctrl+Shift+Tab (previous), wrapping around at the ends. Biorouter uses Ctrl+Tab rather than Cmd+Tab because the operating system reserves Cmd+Tab for switching applications; this is the same choice Safari and Chrome make on macOS.

1

Reorder tabs by dragging

Press and hold a tab, then drag it left or right along the strip. A ghost of the tab follows your cursor and the other tabs shift to make room. Release it where you want it. Reordering never changes which session a tab holds; it only changes the order they sit in.

Split panes

You can split the chat area into panes placed side by side (or stacked) and run a different conversation in each. This lets you watch several agents work at once: one querying a clinical database, another running a SPOKE graph query, a third scanning literature, all visible together. Each pane is its own group with its own tab strip, transcript, model, and composer.

Making a split

1

Split a chat into two panes

Grab a tab and drag it toward an edge of the chat area. As you move, drop zones light up: dragging to the left or right edge creates a vertical (side by side) split, and dragging to the top or bottom edge creates a horizontal (stacked) split. The zone tints live as your cursor crosses it, so you can see where the tab will land before you release. Drop the tab and the chat area splits, with that tab's session now living in its own pane.

Dropping a tab onto the center of another pane instead moves it into that pane's tab strip rather than creating a new split. You can keep splitting up to 6 panes in one window. Each new pane runs a full, independent session.

Resizing panes

Between any two panes is a draggable splitter. Hover it, then drag to give one pane more room and the other less. The split reflows as you drag. If you shrink the window far enough that the panes would become too narrow to use, Biorouter merges the split back to a single group so the chat stays readable; a split you deliberately created at a narrow width is left alone.

Each pane is separate

A pane carries its own model, working directory, permission mode, knowledge bases, and enabled extensions. Two panes can run different models against different folders at the same time. The transcripts do not share context; they are separate sessions that happen to be on screen together.

The terminal inside the app

Every chat tab can open its own terminal, docked beneath the transcript, so you can run shell commands right next to the conversation (inspect a file the agent wrote, run a script, check git status) without leaving the app.

1

Open a terminal for the current chat

Use the terminal control in the chat to toggle the terminal dock open. It appears below the transcript for the tab you are in. The shell starts in that session's working directory, the same folder shown in the composer's working directory chip, captured at the moment the terminal opens.

Terminals are per tab. Each chat tab has its own terminal with its own open/hidden state and its own panes; switching tabs switches which terminal you see. A background tab's shell keeps running (hidden) until you close the tab. Inside the dock, a + after the last terminal tab opens an additional terminal pane. When focus is in the terminal, Cmd+T opens a new terminal pane (rather than a new chat tab), so the shortcut follows wherever your attention is.

Home

Home is the app's landing page and a summary of your usage. Top to bottom it holds a greeting, your activity analytics, and your recent chats, with the composer at the bottom so you can start typing immediately.

The greeting and prompt

A short heading ("UCSF Biorouter") appears above one greeting line, and the composer is on the same page. Home also starts a new session: type in the composer to open a chat.

Usage analytics and the heatmap

Home shows cached statistics about how much you have used the app: total sessions and total tokens, with figures for the last 30 days and the last 7 days. Below them is a usage heatmap laid out like GitHub's contribution graph: roughly five months of daily activity, one cell per day, shaded by how much work that day held (sessions started and tokens processed). A header shows your current streak of consecutive active days and your longest streak.

Hover over any cell, or move keyboard focus to it, to see that day's detail: sessions started, tokens processed, messages, and the top model used. Shading is relative to your own recent window, so ordinary days stay distinguishable from heavy ones rather than all collapsing to the faintest colour.

How the numbers are counted

Tokens are attributed to the day a session started (older sessions from before daily accounting are anchored to their start day), which the heatmap tooltip notes. The counts include your own and scheduled sessions; subagent, hidden, and terminal sessions are excluded so the tiles match the list beneath them.

Recent chats

Under the heatmap is a short list of recent sessions, each with a token count and a relative time. Click one to reopen it as a tab, or use See all to jump to the full History page.

History

History is the searchable record of every conversation you have had. Sessions are grouped by day (Today, then dated headings), and each row shows the session title, its time, its working folder, and its message and token counts.

Searching and reopening

1

Reopen a past session

Press Cmd+F to search across your past conversations by their content, or scroll the list, which is grouped by day. Click a session to open it as a named tab in the chat area, right where you left off. Opening a session that is already open switches to its existing tab.

Importing and exporting sessions

Use Import Session on the History page to bring in a session file (for example one a colleague exported). Individual sessions can be exported for sharing or backup. Your history is stored in a local SQLite database at ~/.local/share/biorouter/sessions/sessions.db, so search and recall read it from your own machine.

The other sidebar sections

The remaining sidebar routes each manage one kind of thing. They share the same page shape: a title, a short description, an action or two at the top right, and a list below.

  • Workflows turn a successful session into a reusable template. Each workflow row has actions to run it, open a terminal for it, edit it, share it, schedule it, and delete it. Create Workflow and Import Workflow sit at the top.
  • Scheduler lists scheduled tasks that run workflows on a cron schedule, showing each one's timing and last run, with edit, pause, and delete controls. Some schedules are built in.
  • Extensions lists your MCP extensions, grouped into the ones that ship with Biorouter and the ones you installed, each with an on/off switch. Add Extension, Browse Extensions (the marketplace), and Add Custom Extension are at the top. Turn off extensions you are not using: fewer active tools improves the agent's tool selection and saves context.
  • Skills lists reusable instruction sets, grouped into families, with tags. Add Skill, Browse Skills, and Add Custom Skill are at the top.
  • Knowledge is where you build and view personal knowledge bases. You ingest sources (drop files, paste text, or add a URL) into a KB, and the agent digests them into a markdown tree with a git history. The page shows a KB selector, an ingest panel, and a graph of the pages and their links, with export (.brkb), a change log, and a control that opens the folder.
  • Apps lists interactive apps the agent has built for you and is the only place to delete one (deleting removes its files from disk, so the card in a chat never offers a delete).

Settings

Settings is the app's configuration hub. The areas you will use most:

Providers and models

Provider Configuration is where you connect LLM providers and pick models. Providers are grouped as Local (Llama Server, Ollama), Institutional (UCSF Versa via Azure and Bedrock), and Commercial (Anthropic, OpenAI, Google Gemini, OpenRouter, and more), with Local listed first. A configured provider shows a check. API keys are encrypted and stored in your operating system's credential store, not in a plaintext file. You can also switch model per chat from the composer's model chip; the setting here is the default.

Permission modes

Permission modes decide how much the agent may do without asking. You can give it full autonomy, require your approval before it takes actions, or keep it to chat only (no actions at all). The composer's mode chip changes this per chat; choose the level that matches how much supervision you want. Sensitive files can be fenced off entirely with a .biorouterignore file listing paths the agent must not read or change.

Themes

Biorouter ships three theme families, each available in light and dark:

FamilyCharacter
Parchment (default)Warm paper and terracotta. The base look.
Alma MaterUCSF brand: navy ground with a teal accent.
Roche LimitWhite, grey, and orange, inspired by JupyterLab.
1

Change the theme

Pick a theme family in Settings, and choose Light, Dark, or System for the mode. System follows your operating system's light/dark setting and is the default, so the app matches the rest of your desktop. The light/dark choice and the family are independent, so any family works in either mode.

Capabilities

Capabilities are the categories of action the agent can take (reading and writing files, running shell commands, querying data, driving an app's own interface). Which capabilities are available in a chat depends on the extensions you have enabled and the permission mode you have set. Apps the agent builds have their own capability switches, so, for example, an app that only works with text can be built with file and shell access turned off.

Install the command line tool

The desktop app bundles the biorouter command line tool. To put it on your PATH, run biorouter setup-path in a terminal (macOS and Windows). If your terminal's biorouter is older than the app, the Biorouter CLI Update card in the app installs and links the matching version again; the app's own bundled daemon always matches the app.

The CLI and the desktop app share the same account and configuration, so a session you start in one shows up in the other. The CLI is documented separately in the command line reference.

The menu bar and tray

The application menu bar mirrors the sidebar with keyboard shortcuts and adds a few things the sidebar does not: New Window, Open Directory, theme switching (Light, Dark, System), provider configuration, and links to the documentation and bug reports. On macOS, a left click on the tray icon brings the window to the front, and a right click opens a short menu (Home, New Chat, Settings, Extensions, Skills, Check for Updates, Quit).

Menu bar navigation shortcuts (such as the number keys for the main sections) can vary between app versions as sections are added. The keys below, which work as they do in a browser (new tab, new window, close, cycle), are stable across the app.

Keyboard shortcuts

Shortcuts use Cmd on macOS and Ctrl on Windows and Linux, except where noted.

ActionShortcut
New tab (new chat), or new terminal pane when the terminal is focusedCmd+T
New windowCmd+N
Close the current tabCmd+W
Close the windowShift+Cmd+W
Next tab / previous tab (wraps)Ctrl+Tab / Ctrl+Shift+Tab
Search the current list (History, Workflows, Extensions, Skills)Cmd+F
Navigate to an earlier / later message to editCmd+Up / Cmd+Down
Open SettingsCmd+,
Open a directory as the working folderCmd+O
Focus the Biorouter windowOption+Cmd+G
Quick Launcher (start a session from anywhere)Cmd+Option+Shift+G (macOS), Ctrl+Alt+Shift+G (Windows/Linux)
QuitCmd+Q

Where to go next

  • Getting started covers installing Biorouter, connecting a provider and your first session.
  • Providers and models covers each provider's credentials and default model.
  • Crew covers working with your lab: joining or hosting a workspace, channels, files and agent tasks.
  • The command line reference documents the biorouter CLI, which shares your account and sessions with the app.
Using Biorouter

Command line

The biorouter command line interface is the terminal side of Biorouter. It runs the same agent that powers the desktop app: you can hold an interactive chat, run a single task from a script, manage sessions and providers, install extensions and skills, maintain knowledge bases, schedule recurring workflows, and start local web or server interfaces. This page documents every subcommand, every flag, the interactive session (the REPL), the terminal integration, and the biorouterd daemon that the GUI talks to. It targets Biorouter 1.91.2 (Node 24+, Rust 1.92).

Top level usage and global structure

The CLI is a single binary named biorouter with one subcommand per task. Run it with no subcommand to drop straight into an interactive session (Biorouter runs first time configuration instead if no config file exists yet).

biorouter [SUBCOMMAND] [FLAGS] [ARGS]

biorouter                      # start (or first-time-configure then start) an interactive session
biorouter --help               # print the top-level help and the full subcommand list
biorouter --version            # print the installed version (1.91.2)
biorouter <subcommand> --help  # per-subcommand help, flags, and defaults
FlagPurpose
-h, --helpShow help for the CLI or any subcommand. Every subcommand accepts --help.
-V, --versionPrint the version and exit. The CLI (biorouter), the daemon (biorouterd), and the core library are compiled from one workspace version, so they never disagree.

Command aliases

Several subcommands have short aliases: session = s, project = p, projects = ps, knowledge = kb, extension = ext, schedule = sched, and setup-path = install-cli.

Exit codes

The CLI returns 0 on success. A turn that ran but did not complete its work reports its own exit code so a caller can tell a rejected provider key apart from a normal disagreement: for example 75 when the provider rejected the credentials. Any other error returns 1.

Flag naming conventions

Flag names are consistent across subcommands so they are predictable:

  • --session-id for session identifiers (for example 20251108_1); --id is an accepted alias.
  • -n, --name for names people can read.
  • --path for file paths (legacy session support).
  • -o, --output for output file paths.
  • -r means --resume for sessions and --regex for filters, depending on the command.
  • -v, --verbose for detailed output, -l, --limit for result counts, -f, --format for output format, -w, --working_dir for directory filters.

Session and chat

session

Start or resume an interactive chat session. This is the CLI's main interface: a persistent conversation with the agent, tool calls, and slash commands. Alias: s.

biorouter session [--resume] [--history] [-n NAME | --session-id ID | --path PATH] [FLAGS]
FlagTypeDefaultDescription
-n, --name <NAME>stringnoneName for the session. With --resume, resumes the session with this name if it exists; otherwise a new named session is created (with a warning) rather than erroring.
--session-id <ID>stringnoneAddress a session by its ID (for example 20250921_143022). Only valid together with --resume. Alias: --id.
--path <PATH>pathnoneLegacy: derive the session ID from a file path (the file stem). For older session storage kept in files.
-r, --resumeflagoffResume a previous session. With no identifier, resumes the most recently used session.
--historyflagoffRender the previous messages when resuming. Requires --resume.
--debugflagoffDebug output: full tool responses with no truncation and full file paths.
--max-tool-repetitions <N>integerunsetCap how many times the same tool can be called consecutively with identical parameters. Guards against infinite loops.
--max-turns <N>integer1000Cap the number of turns the agent takes without asking for user input.
--with-extension <COMMAND>string (repeatable)noneAdd a stdio extension from a full command, optionally with env vars. Format: ENV1=val1 command args....
--with-streamable-http-extension <URL>string (repeatable)noneAdd a remote extension over Streamable HTTP.
--with-builtin <NAME>comma listnoneEnable one or more included extensions by name, for example developer,computercontroller.
--provider <PROVIDER>stringconfigOverride the provider for this session (overrides BIOROUTER_PROVIDER).
--model <MODEL>stringconfigOverride the model for this session (overrides BIOROUTER_MODEL). The provider must support it.
--shared-daemonflagoffRun the session in your profile's shared background service, the one the desktop app and biorouter crew use. It does not give the session Crew access.
--approval-key-stdinflagoffRead the shared service's approval secret from standard input. Requires --shared-daemon.
--no-startflagoffUse only a shared service that is already running. Requires --shared-daemon.
--create-onlyflagoffCreate the conversation in the shared service without sending a prompt. Requires --shared-daemon.
# Start a named session
biorouter session -n gwas-analysis

# Resume the last session, showing prior messages
biorouter session --resume --history

# Resume a specific session by ID
biorouter session --resume --session-id 20251108_2

# Start with the developer builtin and a memory MCP extension
biorouter session --with-builtin developer \
  --with-extension "npx -y @modelcontextprotocol/server-memory"

session subcommands

The session command also groups management subcommands. Each targets a session by --session-id, -n/--name, or legacy --path; if you supply none, most prompt you to pick one interactively.

session list

List saved sessions.

biorouter session list [-f text|json] [--ascending] [-w PATH] [-l N]
FlagTypeDefaultDescription
-f, --format <FMT>text or jsontextOutput format.
--ascendingflagoff (newest first)Sort oldest first.
-w, --working_dir <PATH>pathnoneFilter by working directory. Short alias -p.
-l, --limit <N>integernoneLimit the number of results.

session remove

Remove one or more saved sessions. Runs interactively if no identifier or regex is given.

biorouter session remove [--session-id ID | -n NAME | -r REGEX]
FlagTypeDescription
--session-id <ID>stringRemove a specific session by ID.
-n, --name <NAME>stringRemove a specific session by name.
-r, --regex <PATTERN>regexRemove every session matching the pattern.
Removal is permanent. Biorouter lists the sessions to be removed and asks for confirmation before deleting.

session export

Export a session for backup, sharing, or documentation.

biorouter session export [IDENTIFIER] [-o FILE] [--format markdown|json|yaml]
FlagTypeDefaultDescription
-o, --output <FILE>pathstdoutWrite the export to a file instead of stdout.
--format <FMT>markdown, json, yamlmarkdownmarkdown is a readable transcript; json and yaml are complete backups that preserve history, metadata, and settings.
# Full JSON backup of a named session
biorouter session export -n gwas-analysis --format json -o backup.json

# Readable markdown transcript to stdout
biorouter session export --session-id 20251108_4

session diagnostics

Generate a troubleshooting bundle (a ZIP) for a session.

biorouter session diagnostics [IDENTIFIER] [-o FILE]
FlagTypeDefaultDescription
-o, --output <FILE>pathdiagnostics_<session_id>.zipWhere to write the bundle.

The bundle includes system information (version, OS, architecture, timestamp), the session's full message history, your configuration files, and recent logs.

Diagnostics bundles contain your session messages and system information. Review the contents before sharing publicly if the session includes API keys, personal data, or proprietary code.

session rename

Rename a saved session.

biorouter session rename [IDENTIFIER] --new-name "NAME"
FlagTypeDescription
--new-name <NAME>string (required)The new session name.

session diverge

Branch a stored conversation into a new session, keeping the full history. The original is left untouched. The new session ID is printed to stdout; resume it with biorouter session --resume --session-id <ID>.

biorouter session diverge [IDENTIFIER] [--branch-name "NAME"]
FlagTypeDescription
--branch-name <NAME>stringOptional name for the branched session.
Sessions are stored in a SQLite database (sessions.db) under Biorouter's data directory, not as individual files. Older .jsonl sessions are imported automatically; the legacy files stay on disk but are no longer managed.

run

Execute a task without an interactive session, from an instruction file, a text string, stdin, or a workflow. This is the command for scripting and automation. By default it processes the input and exits; add -s/--interactive to continue in a chat afterward.

biorouter run (-i FILE | -t "TEXT" | --workflow NAME_OR_PATH) [FLAGS]
FlagTypeDefaultDescription
-i, --instructions <FILE>pathnoneRead the prompt from an instruction file. Use - for stdin. Mutually exclusive with -t and --workflow.
-t, --text <TEXT>stringnoneProvide the prompt directly on the command line.
--workflow <NAME_OR_PATH>stringnoneLoad a workflow by name (from local dirs or a configured GitHub repo) or full path.
--system <TEXT>stringnoneAdditional system prompt to customize agent behavior. Not valid with --workflow.
--params <KEY=VALUE>repeatablenoneParameters passed to the workflow. Repeat for multiple values.
--sub-workflow <WORKFLOW>repeatablenoneInclude subworkflows (names or local paths) alongside the main workflow.
--explainflagoffPrint the workflow's title, description, and parameters, then exit without running.
--render-workflowflagoffPrint the rendered workflow YAML instead of running it.
-s, --interactiveflagoffContinue in an interactive session after the initial input is processed.
-n, --name <NAME>stringnoneName for this run's session.
-r, --resumeflagoffResume from a previous run.
--path <PATH>pathnoneLegacy session path, for sessions kept in files.
--no-sessionflagoffRun without creating or storing a session file. Conflicts with --resume, --name, --path.
--debugflagoffFull tool responses and paths, no truncation.
--max-tool-repetitions <N>integerunsetLimit on consecutive identical tool calls.
--max-turns <N>integer1000Turn limit without user input.
-q, --quietflagoffQuiet mode. Suppress everything except the model response, which is printed to stdout.
--output-format <FMT>text, json, stream-jsontextStructured output for automation: json for a single result after completion, stream-json for events as they occur.
--provider <PROVIDER>stringconfigOverride the provider for this run (overrides BIOROUTER_PROVIDER).
--model <MODEL>stringconfigOverride the model for this run (overrides BIOROUTER_MODEL).
--with-extension, --with-streamable-http-extension, --with-builtinsee sessionnoneSame extension flags as session.
--shared-daemon, --approval-key-stdin, --no-start, --create-onlysee sessionoffSame shared service flags as session.
# One-shot prompt, machine-readable JSON, no stored session
biorouter run --no-session -t "summarize this VCF header" --output-format json

# Pipe a prompt in via stdin
cat plan.md | biorouter run -i -

# Run a parameterized workflow, then stay interactive
biorouter run --workflow daily-report.yaml --params region=us-west-2 --interactive

# Inspect a workflow without running it
biorouter run --workflow daily-report.yaml --explain

The interactive session (REPL)

An interactive session is Biorouter's terminal REPL. Start it with biorouter, biorouter session, or biorouter run --interactive. Unlike a single run, an interactive session keeps a live prompt (Biorouter ❯) where you type messages, watch tool calls stream, and issue slash commands between turns. A single run processes one input and exits, which is what you want in scripts and CI; the interactive session is for iterative work.

Slash commands

Type these at the prompt. Press / then Tab to cycle through them; Tab also completes /skill: and /ext: references.

CommandEffect
/help, /?Show the session help with every slash command.
/clearClear the current chat history.
/compactCompact and summarize the chat to reclaim context while keeping key information. (Replaces the deprecated /summarize.)
/diverge [name]Branch this chat into a new session, keeping the full history.
/rename <name>Rename the current chat.
/goal <condition>Keep working until the condition is met. /goal clear stops it.
/loop <interval> <prompt>Run a prompt on an interval, for example /loop 5m .... /loop stop <id> stops it.
/schedule <spec> <prompt>Schedule a recurring prompt using 5m, @daily, or a quoted cron expression.
/mode <name>Set the permission mode: auto, approve, chat, or smart_approve.
/plan [message]Enter plan mode: build a plan from the current chat and offer to act on it.
/endplanExit plan mode and return to normal mode.
/workflow [file.yaml]Save the current chat as a workflow. Defaults to ./workflow.yaml; a supplied path must end in .yaml.
/extension <cmd>Add a stdio extension during the session. Format: ENV1=val1 command args....
/builtin <names>Add included extensions by name (separated by commas).
/tToggle the markdown theme through light, dark, ansi.
/t <name>Set the theme directly to light, dark, or ansi.
/rToggle full, untruncated tool output.
/exit, /quitExit the chat.

Keyboard shortcuts

KeyAction
Ctrl+CInterrupt the current request. The chat resets to before the interrupted turn.
Ctrl+JInsert a newline without submitting.
Up / DownNavigate command history.
Ctrl+RSearch command history backwards. Type a term, press Ctrl+R to cycle backward and Ctrl+S to cycle forward, then Enter to run or Esc to cancel.
TabComplete slash commands, file paths, and /skill: / /ext: references.

Themes

The /t command controls syntax highlighting for markdown in CLI responses (headers, code blocks, emphasis). It affects fonts and colors only, not the terminal chrome. There are three themes: light and dark use subtle colors, and ansi is the most visually distinct. The default is dark. The choice is saved to the configuration file as BIOROUTER_CLI_THEME and persists between sessions; the BIOROUTER_CLI_THEME environment variable overrides the saved value for one session. The CLI theme is independent of the desktop app theme.

Workflows and scheduling

workflow

Validate workflow files, install them into your library, generate shareable links, list what is available, and open workflows in Biorouter Desktop.

biorouter workflow <install|validate|deeplink|open|list> [ARGS]
SubcommandSynopsisDescription
installworkflow install <PATH>Install a workflow .json or .yaml file into the workflow library.
validateworkflow validate <NAME_OR_PATH>Validate a workflow file by name or path.
deeplinkworkflow deeplink <NAME> [-p KEY=VALUE]...Generate a shareable deeplink. -p/--param fills in a parameter in advance (repeatable).
openworkflow open <NAME> [-p KEY=VALUE]...Open the workflow in Biorouter Desktop. -p/--param fills in a parameter in advance (repeatable).
listworkflow list [--format text|json] [-v]List workflows from local directories and configured GitHub repos. --format defaults to text; -v/--verbose adds titles and full paths.
biorouter workflow validate daily-report.yaml
biorouter workflow deeplink daily-report.yaml -p region=us-west-2
biorouter workflow list --verbose

schedule

Run workflows automatically on a cron schedule. Adding a job copies the current workflow into a scheduled_workflows directory in Biorouter's data dir, so later edits to the source file do not change the scheduled copy. Alias: sched.

biorouter schedule <add|list|remove|sessions|run-now|cron-help> [FLAGS]
SubcommandSynopsisDescription
addschedule add --schedule-id ID --cron "EXPR" --workflow-source PATHCreate a scheduled job. --workflow-source is a path to a YAML file (or a workflow encoded in base64). --id aliases --schedule-id.
listschedule listList all scheduled jobs.
removeschedule remove --schedule-id IDDelete a scheduled job.
sessionsschedule sessions --schedule-id ID [-l N]List sessions a schedule created. -l/--limit caps the count.
run-nowschedule run-now --schedule-id IDRun a scheduled workflow immediately.
cron-helpschedule cron-helpPrint a cron expression guide with common examples.

Cron expressions may have 5 fields (minute hour day month weekday), 6 fields (with a leading seconds field), or be shorthands like @hourly, @daily, @weekly, @monthly.

# Run every day at 9:00 AM (6-field form with seconds)
biorouter schedule add --schedule-id daily-report \
  --cron "0 0 9 * * *" --workflow-source ./workflows/daily-report.yaml

# Run every Monday at 8:00 AM (5-field form, no seconds)
biorouter schedule add --schedule-id review-weekly \
  --cron "0 8 * * 1" --workflow-source ./review.yaml

biorouter schedule sessions --schedule-id daily-report -l 10
biorouter schedule run-now --schedule-id daily-report
biorouter schedule remove --schedule-id daily-report
The services-status and services-stop subcommands are deprecated and do nothing. The scheduler no longer runs an external service, so there is nothing to start or stop.

Extensions, skills, knowledge, and apps

extension

Install and manage MCP extensions distributed as .brxt bundles. Alias: ext.

biorouter extension <install|list|remove> [FLAGS]
SubcommandSynopsis and flagsDescription
installextension install <PATH> [--env KEY=VALUE]... [--secret KEY=VALUE]... [--no-enable]Install from a .brxt bundle: extract, run uv sync, and register. --env sets a plain env var; --secret stores a value in the keyring; both repeatable. --no-enable installs without enabling.
listextension list [--format text|json]List configured extensions.
removeextension remove <NAME> [--purge]Remove a configured extension. --purge also deletes the installed files on disk.

skill

Install and manage skills distributed as .zip archives.

biorouter skill <install|list|remove> [FLAGS]
SubcommandSynopsisDescription
installskill install <PATH> [--force]Install a skill (or bundle) from a .zip. --force overwrites an existing install.
listskill listList installed skills, including each slug.
removeskill remove <SLUG>Remove an installed skill by its slug.

knowledge

Manage personal knowledge bases that the agent maintains (markdown trees backed by git history). Alias: kb. Most subcommands default to the active knowledge base when --kb is omitted.

biorouter knowledge <list|active|create|ingest|ingest-conversation|lint|hide|unhide|query> [FLAGS]
SubcommandSynopsis and key flagsDescription
listknowledge list [--format text|json]List knowledge bases; the active one is marked.
activeknowledge active [--set ID] [--clear]Show the active KB, or set it with --set, or clear it with --clear.
createknowledge create <ID> [--name NAME] [--color #HEX]Create a KB with an id of lowercase words joined by dashes, an optional display name, and an accent color.
ingestknowledge ingest [--kb ID] [--url URL | --file PATH | --text TEXT] [--focus HINTS] [--provider P] [--model M]Ingest a URL, file, or text into a KB. --focus passes optional focus hints; --provider/--model override the model used for digestion.
ingest-conversationknowledge ingest-conversation [--kb ID] [--session SESSION_ID]... [--new-kb NAME] [--focus HINTS] [--provider P] [--model M]Digest chat session history into a KB. --session is repeatable and defaults to the most recent session; --new-kb creates a new KB with that display name and ingests into it.
lintknowledge lint [--kb ID] [--fix] [--provider P] [--model M]Check a KB for orphans, contradictions, and stale sources. --fix lets the subagent repair findings.
hideknowledge hide <ID>Hide a KB from the agent; it stays on disk.
unhideknowledge unhide <ID>Make a hidden KB visible to the agent again.
queryknowledge query "QUESTION" [--kb ID] [--save] [--provider P] [--model M]Ask a question against a KB. --save persists the answer as a knowledge page.
biorouter knowledge create ms-genetics --name "MS genetics" --color "#cf6d47"
biorouter knowledge active --set ms-genetics
biorouter knowledge ingest --url https://example.org/paper --focus "risk loci"
biorouter knowledge query "which HLA alleles raise MS risk?" --save

apps

List, open, and serve Biorouter apps (the front ends built by Agent Drafter). open and serve reuse a biorouterd already listening on the configured port (BIOROUTER_PORT, default 3000) or start one for you, then open http://127.0.0.1:<port>/apps/<id>/. Apps render in a real browser, not in the terminal.

biorouter apps <list|open|serve> [ARGS]
SubcommandSynopsisDescription
listapps list [--json]List installed apps. --json emits JSON for other programs instead of a table.
openapps open <ID>Open an app in your default browser.
serveapps serve <ID>Serve an app in the foreground until Ctrl+C.

mcp

Run one of the MCP servers bundled with Biorouter over stdio. MCP (Model Context Protocol) is the standard Biorouter extensions speak. This command is normally launched by a host, not typed by hand.

biorouter mcp <server>

Accepted server names: autovisualiser, computercontroller, webdocuments, developer, memory.

Lab workspaces

crew

Work in a Crew workspace from the terminal: join or host a workspace, manage teams and channels, post and read messages, share files, run agent tasks, and give a chat access to a channel. The commands use the same background service and saved connections as the desktop app. Every command except daemon status asks for your Crew approval secret.

biorouter crew [--connection NAME] <COMMAND> [ARGS]
CommandsWhat they do
daemon, credentialsStart, check or stop the shared background service. Manage the optional encrypted key vault.
status, connections, auth, connect, disconnectList, save and remove connections. Sign in to the server. Open or close the connection.
joinShow this computer's code for the host, then wait until the host lets you in.
workspace, enrollShow, create or rename the workspace. Invite people, let them in with their code, or remove them (host).
members, teams, channels, invites, ownership, remove-member, profilePeople, teams, channels, channel ownership and your display name.
send, history, search, watch, filesPost, read, search and follow messages. Upload, download and share files and server paths.
tasks, grants, contextRun agent tasks in a channel. Give a chat access to a channel, check it and revoke it.
privacyShow privacy settings, change your connection's privacy, or change the workspace's privacy (host).

The Crew page lists the command lines for each task.

Providers and models

models

Inspect and update provider and model configuration, and manage downloaded local models.

biorouter models <current|providers|list|set|local> [FLAGS]
SubcommandSynopsisDescription
currentmodels current [--format text|json]Show the configured provider and model.
providersmodels providers [--format text|json]List available providers.
listmodels list <PROVIDER> [--format text|json]List known models for a provider (for example openai, anthropic, ollama, databricks).
setmodels set --provider P --model MSet the default provider and model.
localmodels local <list|pull|rm>Manage local models stored on disk (Llama Server). See below.
models local subcommandSynopsisDescription
list (alias ls)models local list [--format text|json]List the local model catalog and what is already downloaded.
pullmodels local pull <MODEL>Download (cache in advance) a model without starting a chat. Accepts a catalog name (for example gemma4 or qwen3.6) or a raw owner/repo:QUANT Hugging Face spec.
rm (alias delete)models local rm <MODEL>Delete a downloaded model to reclaim disk space.
biorouter models current
biorouter models list ollama --format json
biorouter models set --provider openai --model gpt-6-sol
biorouter models local pull qwen3.6

configure

Interactively configure Biorouter: providers, API keys, extensions, and permission settings. With no configuration file present, running biorouter with no subcommand launches first time setup, which is the same flow.

biorouter configure

Diagnostics and information

info

Print Biorouter's version and key paths: the config directory, config.yaml, the sessions SQLite database, and the logs directory. Each path is annotated when missing (and whether it can be created).

biorouter info [-v]
FlagDescription
-v, --verboseAlso print the resolved configuration (the config.yaml values) as YAML.

doctor

Check system prerequisites and the CLI install. It reports installed dependencies (git, uv, node, and others) with versions, whether biorouter is on your PATH, the local model (Llama Server) sidecar status and model cache location, the shell sandbox enforcement tier, and (unless skipped) whether a newer release is available.

biorouter doctor [--format text|json] [--no-update]
FlagTypeDefaultDescription
--format <FMT>text or jsontextA report for people, or JSON for other programs.
--no-updateflagoffSkip the networked self update check (faster, and works offline).

setup-path

Install the biorouter command onto your PATH by symlinking the running executable into a standard bin directory, so you can call it from any terminal. If the target directory is not on your PATH, it prints the exact export PATH=... line to add. Alias: install-cli.

biorouter setup-path

usage

Report token and cost usage per day or per model, with a summary of the month so far against your configured monthly budget.

biorouter usage [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--by-model] [--json]
FlagTypeDefaultDescription
--from <YYYY-MM-DD>date30 days agoStart of the range (local time).
--to <YYYY-MM-DD>datetodayEnd of the range (local, inclusive).
--by-modelflagoff (by day)Group usage by model instead of by day.
--jsonflagoffEmit JSON for other programs instead of a table.
biorouter usage --from 2026-07-01 --to 2026-07-20 --by-model
biorouter usage --json

Project management

project

Resume work on your most recently accessed project directory, or start a new session in the current directory when there is no history. Alias: p.

biorouter project

projects

Choose from your recent project directories interactively. Alias: ps.

biorouter projects

Terminal integration

Terminal integration ties a persistent Biorouter session to each terminal window and lets you ask questions from your shell prompt with recent command history as context. Set it up once, then use the @biorouter and @g aliases.

term

biorouter term <init|run|info> [ARGS]
SubcommandSynopsisDescription
initterm init <bash|zsh|fish|powershell> [-n NAME] [--default]Print the shell initialization script. It exports BIOROUTER_SESSION_ID, defines the @biorouter and @g aliases, and installs a preexec hook that logs your commands into the session. -n/--name names the terminal session; --default makes Biorouter the handler for unknown commands (zsh and bash only).
runterm run <prompt words...>Send a prompt to this terminal's session, with the recent shell history included as context. Words do not need quoting.
infoterm infoPrint compact session info (a context usage meter and the model name) for shell prompt integration, for example ●○○○○ sonnet.
1

Add the init line to your shell profile

For zsh: echo 'eval "$(biorouter term init zsh)"' >> ~/.zshrc. Add --default if you want anything that is not a valid command sent to Biorouter.

2

Reload the shell

source ~/.zshrc (or open a new terminal). Each terminal now keeps its own session that resumes automatically.

3

Ask from the prompt

Use the aliases created by the init script.

@biorouter and @g

These aliases both call biorouter term run, so your recent commands are in context.

@biorouter create a python script to process these files
@biorouter create a PR description summarizing these changes
@g how do I fix these permission denied errors?
There is also a hidden biorouter term log subcommand. The shell hook calls it to record each command into the terminal session; you do not run it directly.

Server and browser access

serve

Run Biorouter and reach it from a web browser. biorouter serve starts the biorouterd daemon, passes it the built interface, and prints a URL to open. It is the same interface the desktop app shows, served over HTTP instead of in an Electron window, so sessions, extensions, knowledge bases, workflows and Agent Drafter apps all behave the way they do on the desktop.

biorouter serve [--host ADDR] [-p PORT] [--token TOKEN] [--no-token] [--web-dir DIR] [--open] [--computer-use-approval]
biorouter headless is an accepted alias and behaves identically. It is the name the standalone biorouter-headless binary was known by; that binary and its .tar.gz release artifact were retired, and the capability now ships in every install.

Install it

There is nothing extra to install. Every Biorouter package carries the interface bundle and the daemon that serves it:

  • macOS, Windows, Linux desktop: the app ships the CLI. Accept the “Install Biorouter CLI” prompt, or run biorouter setup-path, then biorouter serve from any terminal.
  • Linux servers, HPC nodes, containers: install the command line package, which has no desktop app and no GUI dependencies:
    sudo apt install ./biorouter-cli_*_amd64.deb     # Debian / Ubuntu
    sudo dnf install ./biorouter-cli-*-1.x86_64.rpm  # Fedora / RHEL / Rocky
    These install biorouter and biorouterd to /usr/bin and the interface to /usr/share/biorouter/web.

Set it up

Choose the provider and model before you start serving. A browser session cannot change them (see the model is fixed below), so this step is not optional:

biorouter configure     # pick a provider and model, and store its credential
biorouter serve --open

serve stays in the foreground and prints the address to open:

  Biorouter is serving at

      http://127.0.0.1:8765/?t=1f4c9e02…

  The token above is shown once, and is new on every launch.

  The model is whichever `biorouter configure` chose; a browser cannot change it.
  Press Ctrl-C to stop.

Open that whole address, ?t= included. The token is what authenticates you. Biorouter exchanges it once for a session cookie and removes it from the address bar, so it does not linger in your history. Ctrl+C stops the daemon and frees the port.

FlagTypeDefaultDescription
--host <ADDR>string127.0.0.1Address to bind. Anything reachable from another machine requires a token.
-p, --port <PORT>integer8765Port to listen on. Deliberately not 3000, which is the daemon's own default.
--token <TOKEN>stringnew random token per launchUse a fixed token instead of a generated one, for a service unit or a script.
--no-tokenflagoffServe with no access token. Refused for any bind address other than loopback, and cannot be combined with --token.
--web-dir <DIR>pathfound automaticallyDirectory holding the built interface. The error names every location it tried.
--openflagoffOpen a browser once the server is ready.
--computer-use-approvalflagoffInteractively set a separate Biorouter Copilot approval key of at least 16 characters. Only its SHA-256 digest reaches the daemon, and the key itself is never saved. Requires an interactive terminal, and it is the only way a browser session can approve a Biorouter Copilot task.

Reach it from another machine

The default bind is loopback, so by default nothing outside the machine can connect. Reaching it from elsewhere is an explicit choice, and a token becomes mandatory rather than optional:

# Reachable on the network. A token is generated and required; --no-token is refused here.
biorouter serve --host 0.0.0.0 --port 8765

The console then prints a second URL built from an address other machines can use. If it cannot determine one, it says so rather than printing a loopback address that other machines cannot reach.

An exposed port is an exposed agent. Anyone who reaches it with the token can run tools, read files the daemon can read, and spend your model credits. The token is a launch credential, not a user account: there are no separate logins and no permissions for each user. On anything larger than a trusted lab network, put a reverse proxy with TLS and real authentication in front of it, and do not expose it to the internet directly.

The model is fixed before you start

A browser session cannot change its model or provider. The picker is inert, and this is deliberate: it is a privacy property, not a limitation.

Biorouter classifies a conversation by the sensitivity of what it has touched, and a conversation that has reached a private model hosted by your institution may never later reach a public one. That guarantee depends on knowing which model a conversation ran against. The desktop app can change the provider during a session because it holds proof that a human at the keyboard asked; a browser tab holds no such proof, and manufacturing one would put the key somewhere page JavaScript could reach, exactly what the mechanism exists to prevent.

So the capability is withdrawn rather than approximated: the provider is chosen once, at the terminal, and the privacy tier that choice implies holds for every session in that daemon. A run started against an institutional model is private for its whole life; one started against a commercial model is public for its whole life. Neither can drift. To change it, stop serve, run biorouter configure, and start it again.

What works in a browser, and what does not

CapabilityIn a browser
Chat, streaming, sessions and historyYes
Extensions, skills, workflows, scheduled jobsYes
Knowledge bases and ingestYes
Agent Drafter apps, including their live agent socketsYes
Changing the model or providerNo, by design, see above
Dragging a file in from your own computerNo. The agent runs on the server, which cannot see your local disk. Images are the exception: they are uploaded with the message. Reference other files by their path on the server.
Shell features only the desktop app has (tray, dock, native terminal dock)No
Biorouter Copilot (desktop observation and control)Only with --computer-use-approval, which sets the approval key a browser must enter. It controls the serving host's desktop, not the device the browser is running on.

Run it as a service

A systemd unit for a shared host. Give it a fixed token so the URL survives restarts, and keep the daemon under a dedicated account:

[Unit]
Description=Biorouter
After=network-online.target

[Service]
User=biorouter
Environment=BIOROUTER_DISABLE_KEYRING=true
# BIOROUTER_TOKEN=... , mode 0600, owned by the service account
EnvironmentFile=/etc/biorouter/serve.env
ExecStart=/usr/bin/biorouter serve --host 0.0.0.0 --port 8765 --token ${BIOROUTER_TOKEN}
Restart=on-failure

[Install]
WantedBy=multi-user.target

On a host with no desktop keyring, Biorouter falls back to a plaintext ~/.config/biorouter/secrets.yaml; BIOROUTER_DISABLE_KEYRING=true forces that behaviour explicitly. Restrict that file to the service account.

web (deprecated)

biorouter web is superseded by biorouter serve and is hidden from --help. It served a small chat page written by hand rather than the Biorouter interface, defaulted to port 3000 (colliding with the daemon), and shared one agent across every chat. It still runs and prints a notice pointing at serve; it will be removed in a later release.

The biorouterd daemon

biorouterd is the REST plus WebSocket agent server. The desktop GUI spawns it on an ephemeral local port and talks to it over HTTP and WebSocket using a typed client generated from the OpenAPI spec. You rarely start it yourself: biorouter serve starts and supervises it for browser access, and exported apps launch it on demand. Run it directly for automation, or when you want the API without an interface.

# Run the agent server (foreground, graceful shutdown on SIGINT/SIGTERM)
biorouterd agent
VariableDefaultDescription
BIOROUTER_PORT3000Port the daemon binds. This is the flat form (the Settings struct is flat); it is not BIOROUTER_SERVER__PORT.
BIOROUTER_HOST127.0.0.1Address the daemon binds.
BIOROUTER_SERVER__SECRET_KEYrandom per runAuth key required on requests. If unset, the daemon generates a random key for the process and logs a warning. The nested key uses the __ separator. In just debug-server mode this is test.
BIOROUTER_SERVE_UIunsetDirectory holding the built interface. When set, the daemon serves it at / in addition to its API, which is how biorouter serve reaches a browser. Unset, the daemon serves only its API, which is what the desktop app wants, since Electron loads the interface itself.
BIOROUTER_BROWSER_TOKENunsetThe token a browser must present once to receive a session cookie. biorouter serve generates and passes this; set it directly only if you are running the daemon yourself.

On start the daemon publishes its base URL as BIOROUTER_APP_BASE_URL so tools running inside the daemon process can emit absolute http://host:port/apps/<id>/ links. CORS is restricted to local origins. The daemon also exposes the same bundled MCP servers via biorouterd mcp <server>.

acp

Run Biorouter as an Agent Client Protocol (ACP) agent server so clients that speak ACP (for example Zed) can drive it. It speaks over stdio by default, or over a WebSocket with --ws. Clients normally launch and manage this process; you rarely run it by hand.

biorouter acp [--with-builtin NAMES] [--ws [ADDR]]
FlagTypeDefaultDescription
--with-builtin <NAMES>comma listnoneEnable included extensions by name.
--ws [ADDR]optional string127.0.0.1:11577 when the flag is given without a valueServe ACP over a WebSocket at ADDR instead of stdio. Used for artifacts that run an agent.

bench

Evaluate a system configuration across a range of practical tasks. Intended for benchmarking and model evaluation.

biorouter bench <init-config|run|selectors|eval-model|exec-eval|generate-leaderboard> [FLAGS]
SubcommandSynopsisDescription
init-configbench init-config -n <FILE>Write a starter config file.
runbench run -c <FILE>Run all benchmarks from a config.
selectorsbench selectors [-c FILE]List all available selectors.
eval-modelbench eval-model -c <CONFIG>Run an evaluation of a single model.
exec-evalbench exec-eval -c <CONFIG>Run a single eval.
generate-leaderboardbench generate-leaderboard -b <DIR>Generate a leaderboard CSV from a benchmark results directory.

completion

Generate a shell completion script.

biorouter completion <bash|zsh|fish|powershell|elvish> [--bin-name biorouter]
FlagDefaultDescription
--bin-name <NAME>biorouterCustom binary name to embed in the completion script.
# zsh: source the completion for the current shell
source <(biorouter completion zsh)

Running headless in a server or CI

biorouter run is the entry point for use without an interactive session. Combine a few flags for clean, scriptable behavior:

  • Provide the prompt with -t "...", an instruction file (-i file), stdin (-i -), or a workflow (--workflow name.yaml --params k=v).
  • Add --no-session so nothing is persisted, or -n name to keep a named session for later resumption.
  • Use --output-format json for a single result after completion, or stream-json to consume events as they occur; add -q/--quiet to print only the model response.
  • Pin the model with --provider and --model rather than relying on ambient config.
  • Bound the run with --max-turns and --max-tool-repetitions so an automated job cannot loop indefinitely.
# Non-interactive, isolated data dir, JSON out, bounded turns
BIOROUTER_PATH_ROOT="$(mktemp -d)" \
  biorouter run --no-session \
  --provider anthropic --model claude-sonnet-4-6 \
  --output-format json --max-turns 10 \
  -t "validate config.yaml and report problems"

Headless Linux servers

On a headless Linux host with no desktop keyring, Biorouter automatically falls back to a plaintext secrets.yaml for credentials; you can force this anywhere by setting BIOROUTER_DISABLE_KEYRING. Set BIOROUTER_PATH_ROOT to isolate config, data, and state per environment (useful for CI). The bundled local model server (Llama Server) needs glibc 2.35 or newer plus libssl3 and libgomp1, so Debian 12 / Ubuntu 22.04 or newer.

Environment variables the CLI honors

Environment variables override the config file for a single invocation. This is the subset that matters for the CLI. The Configuration page lists others.

VariablePurposeDefault
BIOROUTER_PROVIDERLLM provider to use.must be configured
BIOROUTER_MODELModel to use from the provider.must be configured
BIOROUTER_MODEPermission mode for tool execution: auto, approve, chat, smart_approve.auto
BIOROUTER_MAX_TURNSTurn limit without user input (the env form of --max-turns).100
BIOROUTER_CONTEXT_STRATEGYHow to handle a full context window: summarize, truncate, clear, prompt.prompt interactive, summarize headless
BIOROUTER_AUTO_COMPACT_THRESHOLDFraction of the context window at which the session compacts itself (0.0 disables).0.8
BIOROUTER_CLI_THEMECLI markdown theme: light, dark, ansi.dark
BIOROUTER_CLI_SHOW_COSTShow a cost estimate for each response in CLI output.off
BIOROUTER_DEBUGShow full tool parameters without truncation (the env form of --debug).off
BIOROUTER_DISABLE_KEYRINGStore secrets in plaintext secrets.yaml instead of the OS keyring (set to any value).unset (keyring on)
BIOROUTER_WORKFLOW_PATHExtra directories to search for workflows (separated like PATH).none
BIOROUTER_WORKFLOW_GITHUB_REPOGitHub owner/repo to resolve workflow names from.none
BIOROUTER_PATH_ROOTOverride the root for all config, data, and state (isolate environments).platform default
BIOROUTER_SESSION_IDSet by term init to bind a terminal to one session; read by term run/log/info.unset
BIOROUTER_TERMINALSet to 1 automatically while Biorouter runs a shell command, so your shell profile can adjust behavior.unset
ALPHA_FEATURESEnable experimental alpha features.off

For the variables specific to the daemon (BIOROUTER_PORT, BIOROUTER_HOST, BIOROUTER_SERVER__SECRET_KEY), see the daemon section above.

Features

Providers and models

Biorouter connects local models, models hosted by your institution, and commercial models through one interface, so you can match each task to the right trust boundary and switch whenever you want. Providers are grouped into three tiers. Local ranks first everywhere (onboarding, the Settings grid, and biorouter configure) because nothing leaves your machine.

The model picker in the app is the source of truth

Model lineups change constantly, so Biorouter does not ship a fixed list of models. It reads each provider's live catalog and shows it in Settings → Models (and via biorouter models list <provider>). Trust the picker for the exact models available to you today.

What a provider does ship is a default model: the one Biorouter selects when you configure that provider without naming a model. Those defaults are listed below. They were last checked against the source code on 2026-09-25.

Local: zero setup

Keeping data on your own machine gives the most privacy. Two providers run locally.

  • Llama Server (llamacpp) is the bundled option that needs no setup, and the first card a new user sees. The desktop app ships a pinned llama.cpp llama-server binary and manages it as a sidecar process, so you can run capable local models without installing anything else. Pick it, choose a model, and Biorouter downloads the GGUF weights from Hugging Face on first use and starts the server for you. No API key; nothing leaves the device after the first download.
  • Ollama (ollama) connects to an Ollama install you already run. Pull any model and select it; everything stays on your machine. Default model: qwen3.

The Llama Server catalog

Llama Server ships a short curated list, so you do not have to pick a quantisation or hunt for a repository. Any other model works too: type a raw owner/repo:QUANT Hugging Face spec instead of a catalog name. The download happens once, on first use.

ModelName in the CLIDownloadNotes
Gemma 4 E4Bgemma49.6 GBThe laptop default, chosen automatically below 64 GiB of memory the GPU can address. Around 4B active parameters.
Gemma 4 E2Bgemma4-e2b3.1 GBThe smallest option and the best first install on a 16 GB machine.
Gemma 4 12Bgemma4-12b7.6 GBThe default on machines with 64 GiB or more. Dense, quick to load, with a larger advertised context window.
Gemma 4 26Bgemma4-26b18 GBFor workstations with a lot of memory (48 GiB or more).
Gemma 4 31Bgemma4-31b20 GBThe largest curated Gemma 4 option; 64 GiB recommended.
Qwen3.6 35Bqwen3.624 GBA mixture of experts model, 35B total and 3B active. Fast per token once loaded, but a heavy download, so you choose it explicitly. It is never a default.
Qwen3.6 27Bqwen3.6-27b17 GBA dense Qwen3.6 option that needs less memory.

Download any of them in advance, without starting a chat: biorouter models local pull gemma4-12b.

Institutional: hosted by UCSF

Endpoints that UCSF manages keep prompts and completions inside UCSF's own cloud tenant. That is what makes them appropriate for sensitive work your institution has approved.

  • Versa API Azure (versa_azure) serves the UCSF ChatGPT models (OpenAI models inside UCSF's Azure tenant). Default model: gpt-5.5-2026-04-24.
  • Versa API Bedrock (versa_bedrock) serves the Anthropic models hosted by UCSF through Amazon Bedrock. Default model: us.anthropic.claude-opus-4-8.

Commercial cloud

Direct API access to hosted providers. Paste an API key (or complete the provider's sign in steps) and Biorouter reads that provider's live model catalog. The shipping commercial providers are below. The last two are different: they drive a vendor CLI you have already installed and signed in to, so they take no API key at all.

ProviderDefault modelNotes
Anthropicclaude-opus-4-8Direct access to Claude models.
OpenAIgpt-6-solDirect access to GPT models, including GPT-6 Sol, Astra and Luna.
Google Geminigemini-3.1-pro-previewDirect access to Gemini models.
GCP Vertex AIgemini-3.8-flashGoogle and Anthropic models through Google Cloud (service account or application default credentials). GCP_LOCATION may be a region, global, or the us or eu multiregional location. Gemini 3.x and Claude 5.x models go to the global endpoint automatically when it names a single region.
Azure OpenAIgpt-6-sol-2026-09-22OpenAI models on Azure; works with the Azure credential chain and single sign on. GPT-6, GPT-5.6, GPT-5.5 and GPT-5.4 use POST {endpoint}/openai/v1/responses with your deployment name as the model, so AZURE_OPENAI_API_VERSION applies only to the older Chat Completions models.
Amazon Bedrockus.anthropic.claude-sonnet-4-6Anthropic and other models on AWS (AWS credential chain, including SSO profiles).
Databricksdatabricks-claude-sonnet-4-6Claude, GPT, Gemini, and Llama models through Databricks (supports OAuth).
Snowflake Cortexclaude-sonnet-4-6Claude and other models through Snowflake Cortex.
OpenRouteranthropic/claude-sonnet-5A single API that fans out to many upstream providers.
LiteLLMgpt-4o-miniA proxy or gateway that unifies many backends behind an interface compatible with OpenAI's. The default is a placeholder; your gateway decides what is available.
Venice AIllama-3.3-70bAn inference provider focused on privacy (Llama and Mistral families).
GitHub Copilotgpt-5.3-codexGPT, Claude, Gemini, and Grok models through Copilot (OAuth with a device code, no API key).
X.AI (Grok)grok-4.7Direct access to Grok models from xAI.
z.ai (GLM)glm-5.3The GLM model family, through an API compatible with OpenAI's.
Xiaomi MiMomimo-v2.6-flashXiaomi's MiMo models, with regional endpoints.
Tetrate Agent Routerclaude-haiku-4-5A routing service across upstream models (the quickstart path).
AWS SageMaker TGInoneModels you deploy on SageMaker endpoints using Text Generation Inference. You name the endpoint, so there is no default model.
DeepSeekdeepseek-flashDeepSeek models, through an API compatible with OpenAI's (DEEPSEEK_API_KEY).
Groqopenai/gpt-oss-120bOpen weight models served on Groq hardware (GROQ_API_KEY).
Inceptionmercury-2.5Inception's diffusion language models (INCEPTION_API_KEY).
Mistral AImistral-medium-3-5Direct access to Mistral models (MISTRAL_API_KEY).
Moonshot AI (Kimi)kimi-k3The Kimi model family (MOONSHOT_API_KEY).
Claude Codeclaude-opus-5-5Runs inference on your own Claude subscription by driving the claude CLI you have already installed and signed in to. No API key and no base URL; Biorouter never sees a credential. Override discovery with CLAUDE_CODE_COMMAND. It is a public provider, so it carries no BAA and must never see PHI.
Codexgpt-6-astraThe same arrangement on your own ChatGPT subscription, driving the codex CLI. Override discovery with CODEX_COMMAND. Also a public provider, so never for PHI.
Custom (compatible with OpenAI)noneAny endpoint compatible with OpenAI's API, added through the "Add custom provider" card (display name, base URL, key variable, models, streaming).

Where the cell reads none the provider carries no default model, so you choose a model when you configure it. Run biorouter models providers for the current list.

Adding a provider

Providers are managed in Settings → Models. Each card shows its status (configured or not), a Configure button to enter an API key or credentials, and a Launch button to switch to that provider and choose a model. Paste your key, pick a model from the live catalog, and you are ready. Keys are written to your operating system's credential store, not to any config file. From the terminal, run biorouter configure and select "Configure Providers".

Switching per session or per workflow

Your default provider and model apply until you change them, but you can override the choice without touching that default:

  • Per session. Start a session with biorouter session --provider <name> --model <id>, or switch in the desktop app from the model selector.
  • Per workflow. A workflow can set settings.biorouter_provider and settings.biorouter_model so it always runs on a specific model, whatever your default is.
  • Lead and worker routing. A lead model can orchestrate a task and delegate parts of it to worker models, which may be on different providers.
Features

Extensions and skills

Biorouter connects to databases, APIs, file systems, and services through pluggable parts instead of special cases written into the app. Extensions add tools the agent can call over the Model Context Protocol (MCP); skills teach the agent repeatable methods for using those tools; and the BAAM marketplace installs both in one click. Add a capability once and it works in every session. This section covers biorouter 1.91.2.

What an MCP extension is

An extension is an MCP server that Biorouter connects to. Because MCP is an open standard, any server anyone writes can become a Biorouter extension. An MCP server can expose three kinds of thing:

  • Tools the agent can call (run a query, edit a file, fetch a URL).
  • Resources the agent can read (files, records, data sources the server makes available).
  • Prompts the server offers as starting points.

Biorouter scans every extension for known malware before it starts. Enable or disable any extension from Settings → Extensions in the desktop app, or with biorouter configure in the terminal.

Included extensions

These are included in Biorouter, so nothing needs to be installed. The extensions that are on by default are the ones most sessions use. Turn on the others when a task needs them. In the app, these extensions show a "Built-in" badge.

ExtensionDefaultWhat it doesKey tools
DeveloperOnThe core agent toolkit: file operations, shell commands, code search and text editing. Its shell and text_editor tools run with your user privileges, so it carries the most security guidance of any extension.shell, text_editor, analyze, image_processor
Extension ManagerOnLets the agent discover, enable, and disable other extensions during a session, keeping the active tool count small. It also searches the trusted BAAM marketplace, and, each behind your approval, installs a package the chat needs but you don't have, or permanently deletes an installed one you no longer want. It runs a malware check before it enables an extension that launches a package runner.search_available_extensions, search_marketplace_extensions, manage_extensions, install_extension, delete_extension_package, list_resources, read_resource
SkillsOnDiscovers skills on disk at startup and loads the relevant ones into the agent's context (see Skills below).Loads SKILL.md instruction sets from the skill directories
TodoOnBreaks work with several steps into a tracked checklist and reports progress as the agent goes, so you can see where it is rather than waiting for one opaque answer.todo_write, todo_add, todo_update, plan_write
KnowledgeOnIngest, query, and lint your personal knowledge bases, which the model maintains, from inside any chat. Bases are markdown pages backed by git history.ingest, query, lint, plus page, search, and graph reads
MemoryOnTeaches the agent durable facts and preferences (commands, lab conventions, configurations) that ride along in every prompt. A memory applies to one project, or to all your projects.remember_memory, retrieve_memories, remove_memory_category, remove_specific_memory
Auto VisualiserOnTurns structured data into interactive HTML figures that need no other files, opened from a card in chat and rendered in the artifact side panel. One call draws any of 32 figure kinds (charts, scientific plots, diagrams and maps), and a second combines several into one report.render_figure, describe_figure, render_dashboard
Biorouter CopilotOn; task approval requiredNative desktop observation and control. Each chat has separate observations and approval; public models may receive visible app content. The helper controls the backend host.list_apps, get_app_state, click, perform_secondary_action, scroll, drag, type_text, press_key, set_value, screen_capture
Web & DocumentsOnURL fetching, Office/PDF document utilities and caching, independently of desktop availability.web_scrape, xlsx_tool, docx_tool, pdf_tool, cache
Chat RecallOffSearches your past session history by keyword or session ID so the agent can pull earlier context into the current conversation. Search runs entirely against local session history; nothing is sent to a remote service.chatrecall (search mode or load mode)
Workspace ControlOnLets the agent work across your conversations: open one in a tab, split, or window, read what another has done, prompt or steer it, wait for it, and change the extensions, skills, model, or knowledge bases it uses (see Workspace control). Delegating to a subagent needs no extension enabled. These tools, which work across conversations, do.workspace_open, workspace_list, workspace_read_conversation, workspace_send_prompt, workspace_set_tools, workspace_watch, workspace_close, subagent
Code ExecutionOnBacks Code Mode: instead of calling tools one at a time, the model writes one short JavaScript program that batches many tool calls into a single execution, using the context window more efficiently.execute_code, search_modules, read_module
Agent DrafterOnBuilds Biorouter apps: TypeScript front ends, each wired to its own live agent, and exports them as standalone, directly runnable projects (see the Apps & Agent Drafter section).create_app, configure_app, build_app, export_app, plus the ui_* tools
Desktop control requires task approval. Biorouter Copilot requests approval before observation or action, then continues that authorized task without repeated prompts. Stop revokes control. OS permissions remain separate. Private and public chats keep separate observations and grants, but share the physical desktop. Acknowledge a handoff from a private chat to a public one before capture. Developer file and shell tools keep their ordinary permission mode and file access checks.

Adding an extension

Any server that speaks MCP can be added as an extension. There are two routes, both of which write to the same configuration.

From the BAAM marketplace

BAAM is Biorouter's agent, extension, and skill marketplace, served from the public site and browsable at the BAAM page. Its catalog is a registry the app reads to list and install items. For a curated extension this is the shortest path: download the .brxt bundle and drag it into Extensions → Add Extension. Biorouter installs the environment, configures the tool, and adds it to your session, with no terminal needed.

Adding a custom extension

For anything not in the catalog, open Settings → Extensions → Add custom extension and pick the transport. A local command server (stdio) is the common case; a remote server uses streamable_http.

1

Command / stdio server

Biorouter launches a local process (typically a uvx or npx MCP server) and talks to it over standard I/O. You provide: the type (stdio), an id and display name, the command, its arguments, any environment variables (such as an API token), and an optional timeout.

extensions:
  github:
    name: GitHub
    cmd: npx
    args: ["-y", "@modelcontextprotocol/server-github"]
    type: stdio
    enabled: true
    timeout: 300
    envs:
      GITHUB_PERSONAL_ACCESS_TOKEN: "<your_token>"
2

Remote / streamable_http server

For a server that already runs somewhere and is reached over a URL, you provide the type (streamable_http), an id and name, the URL, and an optional timeout. No local process is launched.

extensions:
  my-remote-agent:
    name: My Remote Agent
    url: https://my-mcp-server.example.com/mcp
    type: streamable_http
    enabled: true
    timeout: 300

The same entries can be declared directly under extensions: in ~/.config/biorouter/config.yaml, or added for a single session from the CLI:

biorouter session --with-extension "TOKEN=<t> npx -y @modelcontextprotocol/server-github"
biorouter session --with-streamable-http-extension "https://my-mcp-server.example.com/mcp"

Enabling and disabling during a session

You can turn extensions on and off during a running session without restarting. Toggle any extension by hand from Settings → Extensions, or let the agent manage them: the Extension Manager recognizes when a task needs a specific extension, enables it, and suggests disabling unused ones when the tool count starts eating your context window. An extension the agent enables this way is active for that session only; to persist it, enable it through Settings or the config file.

Extension agents in the marketplace

BAAM features a set of extension agents that connect Biorouter to specialized data and services. Each installs as a .brxt bundle. Several are UCSF connectors that need institutional credentials.

The Privacy column is the extension's tier: the same one BAAM shows as a badge on the card, and the one Biorouter enforces at runtime while privacy tiers are on. With them on, an agent marked Private reaches data your institution governs, and its tools are refused in a chat bound to a public model; a Public one is not held back by the tier, though it still has to be installed, enabled, and permitted like any other extension. Turning privacy tiers off in Settings → Privacy removes that enforcement without changing any tier below.

The tier comes from the marketplace registry that ships with the app, not from anything a .brxt bundle says about itself, so an extension cannot declare its own. It is resolved by the name the extension is installed under, so renaming one locally does change which tier it resolves to. Every agent the registry tags Private is listed below; the Public rows are a selection, not the whole marketplace. The table is checked against the registry by Biorouter's own check suite and again when this site deploys, rather than maintained by hand. See Vaulting & security for what a model that is not private can and cannot reach.

AgentPrivacyWhat it connectsCredentials
SPOKEAgentPublicCypher queries on the SPOKE biomedical knowledge graph (diseases, genes, proteins, drugs, pathways).SPOKEAGENT_PASSCODE from the UCSF wiki credentials page.
UCSFOMOPAgentPrivateSQL written from plain language over the UCSF OMOP deidentified clinical database. It cannot change the data.UCSF credentials.
CDWAgentPrivateMultimodal access to the UCSF Clinical Data Warehouse: cohorts, labs, imaging, notes and NLP. It cannot change the data.UCSF network credentials (CAMPUS\username).
PlaywrightAgentPublicBrowser automation: navigate pages, extract content, and fill forms. No vision model needed.None. Requires Node.js.
CodeGraphAgentPublicA code knowledge graph, indexed in advance, across 23 languages ("who calls X?", "what breaks if I change Z?").None.
BiorOfficePublicCreate, read, and edit Word, Excel, and PowerPoint files from chat.None. No Microsoft Office install needed.

Skills

A skill is a reusable instruction set: a folder containing a SKILL.md file with YAML frontmatter (name, description) followed by freeform instructions that teach the agent to do one thing the same way every time. Unlike extensions, which add tools, skills add procedural knowledge: checklists, deployment procedures, analysis conventions, and API guides. A skill folder may also carry helper scripts and templates the agent reads while it runs.

Skills work two ways:

  • Applied automatically: at session start Biorouter discovers every available skill and loads a relevant one when your request clearly matches its purpose, without you naming it.
  • Run by name: name a skill to run it deliberately, for example /code-review, or in plain language ("use the code-review skill on this PR"). Ask "what skills are available?" to see the loaded list.

A skill's identity comes from the name in its frontmatter, not from its directory name, so a folder named run-gwas/ that declares name: gwas-pipeline is known to Biorouter as gwas-pipeline. When two skills share a name, the more specific location wins.

Installing and combining skills

Install a skill by dragging its .zip onto Skills → Add Skill in the app, with biorouter skill install ./bundle.zip, or in one click from BAAM. Around 129 skills are published through the marketplace, grouped into core, developer, and biomedical categories (single cell analysis, variant calling, differential expression, pathway analysis, clinical biostatistics, and more). Global skills that belong to Biorouter live under ~/.config/biorouter/skills/; project skills live under ./.biorouter/skills/, and portable locations shared with other AI agents (~/.config/agents/skills/, .agents/skills/) are also read. Skill folders are plain text, so a lab can share them to standardize analysis style without sharing any data. Because skills are instructions, the agent can apply several at once in a single task, for example a scripting skill together with a visualization skill.

When a chat is not enough

Extensions add tools and skills add procedure, but some workflows need their own interface rather than a transcript. For those, Biorouter builds and runs apps: full pages driven by a dedicated agent, covered in the next section, Apps & Agent Drafter.

Features

Apps & Agent Drafter

The Agent Drafter extension, included with Biorouter, builds Biorouter apps. Each is a TypeScript front end (an index.html plus src/main.ts) wired to its own Biorouter agent over a WebSocket. The distinguishing point is that the agent drives the interface rather than only answering inside it: it renders panels, charts, and graphs into the page, highlights regions, switches themes, and asks the user questions. Reach for an app when a workflow needs a richer surface than a transcript: a cohort reviewer, a calculator, a knowledge map explorer, a data dashboard, or a tool for one lab. Apps live under ~/.config/biorouter/agent_drafter/ and are served by the local daemon; the desktop app opens them in your browser, and the Applications tab manages them.

The Apps SDK

Every app imports a small client runtime and talks to its agent over one WebSocket. The SDK provides:

PieceWhat it provides
br.* client runtimePrompt, stream, cancel, subscribe to lifecycle events, and read context usage. br.model lists providers and switches the session model while it runs; br.kb reads and ingests into granted knowledge bases; br.state exposes the shared document; br.agent(name) reaches a worker profile.
Component catalogUI primitives the agent drives (panels, charts, graphs, tables, highlights, notifications) that the SDK applies to the page. Authors expose render targets with a region attribute such as <section data-br-region="results">, which the agent finds with ui_describe and writes to.
App contractThe manifest's surface block declares the app's state schema, the actions the agent may call (via app_call), and the signals the page emits back, so both sides work against a typed interface that the server enforces.
Shared reactive state documentOne state document the app and agent both read and write (br.state), so the UI stays consistent across turns and across reconnects. Declarative data-br-bind attributes keep page elements in sync without any wiring code.
Security gated by capabilityUI control is on by default, because its blast radius is the app's own page. files, data, compute, and the vault capability (encrypted credentials) are denied by default and granted explicitly, per app.
Theme packsAn app inherits Biorouter's look, and the agent can restyle it within allowed bounds using six theme packs (base, clinical, lab notebook, terminal, journal, midnight), accents, and custom tokens.
Worker profiles for several agentsAn app can declare named worker profiles, each a full alternate agent config (its own model, prompt, extensions, and KB) validated to be a capability subset of the app. The main agent consults them for smaller questions that stand on their own.

The agent drives the app

Authors mark render targets with a region attribute, for example <section data-br-region="results">. The agent discovers them with ui_describe (its first call in a fresh app) and then writes to targets like @region:results, @panel:<id>, or @main through typed tools, each pushing a frame down the app's socket that the runtime applies to the page:

ToolWhat it does
ui_describeInventories the page: regions, panels, declared actions and signals, and current state.
ui_panel · ui_renderOpen a dock panel, or render widgets (cards, tables, stats, forms, markdown) into any target.
ui_chart · ui_graph · ui_figureDraw charts, network graphs, and Auto Visualiser figures.
ui_highlight · ui_notifyPoint at a region, or toast a status message.
ui_theme · ui_layoutRestyle the app within its allowed bounds; rearrange the declared layout.
ui_state · ui_patch_stateRead and patch the shared state document the page is bound to.
ui_askShow a blocking form and wait: the tool call does not return until the user answers, so the agent can branch on the reply inside a single turn.
app_callInvoke an action the app registered with br.actions.register, and get its return value.

Archetypes

New apps start from one of six working archetypes rather than a blank page: explorer (graph plus inspector and search), dashboard (a KPI grid bound to state), workbench (table, row selection, detail pane), wizard (a staged form), canvas (a surface the author draws), and chat (a plain conversation panel). Each starter passes lint, declares a matching app contract, and runs before you change a line.

Building and exporting an app

Agent Drafter exposes tools for the whole lifecycle. create_app scaffolds a project (a working starter archetype plus a manifest); configure_app and update_app set the persona, model, capabilities, and edit the source; build_app bundles src/main.ts with esbuild, refreshes the vendored SDK, and runs its lint checks; launch_app and preview_app open the result; and export_app writes a standalone folder. You can also ask in chat: "build me an app that reviews this cohort" reaches the same tools. From the terminal, biorouter apps list, biorouter apps open <id>, and biorouter apps serve <id> mirror the desktop's Applications tab.

Exported apps are directly runnable, with no Node required

export_app writes a complete project that runs without a build step: a manifest.json, the bundled front end, launch scripts (run.sh / run.command / biorouter-launch.sh), and a small loopback server that proxies to a local biorouterd daemon. The launcher locates or installs the daemon, starts it headlessly, verifies the app responds, and opens it. Exported apps carry no API keys; they inherit the credentials of whoever runs them.

Security model

Apps are treated as untrusted pages. Each session gets a WebSocket token for that app. The token is never written to disk and is accepted only from a loopback origin. Everything the page sends the agent is wrapped in a data envelope that the system prompt marks as content, not instructions. State bindings only set text and attributes on a strict allowlist, and they never execute code. Raw HTML rendering is off unless the manifest enables it, and the server sanitizes it even then. Knowledge access is limited to the exact bases the manifest grants. One routing rule is always enforced: an app holding sensitive data, such as a clinical database source or a writable knowledge base, may not route its turns to an external commercial provider. It stays on local or institutional models.

Features

Knowledge bases

A knowledge base is a personal wiki that a model maintains: a folder of markdown pages backed by a full git history, all on your own machine. You do not edit it by hand. You add sources (a file, a URL, or pasted text) and Biorouter converts each one to markdown, has a bounded subagent digest it into linked pages, grades the source's credibility, and commits the change. Because a base is plain markdown under git, everything about it stays local, readable, diffable, and reversible. This section covers the whole feature, then Soul, the one knowledge base Biorouter ships and grows for you automatically. Documented for Biorouter 1.91.2.

What a knowledge base is

Each knowledge base is one directory and one git repository, stored under ~/.config/biorouter/knowledge/<kb-id>/. Inside it, the raw sources you added and the pages the agent wrote are kept separate, so you can always derive a page again from its original:

PathWhat it holds
raw/<source-id>/Each ingested source, untouched: the original file, the markdown Biorouter converted it to (source.md), and a meta.yaml with its title, URL, checksum, and credibility grade.
knowledge/The pages the subagent writes: entities/ (people, tools, datasets), concepts/ (methods, ideas), sources/ (one page per source), notes/ (observations and saved answers), and hub pages at the root that span topics.
index.mdA catalog of the pages in the base, which the agent maintains.
log.mdA change log for people to read, which mirrors the git history.
schema.mdInstructions for this base that tell the agent how to maintain this base. You can edit it.
.git/The hidden git repository. Every ingest, link, and edit is a commit. Git is statically built into Biorouter, so no system git is required.
Local by design. Bases never leave your disk. The only network calls Biorouter makes for a base are credibility lookups (Crossref and OpenAlex) and the model you choose to run the digest. You can keep as many bases as you like; the design targets a handful of bases, each up to a few hundred pages, not a search index over thousands of documents.

Creating a knowledge base

In the desktop app, open Components in the sidebar, then Knowledge. The knowledge base selector at the top opens a palette like the Cmd+K / Ctrl+K palettes in other apps, where you name a new base and pick its color. From the terminal:

biorouter knowledge create my-kb --name "My KB"

Either way, Biorouter writes the directory, initializes the git repo, seeds a default schema.md, and registers the base so it appears in the selector and in chat.

The active knowledge base

One base at a time is the active base for a chat session. The active id is remembered per session and persisted at ~/.config/biorouter/knowledge/.active-kb, so the base you are working in travels with the conversation. In chat, a small KB chip sits in the composer next to the model selector; click it to open the same palette and switch bases. When a knowledge tool is called without an explicit base id, it acts on the active base.

Biorouter uses a model where you hide bases from the agent, rather than one where you add them: every base is visible to the chat agent unless you hide it, and the agent may consult a visible base on any turn. Hiding a base keeps it out of the default search across bases, but you (or the agent) can still reach it by naming its id.

Ingesting sources

Ingesting is how material gets into a base. The Knowledge route has an Ingest sources panel with three ways to stage a source, and the same three are available from the CLI and to the chat agent:

  • Drag and drop files onto the dropzone (or use Browse). Each file is added to a staged list.
  • Paste text. Paste notes or an excerpt. Biorouter scans the text for http(s) URLs and offers to fetch and convert each linked page as its own source; you can toggle any link off before staging.
  • Add a URL. Biorouter downloads the page and runs it through the same converter as a dropped file.

Supported formats for the deterministic converter: PDF, DOCX, HTML, CSV, Markdown, and plain text. Spreadsheets (.xlsx, .xls, .ods) and PowerPoint (.pptx, including speaker notes) also ingest. Conversion runs once and is immutable, so its quality bounds everything downstream: whatever a converter drops (reading order across columns, a table, a slide note) the digest step never sees. A scanned PDF that holds only images ingests with a warning that its text is incomplete.

How the digest subagent works

Once a source is converted, Biorouter runs a bounded digest subagent. It is a small agent loop (capped at roughly 30 steps and a few minutes) that can only touch the knowledge base, and it is steered by the base's schema.md. Reading only the converted source.md, it writes a page for the source, creates or updates the entity and concept pages the source touches, and connects related pages with [[knowledge-link]] cross references. Those wiki links are exactly what the graph is built from, so a base whose pages carry no [[…]] references produces a graph with nodes but no edges.

Everything the subagent does for one source is saved as one atomic git commit: it writes to a working branch and commits the whole set of page changes together (or aborts and leaves nothing behind), so the base is never left partly updated. The UI shows progress live over server sent events, so you see pages and graph nodes appear while the ingest runs.

Source PDF, URL, text Convert Digest agent writes [[links]] Wiki pages + git commit Graph
A source becomes interlinked wiki pages: convert the file, let the digest agent write pages with cross links, commit to git, and render the graph.

The graph and credibility colors

The Knowledge route renders the base as a force directed graph: each page is a node, each [[…]] reference is an edge. Hub pages are drawn larger and labeled. Node color encodes the page kind, and source nodes are colored by how credible their source is, so a glance separates material with good support from anecdote:

NodeMeaningColor
HubA page at the root of the base that spans topics, high in the graph's connectivity.Gold
EntityA person, tool, dataset, or other named thing.Blue
ConceptA method, idea, or approach.Green
NoteA single observation or a saved query answer.Grey
FlagA page the agent marked as a contradiction to resolve.Red

Source nodes take their color from a credibility ladder. Biorouter grades each source deterministically before it ever calls a model: it pulls any DOI, arXiv id, ISBN, or PMID from the source, looks it up in Crossref and then OpenAlex, and falls back to host patterns (preprint servers, .gov, .edu, and the like). Only if all of that is inconclusive does a small bounded classifier weigh in.

TierHow it is detectedColor
Peer reviewedDOI resolves to a journal article from a known publisher.Deep blue
BookISBN present, or Crossref reports a book or book chapter.Blue
PreprintHost is a preprint server (arXiv, bioRxiv, medRxiv, etc.).Light blue
Gray literatureHost matches .gov, .edu, WHO, CDC, NIH, FDA, ClinicalTrials.gov.Pale blue
Web sourceAny other web page.Warm orange
Personal sourceA local file, pasted text, or a source with no detectable provenance.Mauve

Retraction is a separate flag: when Crossref or OpenAlex report a source as retracted, its node carries a red badge regardless of tier. You can override any grade by hand. The graph's legend shows Entity, Concept, Hub, Peer reviewed, Web source, and Personal source so the coloring is readable in place.

Search, history, and portability

  • BM25 search. Every base is indexed for BM25 keyword search across its written pages and the raw source.md files, so the agent (and the query macro) can find the right pages fast without reading everything again.
  • Change log and git history. The base's history is a git log; each commit is tagged by kind (ingest, link, flag, query, lint, restore). The change log drawer lists these entries, and log.md mirrors them in plain prose.
  • Restoring a previous version. Pick a past commit to preview the base as it was at that point, then restore it. Restore is a new commit that reverts to that point, on top of the current state, not a destructive rewind, so the restore is itself logged and can be undone.
  • Export and import a .brkb archive. A .brkb file is a zip of the entire base directory, including the .git history and the original source files. Export from the base header (Export as .brkb) to move a base between machines or hand it to a colleague; import unpacks it as a new base with a fresh id so it never collides with an existing one.

The macros

Three higher level operations each run their own bounded subagent loop:

  • Ingest is the digest described above: add a source, classify it, write and link pages, commit as one change.
  • Query searches the base and writes a cited answer. Optionally it files the answer back into the base as a new note page and commits it, so the base learns from your questions.
  • Lint is a hygiene pass that finds orphan pages, contradictions, and stale claims. It returns a report, and with autofix enabled the subagent repairs what it can.

All three are available in the app and from the CLI:

biorouter knowledge ingest --kb my-kb --file ./report.pdf
biorouter knowledge ingest --kb my-kb --url https://example.com/paper
biorouter knowledge query "what does the cohort show?" --kb my-kb --save
biorouter knowledge lint  --kb my-kb --fix

The Soul knowledge base

Soul, the included knowledge base with the id soul, is the one base Biorouter creates and maintains for you. It is installed the first time you run Biorouter and starts empty. Its job is to accumulate durable, useful facts about you: how you frame scientific questions, which tools and commands you reach for, the tool responses you act on, and personal details you reveal such as your name, role, and stated preferences. Over time it becomes the agent's memory of your work, which it consults to personalize answers.

Soul grows on its own through an included scheduled job called Daily Meditation. Every day at 3:00 AM, that job runs the included Meditation workflow, which uses the update-soul skill to review your recent real chat sessions and digest what matters about you into the Soul base (it skips the sessions of its own scheduled job, greetings, and casual chatter). Because the workflow focuses on the Soul base and runs headless, you do not have to do anything for Soul to keep up with your work. See the scheduler section below for how that job is registered.

  • Where it lives: ~/.config/biorouter/knowledge/soul, the same layout as any other base, in a warm parchment color that sets it apart in the selector.
  • How to view it: open the Knowledge route and select Soul in the base selector to browse its pages, graph, and change log. In chat, search it directly with kb_search using kb_id="soul". Soul may be hidden from the default search across bases, so name its id explicitly when you want personal context.
  • How to reset it: resetting Knowledge removes every base and recreates a single empty Soul, so you can clear what the agent has learned and start over. Because a reset is destructive, it is a deliberate action, not something the chat agent can do on its own.

Soul is one specific knowledge base. Everything in the rest of this section (creating a base, ingesting, the graph, the macros) applies to it exactly as it does to any base you make yourself.

Step by step

1

Create a knowledge base and ingest your first source

Open Components in the sidebar, then Knowledge. Use the base selector's palette (Cmd+K) to create a base and give it a name. In the Ingest sources panel, drag a PDF onto the dropzone (or paste text, or add a URL), then click Digest Staged Sources. Watch the streamed progress as the subagent converts the source, writes its pages, and links them; when it finishes, the new nodes appear in the graph and a new entry lands in the change log. From the terminal the same flow is biorouter knowledge create my-kb --name "My KB" followed by biorouter knowledge ingest --kb my-kb --file ./report.pdf.

2

Let the agent read a knowledge base in chat

In a chat session, click the KB chip in the composer and select the base you want (for example your new base, or Soul). That base becomes the active base for the session. Now ask a question that the base can answer; the agent searches the visible bases with BM25, reads the relevant pages, and answers with citations back to them. To pull in personal context specifically, ask about your own preferences or working style and the agent consults Soul by its id. Everything the agent reads stays on your machine.

Features

Crew

Crew is the part of the Biorouter desktop app where your lab works together: channels, shared files, and AI agent tasks that the whole channel can see. A lab's shared space is a workspace. One member, the host, runs it on a shared Linux server under their own account. Every other member connects with their own account on that server over SSH. The Crew manual covers every dialog, message and command. Documented for Biorouter 1.91.2.

The examples use the workspace chen-lab on the server lab.example.edu, hosted by Alice Chen (@alice), and the member Bob Lee (@bob). Text in braces, such as {team}, stands for a name Crew fills in.

What Crew is

  • Open Crew from Crew in the Biorouter sidebar, below New chat.
  • A workspace holds teams, and a team holds channels. You see only the channels you are in. Crew has no direct messages.
  • Only the host invites people, lets them in and removes them. A channel owner, at first its creator, manages each channel.
  • Privacy is Private or Public. It decides which AI models may read the workspace, not which people can see it.
  • Each channel is labeled "Restricted", which only private models may read, or "Public-safe".
  • The desktop app and the biorouter crew commands use the same background service on your computer.

What you need

You needDetails
The Biorouter desktop appTested on macOS. The biorouter crew commands also work in a terminal.
An account on the lab's Linux serverYour own login, with an SSH key, a password or a verification code. Your IT team provides it.
biorouter-crew in your server accountEvery account that connects, the host's included, needs its own copy. You install it in your own account, or IT does. See Server setup for administrators.
The server already verifiedCrew connects only to a server whose SSH host key is in your known hosts file. Check the server's fingerprint with your IT team once.
An invitationThe host sends it. It expires after 24 hours.

The approval secret

On a Mac or a Linux computer, the background service that the app and the command line share acts for you only with your approval secret. The first time Biorouter starts the service, it asks you to choose one.

  1. In the window "Set approval secret for shared BioRouter daemon", enter 32 to 4096 letters, numbers and punctuation marks, with no spaces. You can paste it.
  2. Save the secret in your password manager. Biorouter does not save it.
  3. Enter it again in "Confirm shared daemon approval secret". Biorouter opens.

When the service is already running, the app asks for the secret in "Connect to existing BioRouter daemon". Closing the app leaves the service running.

If you forget the secret, restart your computer. Biorouter then asks you to set a new one. Open Crew and choose Connect to chen-lab.

Windows has no approval secret. There, closing the app stops the service, and the biorouter crew commands do not work.

The Crew window

The first Crew screen offers Join a workspace and Host a new workspace.

PartWhat it holds
Workspace menu (the workspace name at the top of the Crew sidebar)"Hosted by Alice Chen (@alice)", the fingerprint, People…, Privacy…, Agent access…, Create team…, Disconnect, Connection settings… and Add a workspace. Reconnect appears while you are not connected or wait to join, and Switch workspace when you have more than one workspace. The host also sees Invite people to chen-lab….
Status rowThe connection status and the privacy chip, such as "Private · UCSF".
SidebarTeams and their channels, with unread counts, and Add team and Add channel. The host also sees "Waiting to join".
Connection barA note and a button, such as Retry, when something needs attention.
Channel detailsThe tabs About, Members, Files and Agent access.

Join a workspace

Send the host your exact username on the server. The host sends back an invitation message that ends with a line starting brcrew1:. It holds no secret.

  1. In Crew, choose Join a workspace. If you already have a workspace, open the workspace menu and choose Add a workspace, then Join a workspace….
  2. Paste the whole message into Invitation from your host. Crew shows the workspace, its host and its privacy. If any of these is wrong, choose Cancel.
  3. Check Your username on lab.example.edu. It is your server login, not your email address.
  4. Choose Join chen-lab. If the server asks for a password or a verification code, type it in the "Sign in to lab.example.edu" window and press Enter.
  5. Crew shows "Send Alice this code:" and your code. Choose Copy and send the code to the host.
  6. Wait while the status row reads "Not joined yet". If you quit Biorouter meanwhile, reopen it and open Crew. After a computer restart, or on Windows, choose Connect to chen-lab.

When the host enters your code, the workspace opens by itself. If Crew says "Ask Alice Chen (@alice) to add you to a team.", ask the host to add you to one.

Your code is not the fingerprint. The Join dialog also shows the workspace fingerprint. Never send it. To check an invitation, ask the host to read the fingerprint from their workspace menu. If the two differ, do not join.

For a second computer, ask the host to invite you again with Add another device for @bob turned on. Details: Joining a workspace.

Host a workspace

Before you start, you need a login on the server, biorouter-crew in your server account, the server in your known hosts file, and your institution's short ID, such as ucsf.

  1. In Crew, choose Host a new workspace, or open the workspace menu and choose Add a workspace, then Host a new workspace….
  2. Type a Workspace name. Anyone who can sign in to the server can see it, so keep patient and sample IDs out of it.
  3. Type Your server login, such as alice@lab.example.edu. Keep Private, check the institution, and choose Continue.
  4. Choose Start it for me. If the server asks for a password or code, open Run it yourself in a terminal instead, run its commands on the server, and paste their output into Paste what it printed.
  5. Choose Create workspace. This computer becomes the workspace's first admin device.
  6. When Crew asks "Mark chen-lab as a UCSF workspace?", choose Mark as UCSF. You cannot change it later. Agents cannot work in a Private workspace until it is set.

The "Get chen-lab ready" checklist lists the remaining steps. Set your name before you invite anyone, because each invitation carries it.

Invite people and let them in

  1. Open the workspace menu and choose Invite people to chen-lab….
  2. In Username, type the person's server login, such as bob, and choose Invite.
  3. Choose Copy and send the invitation to the person, with the server's SSH fingerprint if they have not used this server before.
  4. When the person sends their code, choose Let in… beside their name under "Waiting to join", paste the code, and choose Let Bob in. When their computer checks in, the dialog reads "Bob joined chen-lab".
  5. Tick channels under "Channels in {team}" and choose Add to {team}. A person in no team sees no channels.
Approve only codes the person sent you. If Crew says "A computer trying to join as @bob showed a different code.", compare it with the code the person sent. To correct a mistyped code, choose Let in…, enter the right code, and choose Replace code.

People… and Privacy… in the workspace menu rename the workspace, cancel invitations, remove people and change the workspace privacy. Nothing is ever deleted from the workspace's history. After the server restarts, start the workspace again, as Server setup for administrators shows. Details: Hosting a workspace.

Teams, channels and people

TaskWho can do itHow
Create a teamAnyone in the workspaceChoose Add team at the end of the team list, type a Name, and choose Create team. The team opens on its new #general channel.
Rename a teamThe person who created itChoose ⋯ beside the team, then Rename team….
Create a channelAnyone in the teamPoint at a team, choose +, type a Name, pick Restricted or Public-safe, and choose Create channel. You cannot change the label later.
Add peopleThe team's creator or the channel owner, and the hostChoose ⋯ beside a team, then Add people to {team}…. Tick people, tick channels under Also add to, and choose Add. Add people… in a channel menu appears only for the channel's owner, so the host adds people to other channels from the team's dialog.
Rename, archive or hand over a channel, or remove its membersThe channel ownerThe channel menu, opened from the channel name, has Rename…, Transfer ownership… and Archive channel…. Archiving cannot be undone. Remove people in the Members tab.
Remove someone from the workspaceThe hostPeople… in the workspace menu
Set your display nameYouChoose the You row, then Edit profile…. Type a Display name and choose Save profile.

People you add do not need to accept. An agent cannot add people. To leave a channel, ask its owner to remove you. Keep patient and sample IDs out of team and channel names. Details: Teams, channels and people.

Messages and files

  • Type in the message box. Enter sends, and Shift+Enter starts a new line. Messages use Markdown.
  • If sending fails, your text stays in the box with "Couldn’t send." and the reason. Press Send again. An unchanged message is never posted twice.
  • Unsent text stays in each channel's message box until you quit Biorouter.
  • Crew sends no system notifications or sounds, and typing @bob does not notify Bob. New messages show as bold channel names with a count in the Crew sidebar.
  • You cannot edit or delete a posted message. To search messages, use biorouter crew search.

Share a file

  1. Choose the paperclip, then Upload a file…, and pick the file. You can also drag a file onto the channel, or paste a copied file into the message box. For a dragged or pasted file, check the full path in the "Share file to Crew" window and choose Share.
  2. Wait until the line "Press Send to share it." appears.
  3. Press Send. The file appears in the channel as a card with its name and size.
An upload cannot be deleted. The file leaves your computer as soon as you confirm, even if you then remove it from your message.

A file can be up to 1 GB. Crew refuses folders and credential files, such as .env, id_rsa or any file that holds a private key. To download a shared file, choose Save on its card.

For a large file already on the server, choose the paperclip, then Share a server path…, type the full path, and choose Add to message. Crew shares only the path. Others open the file only if their own server account may read it. Details: Messages and files.

Ask my agent

An agent can work in a channel in two ways: a task, or a connected chat (next section). Both post as your agent, everyone in the channel sees the posts, and access lasts one hour at most.

  1. Open the channel where the result should appear and choose Ask my agent in the message box. A pane opens on the right side.
  2. Type the task in Task. Enter starts a new line.
  3. Check Model, or choose Change to pick another.
  4. To let the agent read other channels, open Advanced and tick up to 16 under Also read.
  5. Choose Start my agent and allow posting here. The task's row in the channel shows a status such as "Working…".
Your task is posted in the channel. Do not paste data you would not post there yourself.

Stop on the task's row ends it early. "Waiting for your approval" means the agent needs your answer, so choose Review. Crew ends the result with a line that names the shared files the task read, or says it read none. Trust that line over the agent's words. One computer runs at most four tasks at once.

ModelAccepted
A local model, such as Llama Server or OllamaYes
A Private model approved for the workspace's institutionYes
Another Private model, or a Public modelOnly when nothing it reads is protected (see Privacy)
Claude Code or CodexNo

Details: Agents and chat access.

Connect a chat with /crew

A connected chat is an ordinary Biorouter chat whose agent may read a channel and post there. The chat needs at least one message, a model, no reply in progress, and no attachments in its message box.

  1. In the chat, type /crew and press Enter. Nothing is sent to the model.
  2. Crew opens the Chat access pane for the channel it is showing. For another channel, choose that channel, then Review access.
  3. To let the chat read other channels, open Advanced and tick them under Also read.
  4. Choose Allow “{chat title}” to read and post in #methods. The pane shows "Connected." and the time access ends.
  5. Choose Back to chat. The chat shows a "Crew · #methods" chip and Revoke access.

The chat can read its channels and their files, and post in its one channel. With a Private model it can also use the connection's Remote work folder on the server. It cannot use other Biorouter tools, such as the shell or files on your computer, and these limits stay after its access ends.

To end access, choose Revoke access in the chat, then Revoke. The chat stops reading and posting at once, even when the workspace cannot be reached. Deleting a chat does not revoke its access.

When access ends, a note in the chat says why. Choose Grant access again or Start a new chat. These changes end all agent access in the workspace:

  • Adding someone to a team or channel, removing someone from a channel or the workspace, or a person accepting a team or channel invitation.
  • Archiving a channel, or offering or accepting channel ownership.
  • Any change to the workspace's privacy or institution.

Changing your own connection's privacy, or saving Connection settings…, ends your own chats' access. Renaming a team, a channel or the workspace does not. Agent access… in the workspace menu lists your chats and tasks that have access.

Privacy and institutions

SettingValuesWho changes it
Your connection"Private" or "Public"You
Workspace"Private for everyone" or "Allows Public"The host

Your privacy is Public only when your connection is Public and the workspace allows Public. Otherwise it is Private. A new workspace starts as "Private for everyone". To change your connection, choose the privacy chip in the status row, then Make my connection public… or Make private.

The host sets the workspace's institution once. Your connection's institution must match it. Content an agent reads is protected when your privacy is Private, when a channel it reads is "Restricted" or holds Restricted material, or when it uses your remote work folder. Only a local model or a Private model approved for the workspace's institution may read protected content, and only once the workspace has an institution. Restricted content stays Restricted after the host allows Public. Crew on the server applies these rules even when Privacy tiers is off in Biorouter's settings.

What other people can see

  • Members of a channel see your display name, your username, and your messages, files and agent posts there.
  • The host sees the same channels as any member, plus the member list. The Crew window shows nobody your connection's privacy or your devices.
  • The host's server account and the server's administrators can read everything the workspace stores.

Keys and security… in the You menu, at the bottom of the Crew sidebar, lists your devices and where your keys are stored. If you use an encrypted vault and it is locked, choose Unlock in the connection bar. When the connection bar reads "A new device was added to your account on {date}.", choose Review, and tell your host about a device you do not recognize. Details: Privacy and security.

Staying connected

StatusWhat to do
ConnectedNothing.
Connecting…, Reconnecting…Wait.
OfflineChoose Connect to chen-lab. You see this after Disconnect, after you save Connection settings…, and after the background service restarts.
Can’t connectRead the reason in the connection bar, then choose Connect to chen-lab in the main area.
Sign-in neededChoose it and type your password or code.
Can’t verify serverSee Server identity.
Not set up on this serverInstall biorouter-crew in your own server account, as Install it yourself on that screen or Server setup for administrators shows, or ask IT. Then choose Try again.

When the network drops, Crew reconnects by itself for up to an hour. It never sends a message a second time, so if the connection broke while you sent something, check whether it arrived.

Server identity

Crew connects only to a server whose host key is in your known hosts file, and only to the workspace your invitation names.

ScreenWhat to do
"Can’t verify lab.example.edu yet"Compare the server's fingerprint with the one from your IT team, add the key to your known hosts file, and choose Try again. How do I verify it? lists the steps.
"lab.example.edu’s identity changed"Do not connect. Choose Copy details for IT and send them to your IT team.
"This isn’t the workspace you joined"Do not continue. Choose Copy details and send them to your host.

Connection settings… in the workspace menu changes your server login, privacy, institution, port, identity file, jump hosts and remote work folder. At its bottom, Remove chen-lab from this computer… removes the workspace from this computer and deletes its key here. To use it here again, ask the host to invite you with Add another device for @bob turned on. A host must never remove it from their only computer, because nobody could then invite, let in or remove people. Details: Connections and troubleshooting.

Fix common messages

MessageWhat to do
"This doesn’t look like a Crew invitation."Paste the whole message, including the line that starts with brcrew1:.
"This invitation expired."Ask the host to invite you again.
"You’re not in chen-lab yet"Check Your server login in Connection settings…, then send the host the message Crew offers.
"Can’t reach lab.example.edu."Check your network, and your VPN if your lab uses one.
"Confirm this workspace's institution before granting an agent…"Ask the host to set the workspace's institution.
"This feature needs a newer Biorouter background service."On a Mac or a Linux computer, reopening Biorouter keeps the old service running. Restart the computer, or run daemon stop as Command line shows, then open Biorouter. On Windows, quit and reopen Biorouter. See Upgrade Crew.
"Authorize this action in the Crew panel…"Do the action yourself in Crew. If it repeats, quit and reopen Biorouter.
"This workspace has grown past the size Crew supports…"Reading still works. Ask the host about a new workspace.

Command line

The biorouter crew commands reach the same workspaces as the app. Add --help after any command for its options.

  • Every command except daemon status asks for your approval secret. In a script, add --approval-key-stdin and send the secret as the first line of standard input.
  • Add --connection NAME when you have more than one saved connection.
  • Write a channel without its #, or quote it: '#methods'. Name people by username, such as @bob. Files, tasks and chats take an ID.
  • --output-format json prints JSON. Exit status is 0 for success, 1 for a failure or refusal, and 2 for a wrong command line.
# Join a workspace
biorouter crew connections join-invitation ./invitation.txt
biorouter crew --connection chen-lab auth
biorouter crew --connection chen-lab join

# Let people in (host)
biorouter crew enroll invite @bob
biorouter crew enroll approve @bob 7QK2-M9XA-3JTP-WZ4D

# Teams, channels, messages and files
biorouter crew channels create methods --team analysis-lab
biorouter crew members add @bob --team analysis-lab --channel methods
biorouter crew send methods --text 'Plate reader data is in.'
biorouter crew --show-ids files upload methods ./counts.csv
biorouter crew files watch TRANSFER_ID
biorouter crew --show-ids files status TRANSFER_ID
biorouter crew send methods --attachment ATTACHMENT_ID

# Agents
biorouter crew tasks start methods --text "Summarize this week" \
  --provider PROVIDER --model MODEL --allow-posting
biorouter crew grants grant SESSION_ID methods
biorouter crew grants revoke SESSION_ID

# Stop the background service on this computer
biorouter crew daemon stop

An upload alone posts nothing. The upload prints a transfer ID. When files watch reads Transfer Ready., files status shows the Attachment ID: to send. privacy set-personal public and privacy set-workspace public take effect at once, with no typed confirmation. Details: Command line.

Server setup for administrators

The host's copy of biorouter-crew stores the workspace and checks every request. Each member's Biorouter starts the same program in the member's own account over SSH, which passes requests to the host's copy through a Unix socket under /tmp. Crew needs no root, no system service, no open network port and no database.

RequirementDetail
SystemLinux on x86_64 with glibc 2.31 or newer, and a valid /etc/machine-id owned by root.
StorageA local persistent disk. NFS, CIFS and SMB are refused. No folder above the state directory may be writable by its group or others, unless it has the sticky bit.
AccountsThe host uses an ordinary account, not root. Every member uses their own account on the one machine that runs the host's copy.
Kernelpidfd_open for stop. Landlock ABI 3 and seccomp for agents that run commands in a remote work folder.
SSHCrew uses each member's own OpenSSH settings and turns on strict host key checking. Jump hosts must use ProxyJump.

To install, download the biorouter-cli deb or rpm from the release page, check that its sha256sum matches the sha256: value beside it, then take /usr/bin/biorouter-crew out of the package (Get a verified file). In each account that connects, run these commands with that file's path. They need no administrator rights.

mkdir -p "$HOME/.local/bin"
install -m 0755 /path/to/verified/biorouter-crew "$HOME/.local/bin/biorouter-crew"
"$HOME/.local/bin/biorouter-crew" --version

Crew uses only the copy at ~/.local/bin/biorouter-crew. Nothing starts the workspace when the server boots. After every server restart, the host runs start with the workspace's folder and without --name. The workspace keeps its keys and history.

"$HOME/.local/bin/biorouter-crew" start --state-dir "$HOME/.local/share/biorouter-crew/chen-lab"
"$HOME/.local/bin/biorouter-crew" status --name chen-lab
"$HOME/.local/bin/biorouter-crew" stop --name chen-lab

The folder keeps the workspace's original name after a rename, and status and stop take that name. Adding --name to start after a rename fails with name_mismatch. start --name … --bootstrap-key … is only for creating a workspace, which the steps in Host a workspace do.

To upgrade, stop the program, replace the file, and run the start line above. The state directory, ~/.local/share/biorouter-crew/chen-lab by default, holds journal.jsonl, the whole workspace history, and blobs/, the shared file contents.

ItemLimit
Workspace state, including message text16 MiB
Messages100,000, each up to 65,536 bytes
Shared files1 GiB each, 10 GiB in total
Agent access1 hour per grant. A task reads at most 16 other channels. A connected chat reads at most 20 channels, including its own.

At a limit, reading still works and changes are refused. Crew has no export or backup tools. To keep a copy, stop the program and copy the whole state directory to equally private storage. Never edit journal.jsonl. SSH encryption alone does not make a deployment HIPAA compliant. Your institution decides approval, retention and backup. Details: Administration.

Features

Workflows and the scheduler

A workflow is a single portable file (YAML or JSON) that bundles everything an agent needs to run a task the same way every time: the instructions, an optional starting prompt, typed parameters the user fills in, the extensions and skills to enable, the model to run on, and optional rules for structured output and retries. Save one from a chat you already ran, hand it to a colleague as a file or a link, and the scheduler can run any of them unattended on a cron schedule. Documented for Biorouter 1.91.2.

What a workflow file is

Workflows are written in YAML (recommended) or JSON. One file packages an agent's whole setup, so loading it launches a session that is already configured, instead of one you assemble by hand each time. A minimal workflow needs only a title, a description, and at least one of instructions or prompt:

version: "1.0.0"
title: "Summarize Research Paper"
description: "Reads a PDF and produces a structured summary"
instructions: "You are a biomedical research assistant."
prompt: "Summarize the key findings, methods, and conclusions of the attached paper."
Extensions Skills Knowledge Model Workflow one file, runs the same way
A workflow bundles the extensions, skills, knowledge, and model an agent needs into one file you can share and rerun.

The schema fields

FieldRequiredWhat it does
title, descriptionYesA short name and a description of what the workflow does.
instructionsYes*System instructions that set the agent's behavior. Supports templating.
promptYes*The first message sent automatically. Required to run headless, without an interactive session.
parametersNoTyped values the user supplies at launch, substituted with {{ name }}.
extensionsNoThe MCP servers and other extensions the workflow needs.
settingsNoProvider, model, and temperature overrides for this workflow.
activitiesNoClickable prompt bubbles shown when the workflow opens in the desktop app.
responseNoA JSON schema that forces a structured final output.
retryNoRules for running the workflow again automatically, with success checks.
sub_workflowsNoOther workflow files this one can call as tools.
versionNoThe workflow format version, defaults to "1.0.0".

*At least one of instructions or prompt must be present.

Typed parameters

Parameters make a workflow reusable. Each declares a key, an input_type, and a requirement; its value is substituted into instructions, prompt, and activities with {{ key }}. The six input types are:

TypeValue
stringUsed unchanged (the default type).
numberA numeric value, validated in the desktop input.
booleanTrue or false, shown as a dropdown.
dateA date, currently entered as text.
fileA file path; Biorouter reads the file and substitutes its contents, not the path.
selectA dropdown; requires an options list.

A requirement of required must be supplied at launch, optional can be omitted when a default is set, and user_prompt prompts interactively if no value is passed. Rules enforced at load time: optional parameters must have a default, required parameters and file parameters may not have one, select parameters must list options, and every {{ name }} in the templates must match a defined parameter (with no unused definitions).

parameters:
  - key: gene_name
    input_type: string
    requirement: required
    description: "Gene symbol to analyze (e.g. BRCA1)"
  - key: output_format
    input_type: select
    requirement: required
    description: "Output format"
    options: [markdown, json, csv]

prompt: "Analyze {{ gene_name }} and return results in {{ output_format }} format."

Extensions, settings, activities

extensions lists the tools the workflow needs (types include stdio, builtin, platform, streamable_http, frontend, and inline_python). If an extension names a secret in env_keys that is not already in the keyring, the CLI prompts for it at launch and stores it securely. settings overrides the provider and model (biorouter_provider, biorouter_model, temperature) for this workflow only. activities are clickable bubbles, shown only in the desktop app. An entry prefixed with message: renders as an info box. The others send their text as a first message.

Structured output and retry

The response field enforces a final structured JSON output against a json_schema, which is what makes a workflow safe to script against: the final validated JSON is emitted as the last line of output. The retry field runs the workflow again until it succeeds: after each run it executes shell checks (each must exit 0), and if any fail while retries remain it runs the optional on_failure cleanup, resets the message history, and starts over, up to max_retries.

Templating and inheritance

The templated fields use Jinja syntax. Beyond simple {{ name }} substitution, a workflow can inherit from another with {% extends "parent.yaml" %} and override named {% block %} sections, so related workflows share common structure. The indent() filter keeps values that span several lines valid when passing them into a subworkflow, and the included variable {{ workflow_dir }} resolves to the folder holding the workflow file so you can reference companion files.

{% extends "base.yaml" %}
{% block prompt %}
Perform a survival analysis on the provided clinical dataset.
{% endblock %}

Saving, running, and finding workflows

Save a chat as a workflow in one click

When a session has the setup you want to keep, save it as a workflow. A saved workflow captures the instructions, activities, enabled extensions, folder context, and (optionally) the model and retry rules; it deliberately excludes your memory, API keys, and system settings.

1

In the desktop app

While in the session you want to keep, click the workflow button at the bottom of the app, review and edit the fields in the dialog, then choose Create Workflow to save it to your Workflow Library or Create & Run Workflow to save and immediately start a fresh run.

2

From the CLI

Inside a session, run /workflow to write workflow.yaml into the current directory, or /workflow my-name.yaml to choose the path. Validate it afterward with biorouter workflow validate my-name.yaml.

Running a workflow

In the desktop app, open a workflow from a shared link, from manual URL entry, or from the Workflow Library in the sidebar (click Use). The first time you run one, a warning dialog shows its title, description, and instructions; click Trust and Execute to continue (you are not asked again unless it changes). If it has parameters, fill in the Workflow Parameters dialog, then click an activity bubble or send the prompt. From the CLI:

biorouter run --workflow workflow.yaml
biorouter run --workflow workflow.yaml --params gene_name=BRCA1
biorouter run --workflow workflow.yaml --interactive   # prompt for required values
biorouter workflow validate workflow.yaml              # check it loads correctly
biorouter workflow open workflow.yaml                  # open it in the desktop app

Where workflows are discovered

Biorouter looks for workflow files in several places, in order:

SourceLocation
Current directoryThe folder you run from (*.yaml and *.json).
Custom pathsDirectories listed in BIOROUTER_WORKFLOW_PATH.
Global library~/.config/biorouter/workflows/, available to every project.
Project./.biorouter/workflows/, scoped to that project.
GitHub repositoryA repo set in BIOROUTER_WORKFLOW_GITHUB_REPO (needs the gh CLI installed and authenticated); run by name, for example biorouter run --workflow code-review.

List everything Biorouter can find with biorouter workflow list (add --verbose or --format json). The Desktop Workflow Library shows only workflows you explicitly saved or imported, not files discovered on disk.

Sharing by file or link

Share a workflow two ways. As a file: send the .yaml or .json; the recipient runs it with biorouter run --workflow or imports it in the desktop app. As a link: copy the deeplink from the Workflow Library, or generate one with biorouter workflow deeplink <file> (optionally filling in parameters in advance with --param key=value). Clicking a link opens Biorouter Desktop with the workflow loaded. Each recipient gets their own private session; nothing is shared back to you, and they supply their own credentials.

Subworkflows

A workflow can delegate parts of a task to other workflow files listed under sub_workflows. Biorouter turns each into a tool the main workflow can call; the subworkflow runs in an isolated session with its own context and returns its output to the caller. Pass fixed inputs with values (these take precedence and cannot be overridden), or let the agent infer a subworkflow's parameters from the conversation, including results from an earlier subworkflow. Subworkflows cannot nest (a subworkflow may not define its own), and this feature is experimental and may change.

The scheduler

Biorouter includes a cron scheduler that runs workflow files on a recurring schedule with no one present. Scheduled jobs are stored in an SQLite database, so they survive restarts, and they run headless: the workflow executes in the background with no chat window, and its results are saved to your session history. A job keeps firing as long as the Biorouter background process is running, so a schedule runs unattended even when the chat app itself is closed (a foreground job with no window available falls back to a background run).

Create a schedule in the desktop app from the Scheduler view or the Workflow Library (pick the workflow, set a frequency or a cron expression, optionally fill parameters, save), or from the CLI. Jobs use standard cron syntax. Biorouter accepts expressions with 5, 6, or 7 fields for extra precision.

# every day at 9:00 AM
biorouter schedule add --schedule-id daily-report \
  --cron "0 0 9 * * *" --workflow-source ./workflows/daily-report.yaml

biorouter schedule list
biorouter schedule remove --schedule-id daily-report

Because a scheduled run cannot stop to ask you anything, its workflow must include a prompt (the message that starts it), avoid user_prompt parameters, and fill in every required parameter in advance, either in the file's defaults or in the schedule. The provider's API key and any extensions the workflow uses must be available in the environment the background process runs in.

The included Daily Meditation job

Biorouter ships one schedule already registered: Daily Meditation, which runs the included Meditation workflow every day at 3:00 AM (cron 0 0 3 * * *). It summarizes your recent sessions into the Soul knowledge base described in the section above, so the agent's record of your work stays current without any action from you. It shows up in the Scheduler view marked Built-in, and you can pause, edit, or run it on demand like any other job. The workflow and schedule are installed idempotently on startup, so they are recreated if missing but never duplicated or made to overwrite your edits.

Schedule a workflow to run nightly

1

Prepare a workflow that can run headless

Make sure the workflow you want to schedule has a prompt and no parameters that need interactive input. For example, a report workflow whose prompt is "Run the differential expression pipeline on today's data and save the results," with the provider and model set in settings.

2

Register the schedule

In the desktop app, open the Scheduler view, click Create Schedule, choose the workflow as the source, and set it to run nightly (the time picker converts to a cron expression). Or from the CLI, run biorouter schedule add --schedule-id nightly-report --cron "0 0 2 * * *" --workflow-source ./workflows/report.yaml to run it every night at 2:00 AM.

3

Check on it

The Scheduler view lists each job with its next run time and last run status, and controls to pause, resume, edit, delete, or run it now. Each run's output is captured in your session history, so you can open or restore any run the schedule produced. A failed run is recorded and tried again at the next scheduled time.

Headless runs need their credentials in place. A scheduled job runs in the same environment as the Biorouter background process, so the LLM provider's API key must be reachable there, and any file paths or extensions the workflow references must exist and be configured when the job fires. A workflow that works interactively can still fail on a schedule if it depends on input or credentials that are only present in your interactive session.
Internals

Agentic loop and orchestration

When you send Biorouter a request, it does not answer in a single step. It runs a loop: it gathers the context the model needs, asks the model what to do, runs any tool the model asks for, feeds the result back, and repeats until the work is finished. Biorouter, not the model, controls that loop. It decides what context is assembled, which tool calls are allowed to run, what gets saved, and whether an answer with no tool call ends the turn. This page follows the loop from the moment a request arrives to the moment a final answer is sent, then covers the controls that keep a long turn safe, correct, and interruptible, and finally how the agent works across more than one conversation at a time.

From a request to an answer

Every turn moves through the same stages. For a simple question the model may pass through them once with no tool calls. For a real task the middle stages (model call, tool routing, execution, observation) repeat many times before the loop reaches a final answer.

Request Build context tools, knowledge, skills Model Route + run tool permission gate Observe repeat Respond when done
Each turn: build context, call the model, route and run a tool through the permission gate, observe the result, and repeat until the model answers.
1

Receiving the request

A message arrives from the desktop app or the CLI. Biorouter allows one active turn per session: if the same turn is submitted twice it is treated as a single request, and a different turn that arrives while one is running is rejected rather than run in parallel. Slash commands can answer at once or rewrite history, and a persisted goal from an earlier turn is restored before the new reply begins.

2

Assembling context

Before it calls the model, Biorouter builds the full picture the model will see. This is prepared on separate paths that join only at the moment the provider request is sent:

  • System prompt. A base instruction set, plus an overlay for the model in use, the current permission mode, the local date, guidance from each enabled extension, and any workflow or project instructions.
  • Available tools. The list of tools every enabled extension offers, described so the model knows when to reach for each.
  • Active knowledge. If a knowledge base is selected, Biorouter searches it with your whole message and injects up to five relevant results (or an explicit note that retrieval failed) as context only the agent sees.
  • Active skills. Skills you reference are loaded before the call. A skill's full body is injected once per session and later turns get a short pointer, so the same instructions are not sent again every turn.
  • Working directory. A bounded map of the project folder, which respects .gitignore and .biorouterignore, caps how many entries it reports, and targets roughly 2,000 tokens.
  • Session history. The conversation so far, projected into the form the provider expects.

As a conversation grows, its working set is measured against a context threshold (80 percent of the window by default). When it crosses that line, Biorouter compacts: older messages are summarized into a compact continuation for the model while the complete history, which you can read, is kept for you. Compaction changes what the model sees, not what you can scroll back to.

3

The model call

Biorouter sends the assembled system prompt, message history, and tool list to the configured provider and reads back the response as it streams. It classifies what comes out: plain text (a candidate final answer), one or more tool requests, usage numbers, the finish reason, and any provider error. That classification decides what happens next.

4

Tool routing

When the model asks for a tool, the choice of tool follows a simple order of preference. The most basic tools handle straightforward work, and the specialized extensions are reserved for tasks that need them:

  • Primitives first. Listing, reading, writing, editing, or finding files and running single commands go to the developer extension's shell and text_editor tools. These are the default for anything simple.
  • Specialized extensions when warranted. Real computation and chains of several steps, figures, a knowledge base, browser automation, data queries, or building an app each have their own extension, reached only when a primitive cannot do the job.

Routing can also cross models. A lead model handling the conversation can delegate part of a task to a worker model with a different provider and a narrower tool set, which is the basis of the orchestration of several agents described below.

5

Dispatch and execution, with permission gating

A requested tool call does not run until it passes a chain of inspectors. The inspectors do not vote; their decisions merge toward greater restriction, so deny outranks ask and ask outranks allow, and no permissive layer can loosen a stricter one. The chain runs managed (administrator) policy, then a security and command policy check, then the permission gate, then repetition and hook checks. A small set of catastrophic commands is denied even in the most autonomous mode. If a hook rewrites a call's arguments, the rewritten call is sent back through the same checks before it can run.

What the permission gate does depends on the mode:

  • Chat: no tools run at all.
  • Auto: tools run without prompting, but managed policy, the command policy, and hooks can still escalate a call to an approval prompt or a denial.
  • Approve: calls prompt unless a remembered rule already trusts them.
  • Smart approve: calls that only read, and other calls with low risk, run automatically. Calls with higher risk ask.

Approved calls then execute. A global limit of eight concurrent tool calls keeps the system responsive, and calls that would write to the same path are serialized so they cannot clobber each other.

6

The observation returns to the model

Each tool's result is turned into a bounded form the model can see, and added to the conversation. An oversized result is written to disk in full, and the model gets a short preview plus the file path instead of the whole thing. Successful text can be scanned and masked for credentials, prompt injection markers, and PII or PHI patterns. Failures are typed (for example not_found, permission_denied, timeout, or invalid_args) so the model can adapt, and a tool error is returned to the model as context rather than ending the session, which lets the model correct itself and try again.

7

Iterating until a stop condition

With the tool results in hand, Biorouter assembles fresh context and calls the model again. This is the cycle that repeats. It ends when the model returns an answer with no tool calls and that answer passes every completion check that is active (see structured success checks below). If a response was cut off because it hit the output length limit, Biorouter injects a hidden instruction to continue and does so up to twelve times.

8

Producing the final response

Once an answer with no tool call clears its checks, the turn completes and the final answer is delivered. In the desktop app the whole turn (streamed text, tool activity, and the final answer) travels to the client over a live event stream; the CLI renders it directly. The full exchange is persisted so the session can be reopened, searched, and continued later.

Controlling the loop

Autonomy on a researcher's working tree is only safe if the loop has brakes. Biorouter runs several independent controllers during a turn. Most of the values below are defaults that a workflow or session setting can narrow or extend.

Budgets and token targets

A turn can be given a budget in elapsed time, tokens, or dollars. As the budget runs low, Biorouter first warns, then asks the model to wrap up, then stops after a short grace period. The context threshold (80 percent by default) is the token target that triggers compaction rather than a hard stop, so a long session keeps working instead of failing when it fills the window.

Persistent goals

A goal set during a turn is saved with the session and restored before the next reply, so an objective survives across turns. When a goal is active, a goal judge checks whether the work satisfies it before the turn is allowed to finish.

Loop and stall detection

Several controllers watch for a turn that repeats itself and send their evidence to one escalation path. That path can send the model a reminder, give it a short grace period to finish, or stop the turn:

ControllerSignalResponse
Exact tool repetitionThe same call three times (hard limit five)Warn, then stop
Near duplicate, or a cycle between two actionsHigh similarity, or alternation over four stepsWarn
Repeated identical failureNudge at three, escalate at five, deny after sixReplan, then block the failing call
Periodic stall reviewFirst review at 30 actions, then every 10Nudge, then a grace period to finish
Hard caps100 turns and 200 tool callsTerminate with a clear limit result
Reply budgetConfigured time, tokens, or costWarn, ask the model to finish, then stop

Cancel and interrupt during a turn

You do not have to wait for a turn to finish. A hard cancel stops the active turn, is safe to send more than once, and unblocks anything waiting on an approval prompt. A soft interrupt is gentler: your new message enters a queue and is folded in at the next safe point, and if it arrives while the final answer is streaming it keeps the loop alive for one more iteration so the model can take your correction into account.

Structured success checks

A response with no tool call is treated as a candidate, not a guarantee. Before it becomes the final answer, Biorouter runs whichever checks are enabled:

  • Structured output. When a workflow defines a response schema, a dedicated tool validates and stores one JSON value; if it is missing, the model is asked to continue.
  • Workflow retry. Configured checks run after apparent success, and a failed attempt can restore the starting conversation and retry within a bound.
  • Done gate and self critique. Optional passes that iterate on the current work or challenge the answer for contradictions or fabrication (both off by default).
  • Stop hooks. The last gate before the answer is emitted (covered below).

Any failed check sends the turn back to work rather than letting a premature answer through.

Shadow git checkpoints and reverting

So that large edits can be undone, Biorouter can snapshot the working directory at turn boundaries into a private git object database stored in the app's data folder. It never commits to, or reads from, your real .git. From a checkpoint you can rewind along any of three axes: the files (restore the captured tree into the folder), the conversation (truncate history at that point), or both. A restore first takes its own snapshot, so you can undo a rewind too.

Off by default. Checkpoint capture is turned on with BIOROUTER_CHECKPOINTS and is off by default, so a large data folder is not snapshotted unless you ask for it. The opposite choice, committing verified work to your real repository, is available through the verify and checkpoint Stop hook below.

Hooks

Hooks let you run your own shell command, or a small judge that asks a model, at defined points in the loop without changing Biorouter itself. They fire everywhere the agent runs (desktop app, CLI, scheduled runs, and subagents), and they follow a fixed precedence: Biorouter's defaults, then your global config, then project hooks you turn on, then administrator policy, which nothing overrides. The events you are most likely to use:

  • Before a tool. Before a tool runs, a hook can allow it, ask for approval, deny it, or rewrite its arguments (a rewritten call is checked again against every safety gate).
  • After a tool. After a tool runs, a hook can mark the result as an error and feed corrective context back, for example to reject a write that fails lint.
  • Stop. When the agent is about to finish, a hook can block completion and return something it must address first. Repeated blocks are capped so a hook can never wedge the turn forever.

The verify and checkpoint Stop hook

Biorouter includes a Stop hook that blocks the end of a turn until the work is reproducible. It always runs a quick commit check. Uncommitted changes block the stop, and the message asks the agent to add a .gitignore if needed and commit in logical units. When you set BIOROUTER_VERIFY_BUILD=1, it also detects the toolchain and runs the build and tests, and a failure blocks the stop. A limit on consecutive blocks means the hook stops blocking instead of looping if the agent cannot make the build and tests pass.

Subagents and orchestrating several agents

For work that is best isolated, the main agent can spawn a subagent: a temporary Biorouter instance that runs a task on its own and reports back, keeping its tool activity out of your main conversation. You ask for one in plain language ("use a code reviewer to check this function", "research this and summarize the findings"), and the agent decides when delegation helps. Subagents can run one after another or in parallel, inherit the extensions of the session that launched them (or a restricted set you name), and return either a full trace or only the result.

Lead agent plans and delegates Worker 1 Worker 2 Worker 3 delegate report back
A lead agent breaks a task into parts, hands each to a worker subagent, and collects what they return.

Subagents run under deliberate limits: 25 turns and a timeout of five minutes by default, and a bounded number in flight at once. They are also restricted for safety, they cannot spawn further subagents (which prevents runaway recursion), and they cannot change extensions or schedules on the parent session. Beyond single delegation, a lead agent can coordinate named worker profiles, each a different model and role. Turns across those profiles run one at a time (serialized) so their work stays ordered and legible, with parallel workers a later goal.

Memory across sessions

The loop's context is normally scoped to one session, but two mechanisms carry knowledge forward. A knowledge base (for example the "Soul" base, which ships with Biorouter and holds durable user facts) can be searched during context assembly and written to explicitly. Separately, past chats are indexed for recall ranked by relevance, so you can ask what was decided in an earlier conversation and get the right session back rather than merely the most recent one.

Workspace control

A subagent puts a second agent to work inside one conversation. Workspace control is the layer above that: it lets the agent act on your conversations themselves. It can open a new one in a tab, a split pane, or its own window; read what another conversation has already done; leave a note in it or start a turn in it; wait for it to finish; and change which extensions, skills, model, or knowledge bases it uses. The practical effect is that "run the QC pass while I write the methods" stops meaning you open a second chat, paste the context across, and remember to come back to it.

What you ask forWhat you get
"Open a second chat for the QC pass, in a split, and start it on the flowcell report."A new session in its own pane, already working, sharing your working directory unless you said otherwise.
"Delegate the test suite to a subagent and tell me when it is done."A child conversation in its own tab that you can read, steer, and stop, and a parent that waits on it properly instead of polling.
"Give the transcriptomics chat the single cell skill."That chat reconfigured, with a confirmation card first and a notice in its own tab afterwards.
On by default. Delegating to a subagent needs nothing turned on. Everything else reaches into conversations the agent did not create, and it ships as the Workspace Control capability, enabled by default with its full surface, including reading and steering other conversations. To turn it off, clear it under Extensions in the sidebar, or with biorouter configure → Toggle Extensions → workspace.

Where a new conversation lands

The agent places a conversation with the same vocabulary you use by hand, and only that vocabulary. Anything it does not recognize is refused and is never opened as a tab instead, so an unknown placement always produces an error message.

Agent opens a conversation tab a new tab in the pane you are already in: the default, and it opens in the background split a new pane beside the current one, up to six panes in one window window a separate window of its own
The agent has exactly the three placements you have by hand. A value it does not recognize is refused, not guessed at.

Two defaults differ from what many people expect. New tabs open in the background, so your focus stays where you are typing; the agent has to ask for focus explicitly and rarely should. And a new conversation inherits your working directory unless the agent is told otherwise, in which case you are told where it landed. Opening a conversation never moves an existing one's working directory; only a newly created session gets one, and it gets it at creation.

If a split is refused because the window is already at six panes, the agent is told the conversation was not opened and why, so it can say so rather than claim a pane exists.

If you would rather nothing appeared on its own

Turn on Settings → App → Workspace → "Never open tabs automatically". Conversations and subagents still run; you get a notification naming them and open them from History when you want to. The agent is explicitly told that no tab opened, so it cannot report one that is not there. The setting is off by default.

Watching a delegated run

Ask for a subagent in plain language and, whenever the desktop app is open, the child appears in its own background tab with a sub badge and a link back to the conversation that spawned it. Inside that tab you can read the child's transcript as it streams, type into it to steer it while it runs, and stop it from the header. Three things about that tab people get wrong:

  • Closing it does not kill the child. Closing is a view operation everywhere in Biorouter. Stop is the kill switch, and a child whose tab you closed is still running and still in History.
  • If you typed into it, the parent is told. The parent's result carries a note that you intervened, so it weighs the child's own report accordingly. Nothing is said when you did not.
  • The badge follows the session, not the tab. A child that never got a tab is still badged when you open it later from History.

At most four children from one parent hold a tab at the same time. Ask for ten in parallel and you get four tabs; the rest run in the background and appear in History nested under their parent. A spawn is never refused for hitting that ceiling, only downgraded to a background run, and the parent is told which children that happened to. The cap counts live children, so a slot frees as each one finishes.

For a long job, the right way to collect a result is to wait rather than poll: the agent parks until one (or all) of the conversations it names finishes, and a timeout there is not an error: the work keeps running and it can wait again.

Delegation has its own gate. The spawn tool is only offered when the session runs in Completely Autonomous permission mode (the default) and is not itself a subagent: a child cannot spawn grandchildren. If asking for a subagent produces an ordinary answer instead of a child conversation, the permission mode is the first thing to check. A few narrower conditions apply as well; the repo documentation lists all of them.

Looking into another conversation

Ask what you are running right now and the agent lists the workspace: each conversation's id and name, whether a turn is in flight, which parent spawned it, the extensions and knowledge bases it has, and, when the desktop app is attached, which window, pane, and tab it sits in. To look inside one, four views are available, and the narrowest one that answers your question is the right choice:

ViewWhat it showsReach for it when
SummaryWorking directory, message count, the first and last few messages"Where has that chat got to?"
Transcript (default)The messages a person sees, with tool payloads collapsed to stubs of one lineYou want the prose
Tool callsRequest and response pairs, correlated and clipped"What did it do to my repository?"
Spawn contextThe instructions a subagent was started withAuditing a delegation

Long reads are clipped, and the clip names the controls that would narrow it. Sessions you have hidden are refused in every view. And because a read is an ordinary tool call, it is recorded in the conversation doing the reading: there is always a trail of who read what.

Changing another conversation's setup

One tool changes what a different conversation may use: add or remove extensions, scope a skill to that conversation alone, switch its provider and model, or set its knowledge bases. A model switch takes effect on the target's next turn, so a turn already running finishes on the provider it started with, and skills added this way never touch the preferences that apply to your whole machine.

Some of those changes raise a confirmation card in every permission mode, including the fully automatic one: handing a conversation an extension that can start processes, removing one that matters for security, switching its provider, or adding a skill. Whatever changes, the target conversation gets a notice saying what happened and who did it. Silent action across sessions is not a supported configuration. Two refusals are deliberate and should not be worked around: an extension an administrator has disabled cannot be enabled again this way, and a subagent can never be granted workspace control at all.

From the terminal

The CLI is a full front end here, and it reaches the feature two ways. Inside an interactive biorouter session chat the agent advertises the same tools, because the CLI links the same core library the desktop backend does; without a running daemon, listing, reading, waiting, leaving a note, and spawning still work, and the rest refuse by name ("requires the Biorouter daemon") rather than failing obscurely. Separately, there are ordinary subcommands you type:

What you wantCommandNeeds biorouterd
See what exists, with subagent runs nested under their parentsbiorouter session list --subagentsNo
Read a conversationbiorouter session export --id <id>No
Send a prompt into a session and stream its turnbiorouter session send <id> "<text>"Yes
Wait for a turn to endbiorouter session watch <id>Yes
Join a live session, follow it, and steer itbiorouter session attach <id>Yes
Stop the turn a session is runningbiorouter session cancel <id>Yes

Use session attach rather than resuming a session that is running right now: resuming opens a second agent on the same conversation, and the two do not share the daemon's turn lock. Exactly two capabilities have no terminal equivalent: spawning a subagent (already a tool inside biorouter session, so a subcommand would add nothing) and reconfiguring another session's tools. That is not folklore: the mapping between the tools and the subcommands is a compiled table checked against the real command tree, and a new capability with no CLI row fails the build.

The limits you will meet

Each of these is a real, named bound rather than a guideline.

LimitValue
Panes in one window6
Subagent tabs from one parent, at once4 (further children run in the background)
Turns one conversation may drive in others at once4 (the fifth waits rather than saturating the daemon)
Conversations a single wait may watch32
Wait timeout120 seconds by default, 600 maximum
Rows per listing page50 by default, 200 maximum
Characters per conversation read20,000 by default, 200,000 maximum

The full account (every refusal message, the exact confirmation rules, and the few cases where a tool can report a tab that the window declined to open) is in the repository, in workspace control and its reference for each tool.

Internals

Vaulting and security

Biorouter is built for sensitive research data, so its security model is layered and explicit. Your secrets live in the operating system's credential store, not in a config file. A permission mode decides how freely the agent may act. An administrator can pin a policy above your own settings. Your choice of provider decides where your data physically goes, and an OS sandbox, which you turn on, can confine what a shell command may touch.

How secrets are vaulted

Provider API keys and other secrets are stored in the operating system's native credential store, never written to config.yaml in plain text. Custody stays with the OS, and access is gated by the same mechanisms the rest of the platform uses.

Settings you paste a key OS credential store Keychain / Cred Manager read once In memory cached per process config.yaml never
A key you enter goes to the operating system credential store, is read once per process into memory, and is never written to config.yaml.

Biorouter reads the credential store once per process and caches secrets in memory for the rest of the run, so a single authorization covers a whole session. This matters most on macOS, the only platform that prompts.

PlatformCredential storePrompts
macOSKeychainUp to once per binary, ever. The OS asks you to authorize that specific executable to read the item.
WindowsCredential ManagerNone. Protected for each user by the Windows Data Protection API. A large secret set is chunked across multiple credential entries to stay under the limit of 2560 bytes for each credential.
LinuxSecret Service (GNOME Keyring / KWallet)None on a desktop session, which opens the store with your login.
On macOS, click "Always Allow." "Allow" authorizes a single access; "Always Allow" adds the binary to the item's access control list so it is never asked again. The desktop backend (biorouterd) and the CLI (biorouter) are separate executables, so macOS tracks one grant per binary. In the worst case (using both, with secrets created by the other) you enter your password twice, ever.

Two escape hatches exist when the credential store is unavailable or unwanted:

  • BIOROUTER_DISABLE_KEYRING=true stores secrets in plaintext ~/.config/biorouter/secrets.yaml instead. Headless Linux (SSH sessions, WSL, or a host with no Secret Service daemon) falls back to this file automatically.
  • An environment variable for a specific key (for example OPENAI_API_KEY) is read directly and always wins over the credential store.

Secrets for each app: the vault capability

Biorouter apps (built with Agent Drafter) can hold their own secrets, kept separate from your global keys. Each app's secrets live behind the vault capability, which is denied by default: an app gets none unless its manifest lists them (for example "vault": { "encrypted": ["SPOKEAGENT_PASSCODE"] }). When an app is exported to a runnable folder, its secrets sit in a .vault/ directory that is excluded from the export archive, so credentials never travel with the shared app.

Permission modes

A permission mode sets how much autonomy the agent has when it modifies files, runs shell commands, and drives the computer. It applies to the whole session, takes effect immediately, and can change before or during a session (the /mode command in the CLI, or Settings → Mode in the desktop app). It is the tier the user owns.

Tool call shell, editor, ... Permission mode Autonomousruns freely Manual approvalyou confirm Smart approvalrisk based Chat onlyno tools
Every tool call passes through the permission mode, which either runs it, asks you first, judges it by risk, or blocks it.
Mode/mode valueWhat it gates for shell, text_editor
Completely AutonomousautoRuns shell commands, text editor writes, and computer control with no approval. This is the default.
Manual ApprovalapprovePrompts before every write tool: shell, text editor write/edit/insert, and computer control. Calls that only read still run.
Smart Approvalsmart_approveJudges each call by risk. It approves actions with low risk by itself, and asks your approval for shell, text editor, or computer control calls with higher risk.
Chat OnlychatNo tools at all. No shell, no text editor writes, no computer control. Conversation and reasoning only.

Set a persistent default with biorouter configure (select biorouter settings, then biorouter mode) or in Settings, Chat, Mode in the app.

Managed policy: the administrator tier

Permission modes and the user config are owned by the user, so a lab or institutional deployment has no way to enforce a rule the user cannot turn off. The managed policy tier adds a trusted layer, owned by an administrator, that wins over user and project config. It can force specific tools to be denied, to require approval, or to be approved in advance, and it can pin mandatory lifecycle hooks. A managed deny holds even in Completely Autonomous mode; a blocked call surfaces as "Blocked by your organization's managed policy."

The policy is read from a location an administrator owns, which differs by operating system, and Biorouter verifies the file's ownership before trusting it (on Unix it must be owned by root or the current user and not be writable by its group or by everyone). There is no environment variable override, by design.

OSManaged policy path
macOS/Library/Application Support/Biorouter/managed-policy.yaml
Linux/etc/biorouter/managed-policy.yaml
Windows%ProgramData%\Biorouter\managed-policy.yaml

Deploy it through your device management tooling (Jamf on macOS, a package postinstall or Ansible on Linux, Group Policy or an installer on Windows). A file that fails the ownership check is ignored with a warning and the agent runs normally, so a bad push cannot brick a fleet.

Data privacy and patient data

Biorouter routes your inputs and conversation context to the provider you selected, so the privacy properties of a session depend entirely on which provider you chose, not on Biorouter itself. Provider tiers differ fundamentally in where data goes:

Provider tierWhere data goesSuitable for
Local (Llama Server, Ollama)Your device only. Nothing is transmitted to any external service.The most sensitive data, and work that must stay off any network.
Institutional (UCSF Versa Azure, UCSF Amazon Bedrock)Inside UCSF's own cloud tenant, governed by institutional agreements.Uses your institution has approved. Verify the terms first.
Commercial cloud (Anthropic, OpenAI, Google, OpenRouter, others)The provider's own cloud infrastructure, under their privacy terms.Only public data, or data that is not sensitive.
Patient data, PHI, and other regulated data. For clinical records, genomic data linked to individuals, or anything subject to HIPAA or institutional governance, use only services your institution manages, or fully local models. Do not use personal commercial API accounts. Deidentify data before you enter it unless you have explicit authorization and a compliant pathway, provide only the data the task needs, and do not share sessions that contain sensitive information. UCSF data use agreements change, so confirm with UCSF IT Security or your compliance office before a session touches regulated data. The Biorouter team cannot speak to the status of institutional agreements.

What a model that is not private can reach

Biorouter shows this the first time you bind a commercial model, and keeps it in front of you afterwards on the model chip, in Settings → Privacy, and above the Commercial section of the provider grid. It is shown whether or not privacy tiers are enabled: turning the feature off removes the enforcement, not the exposure.

{Provider} is not hosted by your institution.

It is not HIPAA-compliant, is not hosted on-premise, and does not run on this machine. It can read files on this computer. Anything a chat on this model can reach, it can send there: the contents of your working directory, and whatever a command you approve prints.

Biorouter does stop three things: this model cannot read another chat’s transcript, cannot read a knowledge base marked private, and cannot use an extension marked private or switch this chat to a private model to reach one.

It does not stop it reading ordinary files on this computer through the shell, including files an earlier private chat wrote outside Biorouter’s own storage. If the work involves patient data, use a local model or an institutional one.

The short form, on the model chip and in biorouter configure: “Not HIPAA-compliant, not on-premise, not local. This model can read files on this computer. Biorouter will not hand it another chat’s transcript or a knowledge base marked private.”

These are the exact words of COPY_LONG and COPY_SHORT in crates/biorouter/src/privacy/disclosure.rs, the single definition every surface renders. Quote them; do not paraphrase them.

Shell sandboxing

Beyond the permission mode, Biorouter can wrap shell commands in an operating system sandbox that confines writes to the working directory and the temp directory and denies outbound network by default. You turn it on with the BIOROUTER_SHELL_SANDBOX variable. It is off unless you set it.

PlatformMechanismWhat it enforces
macOSSeatbeltWrite confinement and network deny, enforced by the kernel.
LinuxLandlock plus seccomp, with a bubblewrap fallbackKernel write confinement and network deny where the kernel supports it.
WindowsJob Object plus restricted token (containment tier)Process and resource caps, plus a real primitive that kills the whole process tree. It does not confine writes or block network, and Biorouter reports it honestly as such.

Set BIOROUTER_SHELL_SANDBOX=auto to use the best available tier and run anyway if none exists, or strict to refuse the command when a full sandbox is not available. Run biorouter doctor to see which tier your host got. Independently of the sandbox, a denylist that is always on blocks catastrophic commands (for example rm -rf / and its Windows equivalents) in every mode.

Internals

Configuration

Biorouter reads its persistent settings from YAML in your user config directory, and environment variables override those settings for a single invocation. This section covers what config.yaml holds, how the tiers resolve against each other, the environment variables worth knowing, and where every file and directory lives.

The config file

The primary file is ~/.config/biorouter/config.yaml (%APPDATA%\Block\biorouter\config\config.yaml on Windows). It is shared by the desktop app and the CLI, and it holds:

  • Provider and model settings (BIOROUTER_PROVIDER, BIOROUTER_MODEL, temperature, planner and lead/worker models).
  • Extensions, declared under the extensions key: the included servers and any external MCP servers you add (command, args, environment, timeout).
  • General settings such as the permission mode, turn limits, search paths, and workflow discovery.

API keys are the deliberate exception: they are held in the OS credential store, not here (see Vaulting and security). Changes to the config file take effect after a restart. Verify the active configuration with biorouter info -v.

Precedence

The same setting can come from several places. They resolve in this order, highest first:

  1. Managed policy (owned by an administrator) for the permissions and hooks it governs.
  2. Environment variables.
  3. config.yaml and the other config files.
  4. Biorouter's defaults.

For settings the managed tier does not govern, the effective order is environment variables, then config file, then defaults. Where an administrator has installed a managed policy file, it is authoritative for permissions and hooks.

Useful environment variables

Every environment variable overrides the config file for one invocation. These are the ones you are most likely to need.

VariablePurpose
ALPHA_FEATURES (also ALPHA)Enable experimental alpha features. Off by default.
BIOROUTER_PROVIDER · BIOROUTER_MODELSet the provider and model for the session.
BIOROUTER_MODEPermission mode: auto, approve, smart_approve, or chat. Default auto.
BIOROUTER_DISABLE_KEYRINGSet to any value to store secrets in plaintext secrets.yaml instead of the OS credential store.
BIOROUTER_PORTPort the biorouterd daemon listens on. (Note the single underscore: only nested keys use the double underscore form.)
BIOROUTER_SERVER__SECRET_KEYServer authentication key. The __ denotes a nested config key.
BIOROUTER_EXTERNAL_BACKENDUse an externally running backend rather than spawning one (for front end development).
BIOROUTER_EXTERNAL_PORTPort of that external backend. Default 3000.
BIOROUTER_WORKFLOW_PATHExtra directories to search for workflows. Separate them with colons on Unix and semicolons on Windows.
BIOROUTER_MAX_TURNSMaximum turns allowed without user input. Default 100.
BIOROUTER_SHELL_SANDBOXOpt into OS shell sandboxing: off (default), auto, or strict.
BIOROUTER_PATH_ROOTRelocate all config, data, and state under one directory. Useful for isolated or CI environments.

File and directory locations

Paths below are the macOS and Linux locations. Biorouter follows the XDG layout, so config, data, and state are three separate roots. On Windows they all sit under %APPDATA%\Block\biorouter\, which holds config\ and data\; Windows has no separate state directory, so the log files listed below live beneath data\ there.

PathContents
~/.config/biorouter/config.yamlProviders, models, extensions, and general settings.
~/.config/biorouter/permission.yamlTool permission levels set via biorouter configure.
~/.config/biorouter/secrets.yamlAPI keys, only when the keyring is disabled.
~/.config/biorouter/knowledge/Knowledge bases (markdown trees with git history).
~/.config/biorouter/workflows/ · skills/Installed workflows and skills.
~/.local/share/biorouter/sessions/sessions.dbConversation history in a SQLite database.
~/.local/state/biorouter/logs/Log files.
~/Library/Application Support/Biorouter/Electron app state (desktop only, macOS).

Print the resolved config directory, config.yaml, sessions database, and logs directory for your own machine with biorouter info.

Internals

Architecture

Biorouter is built in three layers that stack cleanly: an interface you interact with, an agent that runs the reasoning loop, and a set of extensions that give the agent its tools. A request travels down through the layers and results travel back up. Understanding this shape is the fastest way to find your bearings anywhere else in the system, because every other part of Biorouter is an implementation of one of these three layers.

Three layers

The layers separate what you see from what thinks from what acts:

  • Interface. The desktop GUI or the command line interface. It accepts your input and displays responses, and nothing more; it holds no reasoning of its own.
  • Agent. The core reasoning loop described on the Agentic loop page, together with everything that supports it: session and conversation state, the connections to LLM providers, and workflow and schedule execution.
  • Extensions. Pluggable servers that speak the Model Context Protocol (MCP), the open standard Biorouter uses to talk to tools. Each extension, whether shipped in the box or installed by you, hands the agent a set of tools (file operations, database queries, web access, code execution, figures, and so on).
Interface Desktop app (Electron + React) or the biorouter CLI Agent Reasoning loop, session and conversation state, providers Extensions Pluggable MCP servers that provide tools request result request result
Three layers: the interface talks to the agent, which calls extensions and returns results back up.

In a typical session the interface starts an agent, the agent connects to one or more extensions at once, and it routes the model calls through whichever provider you have selected. Requests flow down from the interface into the agent and out to the extensions; tool results and the final answer flow back up.

The Rust workspace

The backend is a Rust workspace made of several crates. Four of them carry the architecture above:

PieceBinaryRole
biorouterlibraryThe core agent library: the reasoning loop, the LLM provider integrations, session and conversation state, and workflow and schedule execution. This is the Agent layer.
biorouter-serverbiorouterdThe REST and WebSocket server that the desktop app talks to. It owns turn admission and transport and drives the core library on the client's behalf.
biorouter-clibiorouterThe command line interface, one half of the Interface layer.
biorouter-mcplibraryThe MCP servers included with Biorouter, part of the Extensions layer.

The extensions shipped in biorouter-mcp include developer (shell and file editing), computercontroller, memory, autovisualiser (figures), knowledge, agent_drafter (building apps), and the data and compute servers. Because these live behind the same MCP interface as extensions from other authors, the agent treats an included tool and an installed one the same way.

How the interface reaches the agent

The two interfaces connect to the Agent layer differently, which is the main structural distinction between them:

  • CLI. The command line binary calls the biorouter core library directly, in the same process. There is no server in the middle.
  • Desktop GUI. The app is built with Electron and React. Its main process starts biorouterd in the background, and the React interface talks to that server over a local HTTP and WebSocket connection. Streamed turn events reach the interface over a live event stream, and calls the interface makes are type checked against a client generated from the server's OpenAPI specification, so the two sides cannot drift out of agreement.
One config, two front ends. The GUI and the CLI share the same configuration and session store, so providers, keys, extensions, and history set up in one interface are visible in the other. The interface is a thin shell over a single agent; it is not a separate copy of the system.

This layering is what makes Biorouter extensible. Adding a capability means adding an extension at the bottom layer, not changing the loop in the middle or the interface on top. The agent discovers the new tools, the routing rules decide when to use them, and the same permission and hook machinery governs them, all without touching the layers above.