I run an AI agent on a Mac mini at home — my whole team reaches it on Slack
Self-hosting an agent shouldn't be a weekend of daemons. One binary, one markdown file — and the whole team can reach it.
There are two questions people mash together when they talk about self-hosting an AI agent, and keeping them separate is the whole trick:
- Where does the agent live? On hardware you own, ideally. A Mac mini in the corner of the room. Your box, your keys, your data.
- Where do you reach it? Everywhere. Slack while you're in a meeting. Your phone on the train. A plain shell on your laptop when something needs fixing.
Most "self-hosted assistant" setups answer #1 and then make #2 a weekend project — a runtime, an always-on gateway daemon, channel plugins, QR pairing, a JSON config file, and an SSH tunnel for when you need to administer the thing. It works. It's also a lot of moving parts to keep alive just so a bot can answer a question in a channel.
I've been building rysh — an agentic terminal multiplexer where every pane can be a shell, an autonomous agent, or an external chat channel — and I wanted the "agent at home" story to be two artifacts, not a stack: one binary, and one markdown file. Here's the whole thing with real commands, and an honest list of what isn't done yet at the bottom.
Step 1 — Install: one binary, no daemon zoo
brew install rysh-ai/rysh/rysh
rysh
That's the install. rysh is a single self-contained binary — the message broker it uses for internal coordination (NATS) is embedded in the process, so there's no separate gateway daemon to install, keep alive, or restart. Run rysh, and the terminal itself is the platform: a TUI with tabs, panes, and a session that persists.
The one account step: register once at rysh.ai. That single sign-in is what later lets you reach this same session from another shell, share a pane to a teammate, or open it in the mobile app — one identity across your sessions and devices, instead of per-device pairing.
Step 2 — The agent is a markdown file
This is the part I care most about. An agent in rysh isn't a config object buried in a dashboard — it's a file you can read, diff, and check into git. Persona in the body, channels in the frontmatter, secrets as environment tokens that never touch the file:
---
name: support-bot
description: Support humanoid for the #support Slack channel
contacts:
slack:
enabled: true
bot_token: "${SLACK_BOT_TOKEN}"
app_token: "${SLACK_APP_TOKEN}"
reply_mode: mentions
channels:
- "#support"
---
You are support-bot, the support engineer for Northwind Devtools.
Answer only from the product facts below — they are your complete
knowledge base. If the answer isn't here, say you don't know and offer
to open a ticket. Be brief: 1–3 sentences, at most one short code block.
- Current release: nwcli v2.4.1. Install: brew install northwind/tap/nwcli
- Staging deploys are frozen every Friday after 16:00 UTC.
- Roll back with: nwcli rollback <release-id> (IDs from: nwcli releases)
An agent wired to external channels is what rysh calls a humanoid. Note the two things that are not in that file: no API keys (the ${SLACK_BOT_TOKEN} / ${SLACK_APP_TOKEN} tokens resolve from your environment at spawn time), and no plumbing. Spawn it and connect its channel:
##humanoid spawn support-bot
##humanoid channel start support-bot slack
##humanoid channels support-bot
# slack [connected]
connected. That's the agent live on Slack — sourced from a markdown file you could email to a colleague (minus the tokens).
Step 3 — Reach it where your team already talks
Now a teammate @-mentions the bot in #support — "staging deploy failed, why?" — and the answer lands in-thread, generated live from the skill file's facts. Nothing staged.
The important design decision here is that the agent is one thing and the channels are many. The same humanoid answers on Slack today, and email (IMAP/SMTP) and website chat run on the exact same engine — you add a contact block to the frontmatter, you don't re-implement the agent per surface.
And because "should a bot post to my customers on its own?" is a real question, governance is a per-channel switch:
##humanoid governance support-bot ai
# → autonomous on that channel: it answers directly, every action logged
##humanoid governance support-bot human
# → draft-and-confirm: the agent writes the reply as a DRAFT in the pane,
# and nothing goes out until a person types `send`
In human mode I've watched the flow end to end: a message comes in, the channel stays silent, a draft appears in my terminal, I read it, I type send, and exactly one reply posts. Same agent, same skill file — the only thing that changed is who has the last word. That's the difference between "we let a bot loose" and "we put an agent on a channel with a human approval gate," and it's one command. Draft-and-confirm is live for email and website chat today.
Step 4 — Reach it when you're away from the desk
The agent lives at home. You don't. Two ways rysh closes that gap.
From your phone. The rysh mobile app (currently in beta) attaches to your session and gives you a live, interactive view of a pane — real terminal, ANSI colors and all. You can watch what the agent is doing while you're nowhere near the Mac mini.
From any shell. This is the one I use most. A rysh session is manageable like infrastructure — you don't have to sit at the box:
# inject a command into the running session, headless, from any terminal:
rysh send home "##humanoid channels support-bot" --mode shell
# pick up the full live session — history intact — from another shell:
rysh attach home
# and once attached, govern it:
##humanoid channel stop support-bot slack
The session keeps running at home the whole time; send and attach just reach into it.
There's a third reach that DIY chat-bridges generally don't have: the agent's actual terminal is a shareable surface. ##share pane view prints a share ID and marks the pane [SHARED]; a teammate in their own rysh session runs ##upstream subscribe <id> view and watches that pane live (control mode is a separate, explicit decision). When you're done, ##unshare pane. It's pair-debugging for an agent, not an SSH tunnel to a dashboard.
Why this shape
I put the whole setup on a clock once, on camera, one take: 1:48 from brew install to the agent answering on Slack. Not because speed is the point, but because it's a proxy for how few moving parts there are.
The contrast with the popular DIY assistant stacks isn't about capability — those projects are genuinely impressive — it's about what you're signing up to operate: a runtime, a persistent gateway daemon, per-channel plugins with QR pairing and approval codes, a JSON config, and a tunnel for remote admin. That's roughly eight distinct things to keep alive before a real channel answers. And it has a cost you can measure: security researchers reported tens of thousands of those gateways exposed on the public internet earlier this year. When "self-host" means "run and expose a daemon," that's the failure mode waiting to happen.
rysh's bet is the opposite: own the box, govern the agent, reach it from everywhere — the agent's logic in a versioned file, its secrets in env tokens, its channels declared not plumbed, and its terminal shareable and manageable from any shell.
Honest scope — what's shipped, what's not
- Live channels are Slack, email, and website chat. WhatsApp and phone (via Twilio) are on the roadmap — same engine, same skill-file shape — but not live yet. Don't build a plan around them.
- Built on Claude. The provider layer is pluggable, but today the agent runtime uses Anthropic's Claude with your own key. No "better model" claim — this is about where the agent lives and who governs it.
- Self-hostable, not open source. You run rysh on your own hardware with your own key; no OSS license claimed.
- Mobile is beta. The live-pane view works; it's early.
- Observability caveat: for channels in
humanmode, the draft-and-approval flow is visible right in the pane. For a fully autonomous (ai) channel, the full back-and-forth doesn't yet stream into a pane view the way I want it to — a gap I'm closing, not a feature I'll pretend is done. - Private beta. rysh isn't a public signup yet.
If the "AI coworker on your own hardware, reachable from every channel, governed by a human" shape is something you'd actually use, that's exactly who I'm looking for — rysh is onboarding design partners. Happy to go deeper on any of the mechanics in the comments.
More in this series: governance ai|human: the draft-and-confirm switch · One SKILL.md, three channels