A Browser Per Claude Session
In an earlier post I wrote about giving Claude Code eyes with Playwright: running a real Chromium browser next to the agent so it could see a page, click through it, and fix what looked wrong. That solved the original problem, and it is still one of the most useful things I have added to how I build.
Then the way I work changed. I moved everything off my laptop and onto an always-on Linux server, the setup I described in building from my phone, and I started running several Claude Code sessions at once, one per project. The single browser that felt like magic with one session quietly became the bottleneck with many. This is how I fixed it: every session now gets its own browser, already logged in, that I can watch live and take over from my phone. If you want to build the same thing, there is a single file at the bottom you can hand to Claude.
Why one browser stopped working
Each Claude Code session spawns its own Playwright process. That part scales fine. The trouble was that they all shared one thing: a single browser profile on a single display. Chrome puts a lock on a profile directory so only one browser can use it at a time. So the moment a second session tried to open the browser, it collided with the first. In practice only one session could actually drive a browser at any given moment, and the single live view stacked every session’s windows on top of each other. I had parallel agents but a single-lane browser, and they fought over it.
What I wanted was simple to say: each session should get its own browser, on its own screen, that I can watch on its own, without any of them stepping on the others.
Lanes: a browser per session
The fix is a pool of what I call lanes. Think of a lane as a private booth for one browser: its own virtual display, its own browser profile, and its own live view. I run sixteen of them, which comfortably covers the number of sessions I tend to have going.
When a Claude Code session starts up and first reaches for the browser, it claims a free lane, uses it for the rest of its life, and releases it when the session ends. Because each lane has its own display and its own profile directory, the browsers never collide. Sixteen sessions can each be driving a browser at the same time, and each one is a separate window I can pull up on its own.
The moving parts are ordinary. Each browser launches with its own profile directory on its own virtual display, and a small launcher hands out the next free lane when a session asks for one. The two decisions that make it genuinely useful are what happens with authentication and with watching.
Every lane boots already logged in
A browser is far more useful to the agent when it is already signed in to the sites I actually use. Making the agent log in from scratch every session would be slow, fragile, and would mean typing my credentials into an automated browser over and over.
So I keep one master browser profile that I log into by hand, once, whenever a new site needs it. Each lane’s profile is a fresh copy of that master, made when the session claims the lane. Every session’s browser therefore boots already authenticated, without ever handling a password itself. The lane copies are disposable: I do my logins in the master, and the lanes inherit them. If a login expires, I refresh it in the master and the next session picks it up.
Watching, and taking over, from my phone
This is the part I did not expect to rely on as much as I do. Each lane’s browser is not headless. It renders to a real virtual screen, and each of those screens has its own live view I can open in a browser tab over my private network. So from my phone I can pull up exactly what any session’s browser is seeing, in real time, while the agent works.
Watching is useful on its own, but the payoff is taking over. When an agent hits something only a human should do, most often a login, I open that lane’s live view on my phone, sign in myself, and hand control straight back to the agent to carry on inside the now-authenticated session. I stay exactly where a human belongs, at the credentials, and the agent handles everything around it. Doing that for one session was handy. Being able to do it for any of sixteen, from the phone in my pocket, is what makes running this many agents at once actually workable.
Keeping the pool healthy
A pool of sixteen only works if lanes come back when a session is done with them. Most of the time that is automatic: a lane is released the instant its session exits, and a lane whose owner has died is treated as free by the next session that needs one. The one gap is a session that is alive but idle. On my server, tmux restores a Claude session in every window at boot, and those would claim and hold lanes without using them. So a small scheduled job reclaims any lane whose owner has gone away or sat idle for hours. It only ever frees the browser, never the session itself, and the session transparently claims a new lane the next time it needs one. And if every lane is genuinely busy, a new session does not block or collide. It falls back to a plain, unauthenticated browser of its own.
Build it yourself
None of the pieces are complicated on their own: a browser per session, a copy of a logged-in profile, a live view per screen, and a small launcher to hand the booths out and take them back. Rather than wall this post with shell scripts, I put the whole build into a single file. It has every script, the systemd unit, and the wiring, written as step-by-step instructions. Download it, drop it into a Claude Code session on your own Linux box, and it can stand this up for you. You fill in your own hostname and a VNC password where the file marks them.
It targets a native Linux host and assumes the single-browser Playwright setup from part one is already working. If you do not have that yet, start there.
Where this leaves me
Part one was about giving the agent a single pair of eyes. This is about giving a whole team of agents their own eyes at once, and keeping myself in the loop across all of them without drowning. Each project drives its own browser, each browser is already signed in, and any of them is one tap away on my phone when the agent needs a human for a moment.
Together these turn browser automation from something one agent does while I watch into something a dozen agents do in parallel while I glance in wherever I am needed.
If you build something like this, or you are trying to get parallel agents to share a browser without them fighting over it, I would like to compare notes. Use the contact form below or reach out on LinkedIn.