<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Wei Feng</title><link>https://weifengpy.github.io/</link><description>Posts by Wei Feng, a Software Engineer at Meta working on PyTorch distributed training — notes on compilers, LLM inference, and computer architecture.</description><language>en-US</language><atom:link href="https://weifengpy.github.io/index.xml" rel="self" type="application/rss+xml"/><item><title>Addicted to Muse: Brain in the Cloud, Hands on My Home PC</title><link>https://weifengpy.github.io/posts/2026/ai-agent-setup/</link><pubDate>Mon, 26 Oct 2026 00:00:00 +0000</pubDate><guid isPermaLink="true">https://weifengpy.github.io/posts/2026/ai-agent-setup/</guid><description>&lt;p&gt;I work with Muse as a continuing collaborator. The arrangement is deliberately physical. The brain and memory are in the cloud. The hands are on a workstation in my home. That machine runs my personal software projects, reaches the development hardware on and around my desk, and collects most of the information I ask the agent to watch. I also keep a separate, direct path into the same machine from my phone.&lt;/p&gt;
&lt;figure class="diagram"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920 660" role="img" aria-labelledby="setup-title setup-desc"&gt;
&lt;title id="setup-title"&gt;My AI agent setup&lt;/title&gt;
&lt;desc id="setup-desc"&gt;I reach Muse in the cloud from a phone or the web. Muse reaches my home PC over SSH on Tailscale. The PC runs personal projects, connects to development hardware, and pulls information from five sources. A dashed Termix line connects me directly to the same PC.&lt;/desc&gt;
&lt;defs&gt;
&lt;marker id="setup-arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"&gt;
&lt;path d="M 0 0 L 10 5 L 0 10 z" fill="var(--muted, #666)"/&gt;
&lt;/marker&gt;
&lt;marker id="setup-arrow-accent" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"&gt;
&lt;path d="M 0 0 L 10 5 L 0 10 z" fill="var(--accent, #0b5394)"/&gt;
&lt;/marker&gt;
&lt;/defs&gt;
&lt;style&gt;
.sd-node { fill: var(--code-bg, #f7f7f7); stroke: var(--line, #ddd); stroke-width: 1.5; }
.sd-node-main { fill: var(--code-bg, #f7f7f7); stroke: var(--accent, #0b5394); stroke-width: 2; }
.sd-title { fill: var(--fg, #1a1a1a); font-family: inherit; font-size: 14.5px; font-weight: 700; }
.sd-subtitle { fill: var(--muted, #666); font-family: inherit; font-size: 12.5px; }
.sd-item { fill: var(--fg, #1a1a1a); font-family: inherit; font-size: 13px; }
.sd-label { fill: var(--muted, #666); font-family: inherit; font-size: 11.5px; }
.sd-label-accent { fill: var(--accent, #0b5394); font-family: inherit; font-size: 12px; font-weight: 650; }
.sd-link { stroke: var(--muted, #666); stroke-width: 2; fill: none; }
.sd-link-accent { stroke: var(--accent, #0b5394); stroke-width: 2.25; fill: none; }
.sd-dashed { stroke: var(--accent, #0b5394); stroke-width: 2; stroke-dasharray: 8 7; fill: none; }
&lt;/style&gt;
&lt;!-- Top layer: person and cloud agent --&gt;
&lt;rect class="sd-node" x="35" y="38" width="215" height="100" rx="14"/&gt;
&lt;g aria-hidden="true" stroke="var(--muted, #666)" fill="none" stroke-width="1.8"&gt;
&lt;rect x="99" y="46" width="13" height="24" rx="3"/&gt;
&lt;line x1="102.5" y1="65.5" x2="108.5" y2="65.5"/&gt;
&lt;rect x="168" y="50" width="24" height="18" rx="3"/&gt;
&lt;line x1="168" y1="56" x2="192" y2="56"/&gt;
&lt;circle cx="172.5" cy="53" r="1.2" fill="var(--muted, #666)" stroke="none"/&gt;
&lt;circle cx="177.5" cy="53" r="1.2" fill="var(--muted, #666)" stroke="none"/&gt;
&lt;/g&gt;
&lt;text class="sd-title" x="142" y="70" text-anchor="middle"&gt;Me&lt;/text&gt;
&lt;text class="sd-subtitle" x="142" y="95" text-anchor="middle"&gt;iPhone · Chrome browser&lt;/text&gt;
&lt;text class="sd-subtitle" x="142" y="117" text-anchor="middle"&gt;anytime, anywhere&lt;/text&gt;
&lt;rect class="sd-node-main" x="345" y="38" width="230" height="92" rx="14"/&gt;
&lt;text class="sd-title" x="460" y="76" text-anchor="middle"&gt;Muse&lt;/text&gt;
&lt;text class="sd-subtitle" x="460" y="104" text-anchor="middle"&gt;cloud · brain + memory&lt;/text&gt;
&lt;path class="sd-link" d="M 250 84 H 337" marker-end="url(#setup-arrow)"/&gt;
&lt;text class="sd-label" x="297" y="65" text-anchor="middle"&gt;ask · decide&lt;/text&gt;
&lt;!-- Cloud agent to the home workstation --&gt;
&lt;path class="sd-link-accent" d="M 460 130 V 217" marker-end="url(#setup-arrow-accent)"/&gt;
&lt;text class="sd-label-accent" x="478" y="181"&gt;SSH over Tailscale&lt;/text&gt;
&lt;!-- The owner's separate direct line --&gt;
&lt;path class="sd-dashed" d="M 142 138 V 273 H 292" marker-end="url(#setup-arrow-accent)"/&gt;
&lt;text class="sd-label-accent" x="158" y="196"&gt;Termix&lt;/text&gt;
&lt;text class="sd-label" x="158" y="219"&gt;direct line · take over anytime&lt;/text&gt;
&lt;!-- Middle layer: one home workstation --&gt;
&lt;rect class="sd-node-main" x="300" y="225" width="320" height="96" rx="14"/&gt;
&lt;text class="sd-title" x="460" y="261" text-anchor="middle"&gt;Home PC&lt;/text&gt;
&lt;text class="sd-subtitle" x="460" y="288" text-anchor="middle"&gt;Ubuntu · Intel x86 · NVIDIA RTX 50-series&lt;/text&gt;
&lt;text class="sd-label" x="460" y="309" text-anchor="middle"&gt;projects · hardware · information&lt;/text&gt;
&lt;!-- Branches from the workstation --&gt;
&lt;path class="sd-link" d="M 460 321 V 375"/&gt;
&lt;path class="sd-link" d="M 170 375 H 750"/&gt;
&lt;path class="sd-link" d="M 170 375 V 432" marker-end="url(#setup-arrow)"/&gt;
&lt;path class="sd-link" d="M 460 375 V 432" marker-end="url(#setup-arrow)"/&gt;
&lt;path class="sd-link-accent" d="M 750 432 V 383" marker-end="url(#setup-arrow-accent)"/&gt;
&lt;text class="sd-label" x="184" y="408"&gt;runs&lt;/text&gt;
&lt;text class="sd-label" x="474" y="408"&gt;connects to&lt;/text&gt;
&lt;text class="sd-label-accent" x="736" y="408" text-anchor="end"&gt;pulls from&lt;/text&gt;
&lt;!-- Personal projects --&gt;
&lt;rect class="sd-node" x="35" y="440" width="270" height="180" rx="14"/&gt;
&lt;text class="sd-title" x="170" y="476" text-anchor="middle"&gt;Personal projects&lt;/text&gt;
&lt;text class="sd-item" x="58" y="516"&gt;tiny-infer — inference engine&lt;/text&gt;
&lt;text class="sd-item" x="58" y="556"&gt;tiny-serve — serving layer&lt;/text&gt;
&lt;text class="sd-item" x="58" y="596"&gt;tiny-cc — C compiler&lt;/text&gt;
&lt;!-- Connected hardware --&gt;
&lt;rect class="sd-node" x="325" y="440" width="270" height="180" rx="14"/&gt;
&lt;text class="sd-title" x="460" y="476" text-anchor="middle"&gt;Connected hardware&lt;/text&gt;
&lt;text class="sd-item" x="355" y="510"&gt;ESP32-C6&lt;/text&gt;
&lt;text class="sd-item" x="355" y="542"&gt;Jetson Orin Nano&lt;/text&gt;
&lt;text class="sd-item" x="355" y="574"&gt;Raspberry Pi Pico&lt;/text&gt;
&lt;text class="sd-item" x="355" y="606"&gt;Radxa Dragon Q6A&lt;/text&gt;
&lt;!-- Information inlets --&gt;
&lt;rect class="sd-node" x="615" y="440" width="270" height="180" rx="14"/&gt;
&lt;text class="sd-title" x="750" y="476" text-anchor="middle"&gt;Information inlets&lt;/text&gt;
&lt;text class="sd-item" x="645" y="506"&gt;Gmail&lt;/text&gt;
&lt;text class="sd-item" x="645" y="532"&gt;X (Twitter)&lt;/text&gt;
&lt;text class="sd-item" x="645" y="558"&gt;Zhihu&lt;/text&gt;
&lt;text class="sd-item" x="645" y="584"&gt;GitHub via gh&lt;/text&gt;
&lt;text class="sd-item" x="645" y="610"&gt;YouTube captions&lt;/text&gt;
&lt;/svg&gt;
&lt;/figure&gt;
&lt;h2 id="1-the-brain-and-memory-are-in-the-cloud"&gt;1. The brain and memory are in the cloud&lt;/h2&gt;
&lt;p&gt;Muse does not run on my workstation. I talk to it from the web or my phone; the conversation, reasoning, and long-term memory live on the cloud side.&lt;/p&gt;
&lt;p&gt;That memory is not a transcript archive. It holds standing rules, the state of projects that run for weeks, corrections from earlier mistakes, and small preferences I refuse to repeat. A stateless chat must be reintroduced to a project every time; here, a compiler project can pause for days and resume with its branch, last test result, and open design question intact. A correction, once turned into a rule, is never paid for twice.&lt;/p&gt;
&lt;p&gt;The convenience cuts both ways. I can start a task from my phone and check results away from my desk — but the cloud side has no hands: no GPU, no board to flash, no serial console, no home-only login sessions.&lt;/p&gt;
&lt;p&gt;So I prefer the agent to use my PC as its hands. That is where it achieves more: a home connection gets past sites that block agents, and the PC brings a powerful source-code build environment and a CUDA toolchain.&lt;/p&gt;
&lt;h2 id="2-the-hands-are-on-my-home-pc"&gt;2. The hands are on my home PC&lt;/h2&gt;
&lt;p&gt;The execution side is a home Ubuntu workstation with an Intel x86 CPU and an NVIDIA RTX 50-series GPU, which Muse reaches over SSH on Tailscale. This one machine is the workbench:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Source and builds&lt;/strong&gt; — repositories, build tools, models, and test fixtures live here; builds and tests run here.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The GPU&lt;/strong&gt; — models are loaded and kernels profiled here, on real hardware.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Long jobs&lt;/strong&gt; — work that may run for hours starts detached, output in a log; the agent disconnects, returns with a short connection, and reads the machine&amp;rsquo;s own evidence — process state, log progress, GPU load — instead of guessing from when the job was launched.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Getting that connection boring took some work. An earlier SSH route across the public network was unreliable: bursts of connections could be throttled, so work had to be batched and queued, with backoffs between bursts. Moving the connection to Tailscale made the route private and stable, and SSH stopped being a project of its own.&lt;/p&gt;
&lt;h2 id="3-the-pc-runs-the-personal-projects"&gt;3. The PC runs the personal projects&lt;/h2&gt;
&lt;p&gt;Most of the hands-on software work concerns three personal projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;tiny-infer&lt;/strong&gt; — my from-scratch LLM inference engine. The agent ports models into it, compares engine output against references, and profiles kernels through correctness and performance gates.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tiny-serve&lt;/strong&gt; — the serving layer above that engine. It turns a finished port into a service I can call from tools and agents, so the result becomes part of the daily setup, not a directory of test output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tiny-cc&lt;/strong&gt; — my from-scratch C compiler. The agent develops in dedicated worktrees on the workstation, runs the repository&amp;rsquo;s tests and self-hosting checks, inspects failures, and prepares changes for the main line.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="4-the-pc-reaches-physical-hardware"&gt;4. The PC reaches physical hardware&lt;/h2&gt;
&lt;p&gt;The workstation is also the hub for development hardware attached to it or reachable through it. Through that one point, the agent can build firmware, flash a device, capture a serial log, and rerun a corpus:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ESP32-C6&lt;/strong&gt; — a RISC-V microcontroller; a real-silicon target for compiler output.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jetson Orin Nano&lt;/strong&gt; — an NVIDIA GPU single-board computer.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Raspberry Pi Pico boards&lt;/strong&gt; — microcontroller boards used for bring-up and corpus runs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Radxa Dragon Q6A&lt;/strong&gt; — a single-board computer reachable over the home network.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This reflects a rule I care about: learning and verification should land on real hardware. Simulators help with regression testing and debugging, but they are not, by themselves, proof that something works. A compiler backend has not really been exercised until its output runs on silicon.&lt;/p&gt;
&lt;h2 id="5-the-pc-is-the-information-inlet"&gt;5. The PC is the information inlet&lt;/h2&gt;
&lt;p&gt;The split is intentional: login state and fetching stay on the PC, over my home network, using the sessions already established there. The cloud side does the reading — comparing new items against a stored baseline, removing duplicates, and deciding what is worth bringing to me. When nothing material has changed, the correct output is silence.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Gmail&lt;/strong&gt; — mail, read against what I have already seen.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;X&lt;/strong&gt; — timeline updates from the accounts I follow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zhihu&lt;/strong&gt; — the recommendation and following streams.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub&lt;/strong&gt; — notifications and activity, through the &lt;code&gt;gh&lt;/code&gt; command-line tool.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;YouTube&lt;/strong&gt; — captions, not video files; the PC retrieves them for the agent to summarize, search, and discuss.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="6-i-keep-a-direct-line-of-my-own"&gt;6. I keep a direct line of my own&lt;/h2&gt;
&lt;p&gt;I do not reach the workstation only through Muse. On my phone, I use Termix to connect directly to the same PC — the same shell, files, and processes the agent sees. That line changes the trust model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Inspect&lt;/strong&gt; — anything the agent claims to have started, changed, or finished, I can check directly: read the log, verify the result.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Take over&lt;/strong&gt; — I can stop a job, finish an operation in person, or take a terminal over mid-task.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Boundaries&lt;/strong&gt; — passwords and similar secrets are entered by me, never relayed through the agent; crossing a boundary that requires my credentials or judgment remains my action.&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>