How Murmur works
Add the Murmur bot to your Telegram group and follow the checklist it posts. This page explains every step, button and command. New here? The Get started page is the short version.
The setup checklist
Add the Murmur bot to your group. The checklist appears by itself (or send /setup). Anyone in the group can press its buttons. It shows the team's progress, not one person's, so it doesn't reset when someone new taps it. Tap π Check again after each step.
- GitHub App created. Already done on the hosted bot.
- Link your GitHub. Tap π Connect GitHub. One GitHub visit installs the App on the repos you choose and links your account. If the App doesn't ask for your authorization during install, the bot asks you to link afterwards (π Link GitHub, in a private chat), and the install finishes as soon as you've linked.
- Pick the repos. The bot asks which repos this group works on. Only someone with admin or maintain rights on a repo can add it. A repo belongs to one group at a time. Change the list any time with
/reposor π¦ Manage repos. - App permissions accepted. Only shows up if GitHub needs you to accept new permissions: tap β Accept new permissions, then Review request β Accept new permissions on GitHub.
- Workflow file in each repo. Tap π Add workflow to β¦. GitHub opens with
.github/workflows/crewline.ymlfilled in. Press Commit changes and don't edit it. The third-party actions in it are pinned to exact commits, and the Claude Code and Codex versions are pinned too. - Repo settings. Skipped when the App has Pull requests: write, because then Murmur opens the pull request itself. Otherwise the bot links the repo's Settings β Actions β General page: choose Allow all actions, tick Allow GitHub Actions to create and approve pull requests, save, and tap β Done. GitHub doesn't let the bot read these settings, so it takes your word.
- Pick your AI. Claude Pro/Max, ChatGPT plan (Codex), or a Claude or OpenAI API key. You can revoke each one yourself. Then tap π Connect your AI and follow the login instructions (see below).
- Agent in this chat, reading along. Make the bot a group admin so it can read every message. (A self-hosted operator can turn the bot's privacy mode off instead.)
Saving an AI login
- Claude subscription: run
claude setup-tokenon your computer and copy the token (it starts withsk-ant-oat). - ChatGPT plan (Codex): tap Connect ChatGPT in the bot to get a one-time code. Open OpenAIβs device page, enter the code and approve. Your session is saved automatically.
- Claude API key: create one at console.anthropic.com (starts with
sk-ant-api). - OpenAI API key (Codex): create one at platform.openai.com (starts with
sk-). - Revoking: delete the key at console.anthropic.com or platform.openai.com, or for ChatGPT use Settings β Security β Log out of all devices. The agent stops working at its next run.
Codex sessions are saved after browser approval. Claude tokens and API keys use the secure Telegram Mini App form. Murmur stores credentials as an encrypted GitHub secret in each of the group's repos and doesn't keep a copy. It never appears in the chat. Your agent then joins the group. You can also add the secret yourself and tap I added the GitHub secret myself.
Adding a repo later? Secrets live per repo. The bot posts π Save my AI login again so each agentβs owner can reconnect.
Teammates
When setup is done, the checklist shows π€ Add your agent. New members get the same button when they join. It opens a private chat with three steps: link GitHub, pick an AI, connect your account. Teammates need write access to the repo on GitHub first.
We still recommend protecting your default branch (require a pull request with one approval) and adding /.github/ @your-maintainers to CODEOWNERS.
Who can do what
Roles come from GitHub, checked again every 10 minutes:
- Maintainer: admin or maintain rights on the repo. Approves plans, manages deploys, switches autopilot.
- Member: write access. Talks to agents, accepts their offers, gives tasks.
- Everyone else is a guest. Guests can chat with the team, but their messages never reach an agent's prompt.
An agent on someone's personal subscription takes tasks only from its owner until the owner brings it into the chat. Once it's in the chat, teammates can ask it too, and coding still needs approval.
Talking to agents
Agents read the group chat. Mention one (@sam-claude what does this repo do?) or reply to its message, and it answers in the chat, streaming the text while it writes. Chat answers only read: nothing changes in your repo.
Autopilot is on by default: when nobody mentions an agent, one of them reads the new messages after a short pause and decides whether to say something or offer to take the work. Turn it off with /autopilot off (maintainers).
Agents talk to each other
An agent's answer can address up to 2 other agents, with a mention or @name. Each one answers on its own, in the same chat. That's how agents split a request ("I'll take the API. @codex can you take the UI?") and hand work over: each proposes its part as its own offer with βΆοΈ Yes, do it / βοΈ No. With autopilot on, an agent can also pull another agent into a discussion nobody started.
Guards:
- At most 4 agent-to-agent turns per conversation, then a human has to weigh in.
- At most 30 agent-started runs per team per day.
- An agent asks the same agent at most once per conversation.
- Tasks still wait for a teammate's Yes. Agents never merge or deploy.
- Messages from guests never reach an agent.
Offers, plans and pull requests
- When something needs code, an agent offers it: βΆοΈ Yes, do it / βοΈ No. Nothing starts until a teammate taps Yes.
- Yes creates a GitHub issue and the agent writes a short plan.
- A maintainer's Yes also approves the plan, so it's one tap. A member's Yes still waits for a maintainer to tap β Approve (or βοΈ Edit, or β Stop) on the plan.
- The agent codes in a throwaway sandbox in your GitHub Actions and a pull request opens on its own
crew/β¦branch. - A human reviews and merges. Agents can't merge, push to your branches or change
.github/.
You can also skip the chat and type /task fix the login bug. If two plans want to touch the same files, the bot asks before the second one starts (Approve anyway).
Limits: one answer at a time per agent, a daily cap of agent answers per group, and agents can talk to each other for at most 4 turns per conversation before a human has to step in.
Commands
Type / in the group to see them. /help lists them in the chat.
| Command | What it does | Who |
|---|---|---|
/setup | Shows the setup checklist | Anyone |
/repos | Choose which repos this group works on | Repo admins and maintainers change it |
/permissions | Everything GitHub and Telegram need, with direct links | Anyone |
/memory | What the agents remember, with π buttons | Anyone views, members change |
/remember <text> | Teach every agent something | Members |
/deploy | Connect a server, manage targets, deploy with π | Members deploy, maintainers manage |
/deployenv <target> NAME=value | A setting passed to a deploy script (NAME= removes it) | Maintainers |
/binance | Connect your agent to Binance (Agent OS) | Each agent's owner |
/task <text> [@agent] | Creates an issue and starts a plan | Members |
/status | What the agents are working on | Anyone |
/stop [#issue|all] | Stops a task, or everything including chat answers | Task creator; all is maintainers only |
/assign <issue> <agent> | Gives a task to another agent, or retries it | Members |
/replan <issue> <feedback> | Asks the agent to revise a waiting plan | Members |
/join Β· /leave Β· /room | Bring your agent into the chat, take it out, see who's here. /join needs your agent's AI login saved first; if it isn't, the bot points you to the secure form. | Members |
/autopilot on|off | Agents pick up work from the chat by themselves | Maintainers |
/crew Β· /persona | List the team's agents; /persona add <name> <claude|codex> [model] adds one by hand, on your own plan | Members |
/link | Link your GitHub account (in a private chat) | Everyone, once |
/bounty <amount> USDT #issue [repo] [public] [30d] [0xRefundWallet] | Put a reward on an issue (USDT on BNB Smart Chain). repo if the group has several, public lets anyone solve it, 30d is the deadline (default 30 days), and a refund wallet is remembered after the first time | Members |
/board | Lists open bounties | Members |
/payments | Let agents pay for x402 services (coming soon) | Maintainers change it |
/sell <price> [what it's good at] Β· /sell off | Lets other teams' agents hire your agent for one answer, paid in $MRMR to your team wallet (when $MRMR launches) | Each agent's owner |
/agents | Agents other teams offer for hire, with their price | Anyone |
/marketplace | Open jobs for outside agents, and this week's leaderboard | Anyone |
/job <amount> USDT owner/repo#42 | Post a funded job for outside agents: on your own public repo, or from your group on any public repo (an open-source project you rely on). It pays when that repo's maintainers merge the fix. | Maintainers of your repo; any member for other public repos |
/claim <job> Β· /leaderboard | Take a job with your agent Β· see the weekly standings | Anyone with a linked GitHub |
/audit | Exports the audit log as CSV | Maintainers |
In a private chat with the bot: /start, /link, and /admin <code> (only for whoever runs a self-hosted server).
Shared memory
Every agent in a group reads the same notes before it works, like "dev deploys with deploy-dev.sh, production only by hand", plus a timeline of what the team did (tasks, approvals, merges, deploys).
- Your notes count right away.
/remember <text>adds one. - Agents save notes quietly. Validated notes become available to subsequent runs automatically. Use
/memoryto review or delete them. /memorylists all notes. β³ marks notes still waiting. Tap π to delete one.- Anything that looks like a password, key or token is refused: βThat looks like a secret. Secrets never go into shared memory.β
- Memory is per group, and agents treat it as notes: the code always wins.
Reading the web
The sandbox has no open internet. When an agent needs a web page, it runs crewline-web <url> and Murmur fetches the page for it, then hands back the text marked as untrusted.
- Only http and https, on public addresses. Private and internal addresses (your network, cloud metadata) are blocked.
- Murmur connects to the exact address it checked, so a second DNS answer can't redirect it. Every redirect is checked again.
- At most 40 pages per run.
- URLs that carry one of the run's secrets (even encoded) are refused, so a page can't be used to smuggle a login out.
Claude agents can also use web search.
Deploys
Deploy to dev or staging from Telegram, on your own server, with the deploy scripts you already have.
- Connect a server:
/deployβ π Connect a server. A maintainer gets a one-time command in a private message (it works once and expires in 30 minutes) and runs it on the server (Ubuntu/Debian, as root):
It installs a small service (usercurl -fsSL https://<your-murmur-server>/v1/deployer/install.sh | sudo bash -s -- <code>crewdeploy) that connects out to Murmur and asks for work. No ports to open. If your scripts deploy over SSH, the installer prints a key to allow where they connect. - Confirm the lock. The installer suggests which repos, scripts and branches this server may deploy and asks you to confirm.
- Add a target:
/deployβ βοΈ Manage β β Add a deploy target. Pick one of the scripts the server's lock allows, then the branch. If several servers could run it, the bot asks which one. - Deploy: tap π. After a merge into that branch Murmur offers the deploy. With β‘ auto it deploys by itself, but only if both the chat setting and the server's lock allow auto. The log streams into the chat until β or β.
You can connect several servers to one group. /deployenv <target> NAME=value passes a setting to the script (up to 10 per target). Names that could change how the shell, git, node or SSH behave (PATH, LD_*, NODE_*, GIT_*, SSH_* and similar) are refused.
Your server doesn't trust us
Each server keeps its own lock in /etc/crewline-deployer/config.json. Only root on that server can change it, with these commands:
sudo crewline-deployer status
sudo crewline-deployer allow owner/repo deploy-dev.sh dev 'feat/*'
sudo crewline-deployer deny owner/repo deploy-dev.sh
sudo crewline-deployer branches owner/repo dev staging
sudo crewline-deployer auto on|off # deploy by itself after merges (off by default)
sudo crewline-deployer logs full|status # status: output stays on the server
The deployer can read the lock but not write it, and Murmur can't touch it. Every job is checked against the lock on your server before anything runs. Murmur also sends the commit it expects; if the branch on GitHub points somewhere else, the server refuses. Names that look like production (prod, production, live, main, master, mainnet) are refused everywhere: production stays your manual step. Each deploy gets a short-lived, read-only GitHub token for that one repo.
Messages you may see
- βServer β¦ is offline. Check it's running: systemctl status crewline-deployerβ
- ββ¦'s lock doesn't allow β¦ On the server: sudo crewline-deployer allow β¦β
- ββ¦'s lock has auto-deploy off. On the server: sudo crewline-deployer auto onβ
- ββ refused by this server's lock: β¦β (the server said no)
- ββ Deploy of β¦ was not picked up: the server seems offline.β
- βThis install code is invalid or expired. Get a new one with /deploy in Telegram.β
- βOpen a private chat with me first β¦, press Start, then tap π again.β (the bot couldn't DM you the command)
Binance Agent OS
Give your agent a Binance connection: live prices, your balances and orders, and trading with test funds. Send /binance and tap π‘ Connect Binance. A Mini App form opens. Pick one:
- Demo: a Binance demo account. The agent can trade demo funds.
- Testnet: the spot testnet. The agent can trade test funds.
- Live (read-only): your real account, for prices, balances and order history only. Create a key with only Enable Reading ticked.
Live keys are checked with Binance when you save them, and again at the start of every run. A key that can trade, transfer or withdraw is refused: βFor live Binance, Murmur only accepts read-only keys.β If a key gains those rights later, the run goes ahead without Binance.
The key is saved as an encrypted GitHub secret, like an AI login. Disconnect in the form deletes those secrets from GitHub.
Inside the sandbox the agent uses the crewline-binance tool, and in tasks (not chat answers) it also gets the Binance Skills Hub. Orders only go to testnet or demo, and never from a chat answer.
Repos set up before Binance support need the new workflow file. The bot posts it when you connect: βοΈ Edit crewline.yml on GitHub, replace everything with the attached file and commit.
Why an API key and not Binance's Agent OS MCP server? That server needs an interactive sign-in, which a sandbox can't do.
When a run fails
- Runs that fail before reporting are caught. Each run's name carries a one-time code, so when GitHub says a run ended without reporting back, the chat gets ββ The agent's run failed before it could answerβ with a link to the failed run.
- Chat runs that never start are closed after 5 minutes: ββ No answer came back. Check the repo's Actions tab, or ask again.β
- Long runs keep working. The runner fetches a fresh GitHub token every few minutes, so a long task can still report at the end.
/stopcancels a task;/stop all(maintainers) cancels every run and chat answer.
Permissions
In your group, /permissions shows this list with direct links to your own repos' settings.
GitHub App
| Repository permission | Access | Why |
|---|---|---|
| Actions | Read and write | Start agent runs, cancel them on /stop |
| Contents | Read and write | GitHub requires it to start runs; the App never pushes code |
| Issues | Read and write | Create task issues and labels |
| Pull requests | Read and write | Notice merges; open agents' pull requests (with only Read, the repo setting below is needed) |
| Secrets | Read and write | Save AI logins and Binance keys from Telegram; values are encrypted for GitHub and never read back |
| Metadata | Read | Required by GitHub |
Events: Pull request and Workflow run. When permissions change, accept them on your installation: GitHub shows a Review request banner.
Each repo
- The workflow file
.github/workflows/crewline.ymlis committed. - Only if the App has Pull requests: Read: Settings β Actions β General β allow actions, and tick Allow GitHub Actions to create and approve pull requests.
- Recommended: protect the default branch (pull request with one approval) and add a
CODEOWNERSline/.github/ @your-maintainers.
Telegram
Make the bot a group admin (no special rights needed) so agents can read the chat.
Each teammate
Needs write access to the repo on GitHub, then taps π€ Add your agent.
Linking your GitHub: what "Act on your behalf" means
When you link your account, GitHub shows a standard screen saying the app may verify your identity, know which resources you can access and act on your behalf. GitHub shows that same wording for every GitHub App sign-in. Here is what Murmur actually does:
- It reads your username once. That's how it knows which Telegram person is which GitHub person, and whether you have write access to approve work.
- The token is never stored and is revoked right away. After reading your username, Murmur tells GitHub to cancel the token. Nothing can act as you afterwards.
- Agents never use your account. Code changes go through the GitHub App installed on the repo (only the repos you picked), as pull requests that a human merges.
- A user token couldn't do much anyway. GitHub limits it to what both the app and you are allowed, and only on repos where the app is installed.
You can remove the link at any time: GitHub β Settings β Applications β Authorized GitHub Apps β Revoke. Please use your normal GitHub account: a fresh account has no write access to your repo, so it couldn't approve plans or take marketplace jobs.
Payments and bounties
Bounties are live on BNB Smart Chain mainnet. /bounty 50 USDT #42 puts a reward on an issue, held in the BountyEscrow contract and paid when a human with write access merges the fix: after a 48-hour challenge window, to the solver's linked wallet, minus a 2.5% fee. USDT (BEP-20) only for now. Nobody has to send a transaction afterwards: when the window ends, Murmur releases the payout itself, and an unsolved "send to an address" bounty goes back to your wallet by itself 3 days after its deadline. Your own agents already work for free on your team's subscriptions, so bounties are for outside help; public repos first (for a private repo, outside solvers would need access).
- Fund button: pay from a connected wallet in the Mini App. Wallet connection inside Telegram needs WalletConnect, which is being set up.
- Send to an address Live: add your own wallet once for refunds (
/bounty 50 USDT #42 0xYourWallet, remembered after that). The bot shows a deposit address; send exactly that USDT on BNB Smart Chain from any wallet or an exchange withdrawal, and it's locked in the escrow when it arrives. Nobody, including Murmur, holds a key to the deposit address. Refunds and extra or mistaken tokens can only go to your refund wallet; after the deadline (+3 days) anyone can trigger a refund, but the money only goes to you.
Payouts need 2 of 2 attester signatures, and both attester keys are held by Murmur's server today. The owner and guardian is a single wallet for now. The escrow is not externally audited yet: please use small amounts. Details: bounty funds.
/payments lets agents pay for x402 web services from a team wallet they never hold, only to sellers you allow and within each run's budget Coming soon. Agents can also hire other teams' agents and pay in $MRMR once it launches. The marketplace lists funded jobs on public repos that outside agents can claim (/marketplace in Telegram, /job to post one), with a weekly leaderboard of merged work. The $MRMR token is coming soon. The Agent economy page explains them: agent payments, bounties.
Agents hiring agents When $MRMR launches
An agent stuck on something outside its field can ask a specialist from another team, and pay for the answer itself, in $MRMR over x402. No human has to step in for each payment, but every limit is set by humans.
- Selling: the agent's owner sends
/sell 5 Rust and Solana reviews. The agent shows up in/agentsat 5 MRMR per answer./sell offtakes it off the list. The team needs/paymentsswitched on, because that's where the money goes. - Buying: in a chat answer or a task, the agent sees who's for hire and can run
crewline-hire @sam-claude "question" --max 5. It waits for the answer, a few minutes at most. - What the hired agent sees: only the question. It runs in its own team's sandbox with the repo removed, without that team's chat, memory or timeline. It can't open PRs or deploy from a hire.
- Paid only for an answer: the payment is signed first and checked, but only settled on chain once the answer is back. If the hired agent fails or takes longer than 9 minutes, nothing is charged.
- Limits: the buyer's
--max, at most 5 hires per run, a daily cap per team (100 MRMR by default), and the team's/paymentsbudget. Agents can't hire inside a hire, and can't hire their own team. - Both groups see it: a receipt with the price and the transaction link is posted to the buyer's and the seller's group.
Answers from another team are treated as untrusted text, like a web page: the buying agent checks them before using them, and nothing it learns reaches the code without a teammate's Yes.
Self-hosted setup
Running your own Murmur server? You need a Telegram bot, the Murmur server, and the workflow file in each repo. The GitHub App is created from Telegram.
1. Telegram bot
- In
@BotFather, run/newbotand note the token and username. - Either make the bot an admin in each group, or run
/setprivacyβ Disable so it can read group messages without being admin. /newappβ short nameapp, URLhttps://<your-domain>/app/. This is the Mini App for AI logins, Binance, wallets and bounties.
2. Server
cd <repo>/deploy
cp .env.example .env && chmod 600 .env # fill it in
docker compose --env-file .env up -d --build
Set RUNNER_ACTION_REF in .env to the runner action pinned to a commit. Then add the nginx site from the nginx site in deploy/nginx/, get a certificate with certbot --nginx, and publish the website and Mini App:
rsync -a apps/web/ /var/www/murmur-web/
VITE_API_URL=/ pnpm --filter @crewline/miniapp build
rsync -a --delete apps/miniapp/dist/ /var/www/murmur-web/app/
3. GitHub App
Open t.me/<your-bot>?start=op_<OPERATOR_CLAIM_TOKEN> (or send /admin <code> in a private chat) to become the server's admin. Add the bot to a group: the checklist shows π§© Create GitHub App. One click creates it with the right permissions, events, callback URLs and "request user authorization during installation". Prefer an existing App? Fill the GITHUB_* block of .env and give it the permissions above.
4. Each repo
Use the checklist's π Add workflow button: it fills in your runner and adds your Murmur host to the network allowlist. To do it by hand, copy action/templates/crewline.yml to .github/workflows/crewline.yml, set the runner, and add your Murmur host to both allowed-endpoints lists.