Earlier this year I wrote about running Clawdbot on AWS EC2 and then about putting two Moltbot agents in one Telegram group. Those were experiments. This post is about the setup that stuck: Hermes Agent, the open-source agent from Nous Research, which went from a fresh install on a cloud server to running most of my working week from a Steam Deck that had spent most of the past year in a drawer.
It is a build log, not a tutorial. I will cover how the setup grew, why it ended up on a handheld gaming PC, what broke during the move, and what runs on it today. The numbers come from the agent's own session database and config, not from memory.
Where it started: a cloud box and a Telegram chat
Hermes started on the same kind of machine my earlier experiments used: a small Ubuntu instance on EC2. The appeal was the same as before. An agent on a server never sleeps, and I can talk to it from my phone through Telegram.
What made Hermes different from the earlier bots was how much of it is designed to accumulate. Within a few weeks the setup grew four layers, roughly in this order.
1. One chat, then a gateway. Hermes runs a gateway process that connects the agent to messaging platforms. I started with a single Telegram DM. Later I added two Discord bots for team channels, each running as its own Hermes profile with separate skills, credentials, and access rules. A profile is effectively a separate agent sharing one install.
2. Skills instead of repeated instructions. Every time I explained a procedure twice, it became a skill: a Markdown file the agent loads when a task matches. How I deploy, how I review a delegated pull request, how I triage an inbox, how I publish a post on this site. There are 96 skill files on the box today. Most of them are not clever. They are the boring checklists that stop the agent from repeating a mistake it already made once.
3. Scheduled jobs. Hermes has a built-in cron scheduler, and this is where it stopped being a chatbot and started being an assistant. Today there are 19 scheduled jobs on the main profile. A few examples that are about my own work, not clients:
- A job scout that checks freelance job boards every two hours during the day, filters out anything I have already seen or bid on, and sends me a short list.
- A LinkedIn pipeline that drafts the next day's post, sends me a preview at 8 PM, and publishes at 8:30 the next morning unless I object.
- A weekly report for this site that pulls Google Analytics, Search Console, and Bing Webmaster data and tells me what moved.
4. Long-term memory. By default an agent forgets everything between conversations. I added a memory provider (Hindsight, running locally) that extracts facts from every session and recalls the relevant ones into the next. After importing my full history it held about 4,900 memories. It is the reason I can say "carry on with the site" and get an answer that knows which pull request is open.
Delegating code to Claude Code
The fifth layer is the one I use most. Hermes is not my coding tool. When a task means changing a repository, it writes a brief to a file, hands it to Claude Code in one-shot mode (claude -p), and waits. Claude Code works on its own branch, runs the checks, and opens a pull request. Then Hermes re-runs every check itself before telling me anything, because a coding agent's summary is a self-report.
I wrote about that workflow from the Claude Code side in my Laravel development workflow post. The short version: one agent plans and verifies, another writes code, and I review pull requests instead of typing.
Why move an always-on agent to a Steam Deck
The honest answer is money. Once the agent was doing real work every day, the EC2 instance became a monthly bill for a machine that mostly waited for messages. An always-on agent does not need a data centre. It needs a computer that stays on.
I had one. I bought my Steam Deck over a year ago, played it seriously for a few months, and then it sat unused. Moving the agent onto it turned a recurring cost into hardware I had already paid for, and gave the Deck a job again.
The move also brought things a cloud box could not offer. A server in a data centre cannot hear me, cannot speak, and cannot reach anything on my home network, like the TV or the printer. On the Deck, those came almost for free.
Under the plastic, a Steam Deck is a small Linux PC:
- 14.8 GB of usable RAM, plenty for an agent, its tools, and a few containers.
- A 1 TB SSD in mine, with over 400 GB still free after moving everything across.
- A built-in microphone and speakers, which turned out to matter more than I expected.
- A battery, which works as a small UPS when the power flickers.
- SteamOS, which is Arch Linux with a KDE desktop underneath the game launcher.
The agent talks to Telegram and Discord through outbound connections only, so the home network needs no open ports. The one inbound thing, the Hermes web dashboard, goes through a Cloudflare Tunnel behind Cloudflare Access, the same as it did on EC2.
The move, in two days
The migration took two days. Hermes has a built-in hermes backup and hermes import pair, and that part was easy. The backup was about 4 GB and carried settings, keys, memory, skills, past sessions, scheduled jobs, plugins, and the other profiles.
What it does not carry is everything outside Hermes: project folders, SSH keys, GitHub logins, the AWS CLI profiles, and the Claude Code login. Those I copied separately, and Claude Code I simply signed into again on the Deck rather than moving an old session token across.
Then things broke. None of them were exotic, and all of them were fixable in a few minutes once found. They are worth listing, because each one fails quietly.
Every scheduled job would have run 8 hours late
The EC2 clock was UTC. The Deck runs on Manila time, UTC+8. All 16 cron schedules I had at the time were stored as UTC expressions, so after the move every job would have fired 8 hours off: posts going out in the evening, the job scout running overnight. Nothing would have errored. Hermes rewrote all 16 schedules in local time with hermes cron edit, after backing up the job files.
Hardcoded home directories
The cloud user was ubuntu. The Deck user is deck. Every script and prompt that contained /home/ubuntu failed on first run: the LinkedIn tooling alone had 7 scripts and 6 prompt files with the old path. A search-and-replace with backups fixed it, along with a few Python modules that existed on the server but not on the Deck.
Background services do not read your shell profile
claude and my other CLIs live in ~/.local/bin. My shell knows that. A systemd user service does not, so the dashboard reported Claude as "not authenticated" while every terminal test passed. The fix is an explicit PATH in the service unit, and the lesson is to test from the service environment, not from your terminal.
No Docker, so Podman
SteamOS does not ship Docker, and its system partition is read-only: anything installed with pacman is wiped by the next OS update. So everything for the agent lives under /home/deck, and the one connector that ran as a Docker container now runs under rootless Podman. Containers that should survive a reboot need Podman's always restart policy. I learned that one the slow way, when unless-stopped containers stayed down after the Deck restarted.
Two gateways, one bot token
During the switch-over, the cloud gateway had to be stopped before the Deck's gateway started. Two gateways using the same Telegram bot token compete for incoming messages, and each one gets roughly half your conversation.
A gaming device wants to sleep
A Steam Deck is built to suspend the moment you put it down. For an always-on agent that is the main risk, so the setup now:
- runs the gateway as a systemd user service with lingering enabled, so it starts at boot without anyone logging in, in Game Mode or Desktop Mode;
- runs a small service that blocks sleep, and sets the plugged-in sleep timer to Never;
- turns off Wi-Fi power saving;
- remaps the power button, because a short press used to suspend the Deck and a stray double event made the screen flicker.
It also stays on the charger permanently. If you do the same, set the battery charge limit in SteamOS to 80%; sitting at 100% all day wears the battery faster.
What runs on the Deck today
As of this week the Deck runs:
- The Hermes gateway with three profiles: my main assistant on Telegram and two Discord bots.
- 19 scheduled jobs on the main profile, from the job scout to this site's weekly analytics report.
- The web dashboard, reachable only through Cloudflare Access.
- Hindsight, the local long-term memory, with its own small web view behind the same login.
- A "Hey Jarvis" voice listener using the Deck's own microphone and speakers. It answers questions out loud, and anything that would change something gets sent to Telegram for my approval first. It goes quiet from 11 PM to 7 AM.
- Home helpers for the TV and the printer, which simply were not possible from a cloud server.
- Claude Code and the Codex CLI, which Hermes hands coding work to.
The session database holds 365 sessions and about 17,600 messages so far. Most of those sessions were never typed by me: 214 of them are scheduled jobs that ran on their own.
What I would tell someone doing the same
Keep everything in your home directory. On SteamOS this is not a preference. The read-only system partition is the price of reliable OS updates, and it is a good trade.
Back up before you change anything. Every risky change in this story has a dated backup next to it. Most of the time nobody needs it.
Treat migration as a checklist of quiet failures. Clock, paths, PATH, container restart policy, duplicate gateways, sleep. None of them throw an error you will see. Check each one deliberately.
Let the agent verify the agent. The most useful habit in the whole setup is that nothing is reported as done until a second check passes: Hermes re-runs Claude Code's tests, curls the live page after a deploy, and reads the data rather than trusting a summary.
Keep a fallback. The model runs on my Claude subscription, with a second provider configured as an automatic fallback for rate limits and outages. The old EC2 instance is switched off but not deleted. It stays that way for a few weeks while the Deck proves it can carry everything, and then it goes.
The cloud server was the right place to start. It is easy to rebuild and it never sleeps. But once the agent became part of my daily work, paying every month for a server made less sense than using a capable little computer I already owned and had stopped using. The Deck has a purpose again, the bill is gone, and the agent gained a microphone, a speaker, and a view of the rest of my home network along the way.

Written by
Richard Joseph Porter
Senior Laravel Developer with 14+ years of experience building scalable web applications. Specializing in PHP, Laravel, Vue.js, and AWS cloud infrastructure. Based in Cebu, Philippines, I help businesses modernize legacy systems and build high-performance APIs.
Get in touchWant to optimize your AWS costs?
I help companies reduce AWS spending by 30-50% while improving performance. Get a detailed cost analysis.
Related articles
8 min read
Jev and Claude Code: Typed AI Decisions in the Agent Loop
TypeSafe AI's Jev returns typed, calibrated decisions instead of generated text. Here's who Jev is for, and how it fits into agentic coding with Claude Code.
- ai-development
- claude-code
- developer-tools
10 min read
Claude Code Remote Control: The Untethered Developer
How Claude Code Remote Control lets you continue local coding sessions from your phone, tablet, or any browser. Setup guide with real workflow scenarios.
- claude-code
- ai-development
- developer-tools
7 min read
Superpowers Plugin for Claude Code: How I Ship Big Features with Confidence
How the Superpowers plugin transforms Claude Code into a disciplined senior developer for large feature work. Brainstorming, planning, TDD, and subagent-driven execution.
- claude-code
- ai
- developer-tools