npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

alvin-bot

v5.160.1

Published

Self-hosted autonomous AI agent on Telegram, Slack, Discord, WhatsApp, Signal, terminal & web. Claude Agent SDK + multi-provider engine with auto-failover, detached sub-agents, zero-config memory. Local-first, telemetry-free.

Readme

🤖 Alvin Bot — Autonomous AI Agent

v1.5.160.1: Alvin Live: talk to the whole agent, not just a voice model. Real-time voice in the web interface, with every request handled by Alvin's lanes, tools, memory and sub-agents while you keep talking.

Your personal AI agent — on Telegram, WhatsApp, Discord, Slack, Signal, Terminal, and Web.

Alvin Bot is a self-hosted autonomous AI agent that runs on your own machine and answers you on Telegram, Slack, Discord, WhatsApp, Signal, a terminal TUI, and a web dashboard. It is built on the official Claude Agent SDK and runs a provider-agnostic engine that also drives OpenAI, Groq, Google Gemini, NVIDIA NIM, OpenRouter, and Ollama, with automatic failover after two consecutive provider failures and a heartbeat health check every five minutes. Unlike most personal AI agents, it ships a zero-config indexed memory store: with no embedding API key it installs a small multilingual search model that runs inside the bot (no Ollama, no key) and uses a built-in SQLite FTS5 keyword index until then, so recall works out of the box. It dispatches detached sub-agents as independent claude -p subprocesses that keep running and deliver their result even if the parent conversation is aborted. It is local-first and telemetry-free — prompts and responses are never logged off-machine, secrets live in a chmod-0600 .env, and shell execution is allowlisted by default.

What's new — v1.5.160.1 (October 2026): Messages during a reply are handled, not cut off. If a background agent was running and you wrote while Alvin answered, the bot aborted the answer and showed "I got tangled"; a reply that is not waiting for the agent now keeps running and takes your message along. Agent results on Claude lanes no longer start with a false "summary unavailable" note.

v1.5.160.0 (October 2026): Alvin Live, now with your choice of the working model. Alvin Live connects real-time voice to the complete agent harness: Gemini Live listens and speaks, and everything that needs your data or an action runs in Alvin's lanes with their tools, memory, sub-agents and failover, several tasks in parallel while the conversation goes on. New in this release: the Live settings choose which model handles the tasks of a call (your fallback order still applies), task cards show the real state after you hang up, and "New session" starts without leftover results. Built into the web interface: a browser on your laptop or phone is enough.

v1.5.159.0 (October 2026): Alvin Live. A new Live page in the web interface turns Alvin into a phone call: Gemini Live is the voice, and everything that needs your data, research or an action goes to Alvin in a lane with your model, tools and background agents. Interrupt at any time, speak any language, ask "how far is it?" or "stop that" and get the real state. Setup checks a pasted Gemini key with a real live connection (free tier available); the newest live model is used automatically, 30 voices with preview (default Leda), emotion and temperament on by default. Tasks run in the reserved live lane or a live-<workspace> lane and are not posted to Telegram. The page shows the transcript and the exact cost of each live session, priced from Google's price list.

v1.5.158.0 (October 2026): Memory search without Ollama. EMBEDDINGS_PROVIDER=lokal runs multilingual-e5-small inside the bot, in its own process that ends after 15 idle minutes; on a real 20,349-section index it put the right source first for 19 of 28 questions, against 11 for nomic-embed-text. Installed with alvin-bot embeddings lokal (~230 MB), or by itself when no vector provider is set. Ollama only while it is used. With OLLAMA_ON_DEMAND=true the bot holds Ollama's port, starts Ollama on the first real request and stops it after OLLAMA_IDLE_STOP_HOURS (4) without use — for every caller, including the ollama CLI. Running on a server: alvin-bot doctor reads configuration from the environment, the pre-flight checks the data folder, a Web-UI-only instance no longer logs "degraded" every 30 seconds, and the Docker guide explains Claude via claude setup-token.

v1.5.157.1 (October 2026): The Maintenance page loads again. One failing request, such as a backup folder holding a symlink whose target is gone, no longer keeps the page on "Loading…": the backup list skips what it cannot read, the server answers a failing API route with a 500, and the page shows each failed part as a finding or a note while the rest stays usable. Tool calls written as <invoke> text run. A model that answers with <invoke name="…"><parameter name="…">…</parameter></invoke> instead of a structured call has it executed through the same command guard, as long as the message is exactly that one call to a tool offered in the turn.

v1.5.157.0 (October 2026): Private memory is private by default. memory/privat/ and dated topic notes are private without any setting, and a workspace grant opens only what is at least as specific as the private prefix (privateQuellen: * opens everything). Facts from compaction stay out of the shared MEMORY.md: main writes to memory/privat/, a workspace lane to memory/ws-<workspace>/, any other lane to its own folder. The index covers projects/, research/, privat/, workspace folders and lane subfolders, removes deleted files and searches vectors held in memory (scan 43 → 11 ms median). Removing a lane in Telegram or the web UI offers Archive (preselected) or Delete for good; deleting a user deletes that user's lanes and lane archives for good. The web UI's memory page shows every notes folder, the lane archive and workspace grants, and saving there works again; every prompt names its memory folder.

v1.5.156.2 (October 2026): Private memory stays where it belongs. PRIVATE_QUELLEN in .env marks memory sources as private; they reach only the main lane and lanes whose workspace lists them under privateQuellen:, never other lanes, the messenger path or background callers. Project notes, semantic recall, /recall, the asset overview and alvin-bot search follow the same rule, and project notes now load only when a message names them instead of on any word like "2026". Without PRIVATE_QUELLEN nothing changes.

v1.5.156.1 (October 2026): The memory index catches up again with Ollama. A short hiccup between Ollama and its model runner (400 … /tokenize … connection reset by peer) used to end the whole reindex, because a run stores its vectors only at the end and the Ollama path did not retry. Index building now retries such hiccups, server errors and dropped connections up to four times; a real error such as a missing model still fails at once. The search inside every turn keeps a single attempt, so no reply waits for a retry.

v1.5.156.0 (September 2026): Files the bot sends show up in the Web UI. Images, PDFs and any other file the bot sends you on Telegram also appear in the lane column of the turn that produced them and, for your own web-chat turns, in the chat — images inline at their final size, everything else as a card with name, type, size and a download link. Agents and scheduled jobs send through the running bot with curl -K "$ALVIN_MEDIEN_CURLRC"; copies are kept for 30 days or up to 1 GB, and MEDIEN_AKTIV=false switches them off without touching delivery.

v1.5.155.0 (September 2026): Restarts no longer interrupt work by surprise. A pill in the top bar shows running jobs, replies and agents, and every restart path offers to wait until they are done (at most RESTART_WHEN_IDLE_MAX_MIN minutes). The chat header gets a new-session button that works like /new, the desktop sidebar folds into an icon rail, lanes can be shown as a list, and the web files ship without source comments.

v1.5.154.0 (September 2026): The Web UI shows formatted replies properly. Replies in the lanes and on the chat page render tables, headings, block quotes, horizontal lines, lists and links as such instead of raw symbols; code stays exactly as written, and emphasis applies only where it was meant — a calculation like 3 * 4 * 5 stays a calculation. Answers to commands such as /status, /help or /lane read as plain text with their line breaks. A lane with agents working in the background says so in words and learns at once when an agent starts or finishes; hovering shows what each one is doing. If you stop a reply halfway, the part you saw stays in the history and your next messages appear below it; a message sent while a reply is running is kept as well, and the lane refreshes right after compaction. Photo, document, voice and video turns now appear in the lane history on every provider, and the lane badge names the model that answered, such as "Claude (Agent SDK) · opus". Link previews of pages not encoded in UTF-8 show the correct characters, long responses keep accents and emoji intact, finished background agents deliver their full result right away, the settings pages handle unusual names more strictly, and editing the fallback order always keeps your primary provider.

v1.5.153.0 (September 2026): Earlier messages carry the time they were sent. A model behind an OpenAI-compatible endpoint used to receive the conversation history as bare text — no hint whether a message was nine minutes or a day old — and a smaller model guessed the distance badly. Each history message now starts with a bracketed timestamp in the bot's timezone, in the same form as now in the date anchor, and the system prompt explains once where it comes from and that the model must never write one itself. The current message is not stamped, older entries without a timestamp go unchanged, a history without stamps sends exactly the prompt it did before, and the Claude path is untouched. Compaction names the window it summarised and shows the summariser each message's time. Daily memory logs and the "Today's Log" / "Yesterday's Log" sections now use the local date of the bot's timezone rather than the UTC date, so a note written at 00:21 no longer lands in yesterday's file.

v1.5.152.0 (September 2026): A message can ask for a briefing before it runs. /pp <request> makes the bot write a short briefing for itself — the goal, the context it already knows, the constraints you wrote quoted verbatim, the output format and what "done" means — and append it beneath your unchanged text; the reply opens with one line saying what was added. Constraints are checked in code: anything not a word-aligned quote of your message is dropped, a lost "not" is dropped, a stray line break rejects the whole briefing, and role-play, step-by-step scaffolds, shouting and numeric length caps are refused. If the small model that writes the briefing is slow, fails or returns something invalid, your message runs exactly as typed — the six-second limit is enforced by the bot, not trusted to the provider. /pro_prompting auto on does the same for every task-shaped message; it is off by default, stays off until you switch it on, and never touches confirmations, replies to the bot's questions, steering notes, forwarded or quoted third-party text, cron jobs, autopilot turns or continuations. The briefing is written by a second model, by default from a different vendor than the one answering you — /pro_prompting status names it, PRO_PROMPTING_MODEL changes it; that model sees the message text and nothing else. Two operator switches stop it for everyone: ALVIN_PRO_PROMPTING=off at start, or the file ~/.alvin-bot/pro-prompting/AUS at any time. Also repaired on the way: thinking models used on the bot's short-call path (lane titles, summaries, memory extraction) now get a reasoning level and stop returning empty output, and the Groq preset no longer points at a retired model. With the prefix absent and the automatic mode off, the prompt handed to your model is byte-identical to the previous release.

v1.5.151.0 (September 2026): A command aimed at a neighbouring service no longer restarts the bot. The launchctl and pkill rules matched on the prefix of the job label and on the process name anywhere in a path, so a neighbouring service was never reached and the bot restarted instead. The full label counts now, a pkill -f pattern is measured against this process's real command line read from the process table, and every pkill/killall of a line is examined, not only the first. A foreign pattern is never compiled — its literal pieces are matched in order — so it cannot stall the synchronous tool path. The destructive-command guard reads the target of the rm that runs instead of the whole line: eight destructive spellings the line scan let through are covered, and a stray / elsewhere no longer refuses ordinary work.

v1.5.150.1 (September 2026): A cron retry after the round limit gets twice the budget on every provider. When a scheduled AI job stopped at its 300 rounds, the retry was supposed to get 600 — but only the Claude Agent SDK's wording ("max turns") was recognised, so jobs on GLM, Ollama and other OpenAI-compatible providers were retried against the same 300. Both wordings count now, and the delivery says "stopped at turn limit" instead of "error".

v1.5.150.0 (September 2026): A message sent mid-turn is no longer left behind. Plain messages typed into a working lane were queued instead of steered whenever the lane ran on a different provider than the globally active one, and a queued message only moved when another one followed; /btw worked because it asked the open channel. Routing now asks the channel's actual reader, queued messages run as their own turn as soon as the running one ends (not after a stop), a steered message the turn never read is carried over instead of dropped, and the column badge reports what really happened. Every lane column has its own stop button — /stopall for that lane only, enabled only while something runs. Column headers are three fixed rows of one height in every column (measured in WebKit and Chromium, 360–1,400 px, with and without touch); the autopilot badge is never shortened, and reset no longer wears the refresh icon.

v1.5.149.1 (September 2026): The rest of the performance audit, finished. The running version sits right-aligned next to "Connected", delivered over the WebSocket itself so the first page load stays at two requests. Lane columns rebuild once per turn instead of two to three times and keep the reader's position — at the rebuild, at the end of a turn and at an error line. The memory index replaces entries only after embedding, reuses unchanged vectors, caps sections at 2,000 characters, drops embedded base64 and cleans its legacy twin of MEMORY.md once. A single missed availability probe no longer escalates into a 25-second outage, video and setup checks leave the main thread, Inter is served locally, and the Ollama cloud context window was measured at 1,048,576 tokens with an explicit 400 beyond it.

v1.5.145.0 (September 2026): The service no longer runs throttled. A ten-agent audit with three-sceptic verification found the bot pinned to the efficiency cores since its first release (ProcessType=Background): priority 4 instead of 20, CPU-bound work 3.1–5.6× slower, a speech synthesis 10.7–12.4 s instead of 2.3, inherited by every detached agent and shell tool. Fixed, along with the Supertonic readiness probe (five synchronous process starts, polled every 8 s = ~6 % of the time frozen), a status poll that kept running on a page you had left, and an audio context leaked once per chat turn.

v1.5.144.2 (September 2026): Read-aloud no longer pauses the bot. Supertonic's readiness probe started three processes synchronously before every synthesis; under load it overran its 3-s limit, stalled the main thread and falsely fell back to Edge. It now runs only until the first successful synthesis (the boot pre-warm counts) and again after a failure.

v1.5.144.1 (September 2026): The startup database check no longer freezes the bot. PRAGMA quick_check on the memory database ran synchronously on the main thread; under I/O pressure it took up to 78 s, during which every timer and answer waited and the web interface was unreachable. It now runs in a worker thread — same check, same verdict, main thread free; a late verdict is reported when it arrives. Failed stall captures are logged with their reason; the read-aloud cache is fully asynchronous.

v1.5.144.0 (September 2026): Hear the whole turn, and have a reply read aloud. Two new cues — Thinking the moment the bot becomes active, Writing at the first streamed character — complete the arc with Sent and Reply, each with its own switch. And every reply carries a small play button: one tap speaks it in the bot's own voice (the same one voice replies use), a second tap stops it; generated only on tap, cached per text, capped at 60 MB.

v1.5.143.0 (September 2026): The login screen names its version, and versions now read as v1. The web interface asked for a password without saying what was behind it; the login page now shows the running version, served by a small public GET /api/version. And what a person reads is now v1.5.143.0 — the leading one marks the first mature generation, the three numbers behind it stay exactly what npm publishes. Everything that compares versions keeps using the package number; a test fails the build if the display string ever reaches a calculating path.

v5.142.3 (September 2026): A stall is caught in the act. The loop watchdog had recorded three stalls of 57–78 s with no culprit named; now a second thread reads a heartbeat every second and, when it stops for three seconds, captures the main thread's native stack with sample while it is still stuck — the blocking call lands in loop-stall.log. Breadcrumbs mark startup phases, the start of a turn and plugin tools.

v5.142.2 (September 2026): The web interface no longer warms up your phone. At idle, with no JavaScript running, the page used 26.6 % of a CPU core — the sidebar's green "connected" dot pulsed by animating its shadow, which the browser repainted on every frame, on every page, for the whole session. Animations now move only opacity and transform, the dot breathes three times after connecting and then rests, and idle usage is 0.5 %.

v5.142.1 (September 2026): Sound cues, now on iOS too — and switchable one by one. On an iPhone only the on/off button's tone played: the cues suspended their audio context after six seconds of quiet, and iOS will not resume it outside a tap. The suspension is gone, the context is created on your first tap, and it is woken when the tab returns from the background. Every cue has its own switch under Settings, with a preview beside it.

v5.142.0 (September 2026): Sound cues. The web interface plays short synthetic tones for what the bot is doing — a reply finished, an agent started or done, an autopilot switched on, each run (duller when it brought nothing new), switched off, an error, a provider switch. Eleven cues, none over 0.6 s, built on the spot from two or three oscillators: no audio files, nothing running while idle, and a cooldown so five runs in a second are one ping. On/off, volume and a preview per cue live under Settings, plus a Sound button in the sidebar.

v5.141.0 (September 2026): Web search fails honestly instead of on its own parser. web_search on the generic lane crashed with "Unexpected end of JSON input" when DuckDuckGo throttled; its fallback used grep -oP, which macOS does not have, so it could never return anything there. Both are fixed, results are extracted in JavaScript, and a bot challenge (which both engines now serve to command-line requests) is reported as such — not as "no results". The system doctor's "Empty values found in .env" warning now names the keys and is informational: empty means off.

v5.140.0 (September 2026): Workspaces can be removed. Creating one has always been possible from the web interface; removing one was not — the only way was to delete the .md by hand. Each card now has a Remove button, and Telegram gains /workspace rm <name>. Both name what is bound to it first: which lanes lose their binding, how many sessions fall back to the default directory, how many users have it active. All three are released when it goes, so no lane keeps running in the wrong directory unannounced. default stays, and so do the working directory, every message and the lanes themselves.

v5.139.0 (September 2026): Nothing blocks, nothing freezes, nothing stops at a limit. A conversation's system prompt is recorded once by Claude Code and reused verbatim — so everything that changes now travels with the message instead, and a session that runs for days no longer answers with the time it started. Hitting a quota locks that account until its stated reset and the answer comes from the next link of your chain, with one line saying so. Shell and Python may take ten minutes instead of thirty seconds. Reading a file no longer halts the whole bot, and if the loop stalls anyway, a watchdog writes down how long and at what. Background agents get the same permissions as the chat, the fencing of external content works again after two months of being silently rejected, ALVIN_FREIE_HAND=1 lifts every tool guard for owners who want that, and the web interface's Cron page gains filters and bulk actions.

v5.138.0 (September 2026): Autopilot off means off — including what it started. Jobs and background agents an autopilot run starts now remember that run. /autopilot off lists whatever of it is still running, with buttons to pause the jobs, stop the agents, or keep them; the same list arrives when a run ends at one of your limits or its lane is removed. Nothing stops without a tap, jobs are paused rather than deleted, and jobs you asked for yourself never appear. A background agent that finishes after its run has ended hands over to a normal turn, and /cron and the web job card show where a job came from.

v5.137.1 (September 2026): Lane titles are back — light, stable and never in the way. A lane you have not named gets a short title for what it is about right now, in the web board and in /lanes on Telegram. It stays while the topic stays and changes when the conversation moves on: a local check decides without any model call, and only a real topic change asks the lane's own model — once, over its lightest route, after the answer, cancelled the moment you write again. Returning to an earlier topic brings its title back for free, and a name you typed always wins. Since v5.137.1, clearing a lane's name titles it from its conversation right away, also directly after a restart.

v5.136.0 (September 2026): You decide which Claude model runs, everywhere it runs. Without a choice of your own, Claude (Agent SDK) now runs on Opus — always the newest one. /provider sets Claude's model for everything that has no model of its own (conversations and lanes without a pin, background agents, scheduled jobs on "Claude (Agent SDK)"), and model choices — including the web chat's header — say what that entry runs today. /model only ever changes the lane you are in, and a provider that is a single model says so instead of offering a list that does not apply. Every scheduled AI job gets its own effort setting next to its model; jobs without one now run at medium like a conversation. Your /effort counts the same for text, photos, voice, video, documents, the other chat platforms and the web dashboard, and background agents follow the effort of the turn that started them.

v5.133.0 (September 2026): The bot measures its own hands, and gains eyes and a reader. A local model is no longer routed by its address: it is measured once — native tool calls, the text protocol, a read-then-write chain — and afterwards takes the simplest path it actually passed, with the offline harness kept as the fallback for the models that need it. /status and alvin-bot doctor show a 🖐 Hands: line, /model test measures again, WERKZEUGWEG forces a path. A model without vision now gets the bot's eyes: the macOS Vision framework first, a local vision model in Ollama second, delivered as a fenced description — with read_image taking a question and look_again asking about the last image. PDFs and Office files arrive as text on every non-Claude lane, on upload and through the new read_document tool, read on macOS with PDFKit before any command-line helper. And the harness is honest: a silent model yields an error instead of an echo of its own plan, facts travel between steps, and a task it cannot carry finishes in the plain tool loop of the same turn.

v5.132.1 (September 2026): Correction release. A password or API key saved through the setup wizard, /setup key, the environment editor or alvin-bot setup is stored in the form the bot reads back on start — a #, a space or a quote in the value no longer changes it between "saved" and "running". Link previews classify destinations with the bot's shared network guard and connect to the exact address they checked. read_image asks the resizer for PNG explicitly. Autopilot on sees its own ending in laut mode, keeps watching after a failed run, keeps a replaced run's turn out of its successor, and on budget 5 sets a budget. The heartbeat fails over along the chain in effect, a background result arrives as capped text when its upload does not, a file sends without a caption, and $ survives Iterate.

v5.132.0 (September 2026): The web UI answers, iterates and previews. Every message gains two buttons — Reply quotes what it sits on, Iterate sends the bot's own result back to it to assess what is weak and improve only where there is something substantial, ending with an honest verdict ("Improved: …" or "Nothing substantial to improve, because …"). Links in bot messages arrive as preview cards — title, domain, description, thumbnail — loaded lazily when the bubble scrolls into view, silent on failure. And autopilot gains an "on" mode: the lane derives its task from its own context, works until done, announces the hand-off, and then watches — a typed message in the lane prompts a rate-limited look-around, while its own turns never do; the status line shows on · working/watching.

v5.131.0 (September 2026): Images reach the model as images. A new read_image tool hands local PNG, JPEG, WebP and GIF files to the model as a picture — the format read from the content, oversized images downscaled instead of rejected — and a tool result's image survives the redirect to GLM, OpenRouter or a local Ollama as its own message instead of arriving as a "not forwarded" note; MCP clients see real image content. Telegram replies that quote foreign text — a group title, a job name, a model tag with an underscore — used to die whole on one character; every such spot escapes the text now, and the ollama model-card buttons take the same routes as the typed commands. Promoting a fallback provider is one decision everywhere, a held chain holds for a pinned lane, and promised work arrives: no paid follow-up turn after an autopilot is switched off, no double delivery after a restart, and on Slack, Discord and WhatsApp a background agent's result reaches the session history too. Attachments count as delivered only when the upload actually went through.

v5.130.0 (September 2026): In an autopilot run, a finding is a task, not an offer. Every autopilot run tells the model its situation — nobody is reading along, nobody will answer a question; fix, verify, report — and a run that still ends with a question gets one follow-up in the same run, and no more.

v5.129.0 (September 2026): A background agent's result now lands in the lane it was started from. The web dashboard's lane column renders the lane's history, and on the default Telegram delivery path that history only ever received a truncated completion note — the summary itself went to Telegram alone. Both delivery paths now write the same three entries (status line, summary, attribution note), the completion note no longer claims a delivery it cannot see, and its excerpt ends at a sentence. Also: a lane whose workspace folder has disappeared no longer throws inside the bot when an agent is started — the agent answers with a clear message instead.

v5.128.0 (September 2026): Model names are looked up, not remembered. Every list of Anthropic and OpenAI models — /model, the dashboard, the setup wizard, /status — now comes from the live catalogues: your API key, your signed-in Claude CLI (the same list Claude Code's /model shows, no key and no tokens needed), or OpenRouter's public catalogue, cached for six hours and refreshed in the background, without a cron. The aliases opus, sonnet, haiku and fable keep working and now say what they resolve to today (opus → Claude Opus 5). A new openai-latest provider runs whatever GPT flagship exists on the day the bot starts, and with an OpenAI key the model list finally includes the current generation instead of stopping at GPT-4. Every list names its source and date; a short built-in list is the last resort only.

v5.127.0 (September 2026): Voice messages are transcribed on your own machine. A local Whisper is used when one is installed — no key, no network, nothing leaving the box; on an Apple M4 a five-minute message takes about eleven seconds. Groq remains the fallback and the reason for every switch is logged. Errors from the speech API now say what happened instead of collapsing into "could not understand the voice message".

v5.91.0 (August 2026): A workspace file that grows without bound no longer taxes every message. Notes kept in a workspace CLAUDE.md are read into every turn; a file grown past 400 KB was measured at roughly 280.000 tokens for a one-word answer. Dated records are now moved to sibling files on demand, rules stay resident, and nothing is ever lost — the rewrite is checked line by line and abandoned if even one line would go missing. Full changelog →

v5.90 (August 2026): Ollama's cloud models now work as a provider. Ollama Pro serves frontier models through the same local port as your downloaded ones; the bot used to declare them missing (they never appear in the local catalogue) and route them through the scaffold built for small local models, which returned an empty answer. Both are fixed, local models keep their behaviour unchanged. Also: the test suite no longer depends on whether an Ollama daemon happens to be running on the machine. Full changelog →

v5.89 (August 2026): Running the bot on a server in Docker now takes one command. alvin-bot docker init writes a Dockerfile, a compose file and a .env template into a directory you choose; docker compose up -d does the rest. The image is built from the published npm package rather than a repository checkout, so there is nothing to clone and nothing to keep in sync. Chromium is included, data lives in a named volume that survives a full recreate, and the Web UI is bound to loopback by default. Also fixed: notes, calendar and smart-home data were stored inside the installed package, where a global install cannot write them and the next npm update would erase them — they now live in the data directory. Full changelog →

v5.88 (August 2026): Lanes can now be created from the browser and pointed at a workspace. Opening a parallel workstream meant switching to Telegram, and binding one to a project context meant a command the Web UI never mentioned. The Lanes view now creates lanes, assigns their workspace from the column header, and can add a workspace itself — name, purpose, working directory, emoji, colour. Changing a lane's workspace later is allowed and says beforehand what it costs: the column keeps its messages while the model loses the thread, plus, for a workspace that shares lane memory, that this lane's daily logs become readable by the other lanes there. A working directory is now stored exactly as entered or refused, never silently normalised into a different one. Full changelog →

v5.87 (August 2026): The bot can now run an adversarial build loop in the background. /gauntlet [light|medium|heavy] <instruction> hands a task to a detached worker that implements it test-first, then sets independent critic agents on the result — correctness, regression, and at heavy a mutation critic that writes changes which keep every assertion intact yet break the behaviour, so tests that only look thorough are exposed. Only real defects trigger another round; cosmetic findings are reported, not iterated on. The chat stays free while it runs, and /subagents cancel stops it. Full changelog →

v5.86 (August 2026): Lane columns can now be reset, renamed and cleared out from the browser. The Lanes view could show parallel workstreams but not manage them. It now has per-lane reset, rename and delete; columns order by last activity so a lane you just watched finish stays put; the header reports tokens rather than dollars; every message carries a date; a badge shows how many sub-agents a lane is running; and files can be dragged straight into a column, streamed to disk under a size cap instead of held in memory. Three fixes as well: answers no longer disappear from a column after finishing, the view reconciles itself after a dropped connection instead of needing a reload, and a finished sub-agent's result is no longer painted as if you had typed it. Full changelog →

v5.85 (August 2026): The bot now recovers from a stuck Telegram connection without restarting itself. Its in-process repair for stuck polling used to be cut off a fraction of a second before it would have worked — the health check judged a freshly restarted polling loop by its predecessor's last success, with a grace period exactly as long as one poll request. Polling health is now judged against each loop's own start time, and the grace period is derived from the real poll timeout instead of coincidentally matching it. A reproduction against a real polling stack went from zero successful recoveries out of seventeen to fourteen out of fifteen; a genuinely stuck connection still escalates to a full restart as before. Full changelog →

v5.84 (August 2026): The bot now makes sure it comes back after restarting itself. Its last-resort self-repair used to be a plain exit, trusting the operating system to notice and relaunch it — if it wasn't actually watching, the bot could stay down indefinitely. On macOS it now hands off to a small helper that waits for the old process to disappear and explicitly tells the service manager to start it again, and the message you get says which route was actually taken. Never two bots at once: the hand-off only acts once the old process is confirmed gone. Also: the bot now checks that its own outside safety-net watcher is still ticking, and tells you once if it has gone quiet. Full changelog →

v5.83 (August 2026): Background agents now work from voice, photo, document and video messages, not just text. Those four message types — and the web chat — were quietly falling back to a temporary in-session helper that dies the moment the turn ends; all of them now dispatch a real, detached agent that survives it. Also: an empty answer used to cost up to ten minutes while a stuck automatic retry sat silent — it now starts clean and reports back in seconds if it fails, though that turn still needs to be sent again. Full changelog →


✨ Features

🧠 Intelligence

  • Multi-model engine — Claude Agent SDK · OpenAI · Groq · NVIDIA NIM · Gemini · OpenRouter · Ollama · Codex CLI · any OpenAI-compatible API
  • Automatic fallback + heartbeat monitor — checks providers every 5 min (token-free for API-key providers — the free models endpoint, not a paid completion), auto-failover after 2 failures, auto-recovery; reorder priority via Telegram /fallback, Web UI, or API
  • Adjustable thinking depth & answer length — /effort low to /effort max; /verbosity short|medium|full applies on every input path (text, voice, photos, documents, web)
  • Pluggable memory backends (v4.22) — Gemini · OpenAI · lokal (in-process, no Ollama/key) · Ollama · FTS5 keyword fallback. Auto-detection picks the best available. Indexed search across MEMORY.md, daily logs, project files, hub memory, asset index. Override via EMBEDDINGS_PROVIDER.
  • Smart system-prompt injection (v4.22) — once SQLite is populated, stops bulk-injecting MEMORY.md and surfaces only the chunks relevant to the user's current message. Cuts ~25 k tokens per turn for typical setups. MEMORY_INJECT_MODE=auto|legacy|sqlite to override.
  • Layered memory (L0–L3) — identity.md + preferences.md always plain-text · project memories on topic match · daily logs / curated knowledge via semantic or keyword search
  • Persistent sessions — Claude SDK resume tokens, conversation history, language, effort survive bot restarts
  • Multi-session workspaces — parallel context-isolated sessions per Slack channel or /workspace switch, each with its own cwd, purpose, persona. Memory + skills stay globally shared. How-to ↓
  • Detached sub-agents — alvin_dispatch_agent MCP tool spawns independent claude -p subprocesses that survive parent aborts. Results deliver as separate messages; /subagents list shows live per-task health (dead process, stalled output) and /subagents cancel stops them safely. Optional cost routing sends light tasks to a cheaper model (SUBAGENT_AUTO_ROUTE). Works identically on Telegram / Slack / Discord / WhatsApp.
  • Smart tool discovery — scans your system at startup; typical install surfaces 30–70 tools depending on what's locally available
  • Skill system — 14 SKILL.md files (see Skills ↓) auto-activate based on message context
  • Self-awareness + auto-language — knows it IS the AI · detects EN/DE/ES/FR and adapts; learns preference over time

💬 Multi-Platform

  • Telegram — streaming, inline keyboards, voice, photos, documents
  • Slack — Socket Mode via @slack/bolt, DMs + @mentions, file attachments, assistant.threads.setStatus typing. One channel = one isolated workspace.
  • WhatsApp — via WhatsApp Web; self-chat as AI notepad, group whitelist with per-contact access, full media. Owner approval gate routes to Telegram (DM / Discord / Signal fallback) before the bot replies.
  • Discord — server bot with mention/reply detection and slash commands
  • Signal — via signal-cli REST API, voice transcription
  • Terminal — rich TUI with ANSI colors + streaming (alvin-bot tui)
  • Web UI — full dashboard, chat, settings, file manager, terminal, workspace overview, live Lanes view (v5.82)

🔧 Capabilities

  • Tool layer — Shell · files · Python · git · email · PDF · media · vision · screenshots · system control. Universal tool use across any provider that supports function calling; text-only fallback for those that don't.
  • 6 built-in plugins — weather · finance · notes · calendar · email · smarthome
  • MCP client — connect any Model Context Protocol server
  • Cron — AI-driven scheduled tasks ("check my email every morning"), @daily/@hourly shorthand, shell jobs run without blocking the bot, and a self-healing scheduler that restarts itself in-process if it ever wedges
  • Voice — speech-to-text on your own machine via Whisper (no key, no network), Groq as the fallback; TTS via Edge TTS or ElevenLabs
  • Vision + image generation — photo / document analysis · Gemini / DALL·E generation with API key
  • Browser — 4-tier strategy: WebFetch · stealth Playwright · CDP with persistent profile · agent-browser CLI (Tier-1.5, opt-in)

🖥️ Web Dashboard

  • WebSocket streaming chat · model switcher · platform & provider setup · file manager · memory editor · session browser · in-browser terminal · maintenance + health · workspace cards with cost aggregation

Files in the Web UI

Every file the bot sends you (images, PDFs, any file) also appears in the Web UI: in the lane column of the turn that produced it and, for your own web-chat turns, in the chat. Agents and cron jobs send files through the running bot:

curl -K "$ALVIN_MEDIEN_CURLRC" --data-urlencode "pfad=/abs/report.pdf" --data-urlencode "caption=Weekly report"

This needs curl 8.3.0 or newer. For people at a terminal there is a convenience command, run from the installation directory: node <install dir>/bin/cli.js send-file <path> [--caption …].


⚖️ How Alvin Bot compares

Alvin Bot sits in the same category as Hermes Agent (Nous Research) and OpenClaw — self-hosted personal AI agents that live on your machine and reach you on the chat apps you already use. They optimize for different things. This table is intended to be fair: where Hermes or OpenClaw is the better tool, it says so.

| Dimension | Alvin Bot | Hermes Agent | OpenClaw | |---|---|---|---| | License / hosting | Proprietary · self-hosted · local-first · zero telemetry | MIT · self-hosted · 7 execution backends | Open-source · self-hosted · bring-your-own-key | | Model providers | Claude Agent SDK + OpenAI · Groq · Gemini · NVIDIA NIM · OpenRouter · Ollama, with automatic failover after 2 provider failures + a 5-min heartbeat monitor | 200+ models | Bring-your-own model / key | | Sub-agents | Detached claude -p subprocesses that survive a parent abort; readonly/research toolset presets | Isolated subagents for parallel workstreams | Not a primary focus | | Browser automation | 4-tier escalation: WebFetch → stealth Playwright → persistent-profile CDP → agent-browser CLI | Built-in browse / vision tools | Via tools | | Platforms | Telegram · Slack · Discord · WhatsApp · Signal · terminal TUI · Web (7) | 20+ platforms from one gateway | 25–50+ platforms · native mobile apps · voice activation | | Memory | Layered L0–L3; SQLite embeddings with a zero-config FTS5 keyword fallback (works with no API key); smart prompt-injection trims ~25 k tokens/turn | SQLite + full-text search · agent-curated · Honcho user profiling | Transparent plain Markdown/YAML files you can grep and git-track | | Extensibility | Hot-reload skills + 6 plugins · self-modifying skills · hooks · MCP client | 40+ built-in tools · autonomous self-improving skill loop | Skills as files · very large ecosystem | | MCP | MCP client (connect any MCP server) | MCP client and hermes mcp serve (acts as an MCP server for Claude Desktop / Cursor / VS Code) | Tool integrations | | Self-healing | Startup preflight · dead-man's-switch heartbeat · crash forensic bundles · AI self-diagnosis · crash-loop brake · trend anomaly detection | Stable in practice; self-improving | Frequent updates can break running instances | | Security defaults | Exec allowlist + shell-metachar filter on by default · DM pairing · timing-safe webhook auth · 0600 file perms enforced · alvin-bot audit CLI · honestly documented threat model | Standard | Standard | | Real-time voice | Built into the web UI (laptop or phone browser, no telephony or plugin): Gemini Live is the voice, every request runs through the full harness in parallel lanes while you keep talking; exact cost per voice session | Built-in voice mode (CLI push-to-talk, Discord voice); continuous talk-while-it-works via community add-ons | Voice Call plugin with real-time Gemini Live / OpenAI over Twilio or Telnyx, consulting the main agent; voice activation in native apps | | Maturity / community | Small, focused, single-maintainer; modest public adoption | Large community, Nous Research team | Large community + team, Nvidia NemoClaw fork |

Use the right tool for the job

  • Use Alvin Bot when you want one resilient, self-healing agent on your own box that keeps working when a provider rate-limits or fails, gives you indexed memory without buying an embedding API key, ships safe-by-default execution sandboxing, and is built directly on the official Claude Agent SDK — and you mainly live in Telegram / Slack / Discord / WhatsApp / Signal.
  • Use Hermes Agent when you want a research-grade self-improving agent, need it to act as an MCP server for Claude Desktop / Cursor / VS Code, want 200+ model choice or many execution backends, and value a large community.
  • Use OpenClaw when you want the widest messaging reach (25–50+ channels) plus native mobile apps and voice activation, fully transparent plain-file memory you can git-track, and the largest ecosystem.

A longer head-to-head with FAQ and decision guide: Alvin Bot vs Hermes vs OpenClaw.


🚀 Quick Start

Brand-new machine? One line is all you need — even with nothing installed (no Homebrew, no Xcode tools, no Node, no admin password):

curl -fsSL https://unpkg.com/alvin-bot/install.sh | bash

It reuses an existing Node if you have one, otherwise fetches a self-contained Node into your home folder, installs Alvin into a user-owned location (never sudo, nothing system-wide), and launches the setup wizard.

Already have Node 18+? The classic three commands work too:

npm install -g alvin-bot
alvin-bot setup
alvin-bot start

Either way, the setup wizard validates everything:

  • ✅ Lets you pick your AI provider and tests the key
  • ✅ Verifies your Telegram bot token
  • ✅ Confirms the setup works before you start

You'll need: a Telegram bot token (@BotFather) · your Telegram user ID (@userinfobot). Node.js 18+ (nodejs.org) is auto-installed by the one-line script if missing.

WhatsApp is optional. Telegram, Slack, Discord, terminal and the web UI work out of the box. The WhatsApp connector is an opt-in add-on (it needs a couple of extra packages) — enable it any time from the Web UI (Platforms → Install Dependencies); the bot shows you the exact one-line command when you first try to use it.

Native build note: Alvin Bot uses better-sqlite3 for indexed memory. Prebuilt binaries are included for common macOS and Linux environments so most installs need nothing extra. If your platform doesn't have a prebuilt binary and the optional native compilation is skipped, the bot still runs — semantic memory falls back gracefully to keyword search. A C++ toolchain (Xcode Command Line Tools on macOS, build-essential on Ubuntu) and Python 3 are only needed if you hit a build-from-source fallback.

Free AI providers available — no credit card needed. Privacy-first? Pick the 🔒 Offline — Gemma 4 E4B option in setup for a fully local LLM via Ollama (macOS/Linux: automated install; Windows: manual).

📘 First-time setup walkthrough

| Platform | Guide | |---|---| | 🪟 Windows (WSL + Task Scheduler for 24/7) | Online guide |

Covers: Node.js install · Telegram bot creation · first-time setup · foreground test · background service · offline Gemma 4 mode · troubleshooting.

🔐 A note on permission prompts

The first time Alvin reaches for a new tool — a shell command, a file read, a web fetch — you may see a permission prompt from the underlying agent runtime asking whether to allow it. Those prompts come from Alvin himself, not from a third party. Approving one expands what he can do for you autonomously; denying keeps the scope narrow. The more you allow, the more capable and hands-off he becomes — you stay in control either way, and you can always revoke a permission later.

macOS only — one extra step under launchd. If you install Alvin as a background service (alvin-bot launchd install), macOS won't be able to show you those permission dialogs interactively anymore. To let the bot and anything it spawns (Codex CLI, file-reading skills) actually read your files, grant Full Disk Access to node once: System Settings → Privacy & Security → Full Disk Access → + → add /opt/homebrew/Cellar/node/<version>/bin/node (find the exact path with readlink -f "$(which node)"). alvin-bot launchd install and alvin-bot doctor will both detect and remind you with the exact path. After brew upgrade node you'll need to re-grant, because TCC binds to the versioned Cellar path. The macOS setup walkthrough covers this end-to-end.

macOS: use launchd instead of pm2 (recommended)

If you're on macOS and using Claude Code (Max subscription) as your provider, run the bot as a LaunchAgent — it inherits the GUI login session so the macOS Keychain stays unlocked and the Claude OAuth token just works without any manual security unlock-keychain dance:

alvin-bot launchd install    # writes ~/Library/LaunchAgents/com.alvinbot.app.plist and starts the agent
alvin-bot launchd status     # show PID + recent stdout/stderr logs
alvin-bot launchd uninstall  # unload + remove the plist

Pm2 still works and remains the default on Linux/Windows — but on macOS with Claude Code, launchd is the only path that reliably keeps Keychain access over restarts.

📖 Handbook

For a full walkthrough of everything Alvin Bot can do — providers, sub-agents, cron jobs, plugins, MCP, security audit, web UI — read docs/HANDBOOK.md.

AI Providers

| Provider | Cost | Best for | |----------|------|----------| | Groq | Free | Getting started fast | | Google Gemini | Free | Image understanding, embeddings | | NVIDIA NIM | Free | Tool use, 150+ models | | OpenAI | Paid | The newest GPT, picked for you (openai-latest) | | OpenRouter | Paid | 100+ models marketplace | | Claude SDK | Paid* | Full agent with tool use |

*Claude SDK requires a Claude Max subscription ($20/mo) or Anthropic API access. The setup wizard checks this automatically.

Model names stay current — no cron, no release

Anthropic and OpenAI ship new models faster than any bot can hard-code their names. Alvin therefore looks them up instead of remembering them. Whenever a list of models is shown — /model, the models page of the dashboard, the setup wizard, /status — the bot asks, in this order:

| Family | Sources, first answer wins | |--------|----------------------------| | Anthropic | your ANTHROPIC_API_KEY → your signed-in Claude CLI (no key, no tokens; the same list Claude Code's /model shows) → OpenRouter's public catalogue | | OpenAI | your OPENAI_API_KEY → OpenRouter's public catalogue |

The answer is cached for six hours (memory and ~/.alvin-bot/model-directory.json) and refreshed in the background when it is older; nothing runs on a schedule, and a network that does not answer never blocks a page. Every list says where it came from and when. Only if every source fails does a short built-in list apply, and it says so.

What this changes in practice:

  • The tier aliases opus, sonnet, haiku and fable keep working exactly as before, and every place that shows them also shows what they resolve to today (opus → Claude Opus 5).
  • openai-latest is the OpenAI twin of claude-opus (auto-latest): it runs whatever GPT flagship exists on the day the bot starts. OPENAI_MODEL still pins a specific model.
  • With an OpenAI key, /model lists every chat-capable model your key can reach, current generation included.

MODEL_DIRECTORY=off disables all lookups (air-gapped hosts); the built-in list is then the only source.

Alternative Installation

The one-liner from Quick Start, served from a second CDN if the first is blocked:

curl -fsSL https://cdn.jsdelivr.net/npm/alvin-bot/install.sh | bash

Bootstraps Node if missing (self-contained, no sudo), installs Alvin into a user-owned location, and runs the setup wizard automatically.

| Platform | Download | Architecture | |----------|----------|-------------| | macOS | Coming soon | Apple Silicon (M1+) | | Windows | Coming soon | x64 | | Linux | Coming soon | x64 |

The desktop app auto-starts the bot and provides a system tray icon with quick controls.

npm install -g alvin-bot
mkdir -p /opt/alvin-bot && cd /opt/alvin-bot
alvin-bot docker init      # writes Dockerfile, docker-compose.yml and .env here
# edit .env — BOT_TOKEN, ALLOWED_USERS, one AI provider
docker compose up -d

The image is built from the published npm package, so there is no repository to clone. Chromium is included, the Web UI is bound to loopback (reach it over an SSH tunnel), and everything the bot writes lives in a named volume that survives upgrades.

Claude in a container — run claude setup-token once on your own machine and put the token in .env as CLAUDE_CODE_OAUTH_TOKEN (with PRIMARY_PROVIDER=claude-sdk). Groq, Gemini, OpenAI or a local Ollama work too.

Full guide: docs/install/docker.md

npm install -g pm2
pm2 start ecosystem.config.cjs
pm2 save && pm2 startup

Troubleshooting

alvin-bot doctor        # Check configuration & validate connections

If your AI provider isn't working, run doctor — it tests the actual API connection and shows exactly what's wrong.


📋 Commands

| Command | Description | |---------|-------------| | /help | Show all commands | | /start | Session status overview | | /new | Fresh conversation (reset context) | | /model | Choose the model of the lane you are in (inline keyboard) | | /effort <low\|medium\|high\|xhigh\|max> | Set thinking depth | | /voice | Toggle voice replies | | /imagine <prompt> | Generate images | | /web <query> | Search the web | | /remind <time> <text> | Set reminders (e.g., /remind 30m Call mom) | | /cron | Manage scheduled tasks | | /kontingent (alias /quota) | Show quota locks, release them (frei), or set a test lock (test 2m) — while an account is used up, the fallback chain answers | | /recall <query> | Search memory | | /remember <text> | Save to memory | | /export | Export conversation | | /dir <path> | Change working directory | | /workspaces | List all configured workspaces (v4.12.0) | | /workspace [name] | Show or switch the active workspace — /workspace default resets (v4.12.0) | | /workspace rm <name> | Remove a workspace — names what is bound to it first, then confirm deletes it (v5.140.0). The working directory and every message stay | | /status | Current session & cost info | | /setup | Configure API keys & platforms | | /system <prompt> | Set custom system prompt | | /fallback | View & reorder provider fallback chain | | /skills | List available skills & their triggers | | /lang <de\|en\|auto> | Set or auto-detect response language | | /cancel | Abort running request | | /reload | Hot-reload personality (SOUL.md) | | /finish | Wrap up the current turn — the model finishes its thought and stops | | /pp <request> | Refine this one message before it runs | | /pro_prompting | Automatic refinement on/off, status, own entries | | /lane <name> | Switch to (or create) a lane — a parallel workstream with its own context | | /focus <name> | Alias of /lane | | /lanes | Dashboard of all lanes | | /autopilot <task…> | This lane keeps working on it alone until you stop it | | /provider | Which provider serves this conversation; switch the global one and its Claude (Agent SDK) sub-model | | /models | Browse and pin models | | /ollama | Manage local and cloud Ollama models | | /openrouter | Manage OpenRouter models | | /memory | Inspect what has been remembered | | /reindex | Rebuild the memory index | | /note <text> | File a note without starting a turn | | /tools | Which tools the serving model actually has | | /sub_agents | Background agents: what is running, what came back | | /browse <url> | Fetch and read a page | | /webui | Open the web interface | | /mcp | Manage MCP servers | | /plugins | Manage plugins | | /groups | Group-chat settings | | /security | Security posture and permissions | | /users | Who may talk to this bot | | /lean | Trim the context for small local models | | /autoupdate <on\|off> | Automatic updates | | /version | Which version is running | | /ping | Is it alive | | /about | What this does, whose terms apply, and that use is at your own risk |


🏗️ Architecture

  Telegram   Slack   WhatsApp   Discord   Signal   Web UI · TUI · CLI
      └─────────┴─────────┴────┬────┴─────────┴───────────┘
                               ▼
              Workspace Resolver  (per-channel cwd + persona)
                               ▼
                 Engine  (routing · fallback · heartbeat)
        ┌──────────────────────┼───────────────────────────┐
        ▼                      ▼                            ▼
   Claude SDK         OpenAI · Groq · Gemini ·      Ollama · Codex CLI ·
                      NVIDIA · OpenRouter           OpenAI-compatible
        │
        ├─ reads ▶  Memory Layer
        │              ├─ L0 / L1 — identity.md · preferences.md (always plain-text)
        │              └─ SQLite store — provider auto-detect (Gemini · OpenAI · Ollama · FTS5)
        │
        └─ dispatches ▶  Detached sub-agents  (independent `claude -p`, survive parent abort)

Rendered as plain text so it displays identically on npm and GitHub (npm's README renderer does not support Mermaid diagrams).

Provider matrix

| Provider | Tool use | Streaming | Vision | Auth | |---|---|---|---|---| | Claude SDK (Agent) | ✅ native (Bash, Read, Write, Web, MCP) | ✅ | ✅ | Claude CLI OAuth | | OpenAI · Groq · Gemini · NVIDIA NIM · OpenRouter | ✅ universal tool use | ✅ | varies | API key | | Ollama (local) | ✅ via tool-bridge | ✅ | varies | none | | Codex CLI | ✅ subprocess | ✅ | — | Codex CLI auth | | Any OpenAI-compatible | ⚡ auto-detect | ✅ | varies | API key |

Universal tool use — Alvin gives full agent powers to any provider that supports function calling. Shell · files · Python · web work everywhere; providers without tool calls degrade cleanly to text-only chat.

Project layout

src/
├── index.ts                 entry point
├── engine.ts                multi-model query engine
├── handlers/                message + command handlers
├── platforms/               Telegram · Slack · WhatsApp · Discord · Signal
├── providers/               Claude SDK · OpenAI-compat · Ollama · Codex CLI
├── services/
│   ├── embeddings/          v4.22 pluggable provider facade (Gemini/OpenAI/Ollama/FTS5)
│   ├── memory*.ts           layered memory (L0-L3) + inject-mode resolver
│   ├── workspaces.ts        per-channel cwd + persona registry
│   ├── alvin-dispatch.ts    detached sub-agent orchestration
│   ├── browser-manager.ts   4-tier browser strategy
│   └── …                    cron · voice · skills · MCP · hooks · …
├── tui/                     terminal chat UI
└── web/                     dashboard server + APIs
web/public/                  zero-build HTML/CSS/JS UI
plugins/                     6 built-in plugins (hot-reload)
skills/                      14 SKILL.md files (hot-reload)
bin/cli.js                   CLI entry point
electron/                    Electron wrapper for the .dmg build

🛣️ Lanes — parallel workstreams

A lane is a separate line of work with its own conversation, its own context and its own model. Switching lanes does not disturb the others; they can run at the same time.

/lane research          # switch to it, or create it on first use
/lanes                  # dashboard: what each lane is doing, what it costs
/lane research in ops   # bind a lane to a workspace (persona, cwd, model)
/lane model research groq   # pin one model to one lane
/lane budget research 5     # per-day spend cap for that lane alone
/lane rm research           # remove it, with its conversation

You can also address a lane without leaving the one you are in:

@research: check whether the export finished

main is the ordinary conversation. It is a lane like the others in most respects, but it follows /provider globally rather than a per-lane pin.

Autopilot — a lane that keeps working on its own

Switch a lane to autopilot and it carries on without you typing. The task is sent again on every run, unchanged.

/autopilot work through the migration checklist step by step
/autopilot status
/autopilot off

It runs until you stop it. There is no run limit and no spend limit unless you set one — most people run on a subscription, where a run is not a billing event. Limits are yours to choose:

/autopilot draft the release notes every 30m
/autopilot review the open tickets max 50
/autopilot summarise new mail budget 5
/autopilot watch the build every 15m max 100 budget 2.50 laut

| Switch | Effect | |---|---| | every 30m / every 2h | Your own interval (default 2h, from 1 minute to 7 days) | | max 50 | Stop after that many runs | | budget 5 | Stop at that spend, in USD, counted across the whole run | | laut | Post every run in the chat (default: quiet) |

Switches are only read at the end of the line, so check the filing every 45 min stays a task rather than being cut in half.

By default a run is quiet: it appears in the lane column of the web interface, while the chat gets the start, the end, and anything that goes wrong. Twenty-four runs over two days would otherwise be two dozen messages, half of them at night.

If the same answer comes back three times in a row you get one notice and it keeps going — three times the same thing usually means stuck, but sometimes it means legitimately waiting, and only you can tell those apart.

A finding is a task, not an offer. Every autopilot run tells the model what situation it is in: nobody is reading along and nobody will answer a question. Something it notices within the lane's assignment gets fixed, verified and reported as done — not offered with "let me know if I should". Only what is irreversible, outside the assignment, or spends money with a third party stays undone, stated in one sentence, and the run carries on. Open points from the previous run are the next run's first task, and background agents started from an autopilot run work under the same rules. Should a run still end with a question or an offer, the autopilot follows up once in the same run ("nobody will answer — do it now") and then leaves it at that; a second follow-up would be a loop. When you type into the lane yourself, none of this applies — you are there to answer.

Off means off — including what it started. A run may schedule jobs and start background agents; both remember the run that created them, also when a tool writes a job straight into the job file while the run is the only one working in that chat. /autopilot off lists whatever of it is still running under its confirmation, with buttons: pause the jobs, stop the agents, stop both, or keep them running. Nothing stops without a tap, and jobs are paused, not deleted — /cron resumes them. The same list arrives when a run ends at one of your limits and when you remove the lane. Jobs you ask for yourself in the lane's conversation never appear on it. A background agent that finishes after its run has ended hands its result to a normal turn, not an unattended one.

Three things it will not do: no lane carries an autopilot of its own accord, there is no global switch, and main cannot have one — main is the conversation.

You are responsible for what it does. It acts under your accounts and your credentials, unattended, for as long as you leave it running. See /about.

🎙️ Local speech-to-text

Voice messages are transcribed on your own machine when a local Whisper is available. No key, no network, nothing leaving the box. Groq stays as the fallback, so nothing breaks if you have neither.

Measured on an Apple M4, model small, German speech:

| Path | 22 s of speech | A 5-minute message | |---|---|---| | whisper.cpp (warm) | 1.1 s — 21× real time | ~11 s | | whisper.cpp (first run after boot) | 14.3 s | model load + Metal shader compile, once | | openai-whisper (Python) | 9.7 s — 2.3× real time | ~2 min | | Groq API | network round trip | needs GROQ_API_KEY |

Setup — whisper.cpp (recommended):

brew install whisper-cpp        # the whisper.cpp project's own CLI

That is the only step. On the next start the bot notices the binary, fetches the small model (466 MB) into `~/.alvin-bo