Repository navigation
Releases: nxfi777/tallylamp
Release list
Tallylamp 0.11.6 — OAuth logins survive parallel clients
Tallylamp 0.11.6
OAuth connectors now stay signed in when a client runs several processes off
one saved login. Before this release, two of those processes refreshing around
the same time looked like a stolen token, and Tallylamp disconnected every
process using that login until someone approved it again.
What changes
- A client that presents the refresh token rotated just before the live one
gets that same successor back, with a fresh access token. This happens
without any theft when several processes share one saved login and another
one refreshes first. Codex does this when its desktop threads each run their
own process. It also happens when a refresh response never reaches the
client's store. - A successor refresh token is now derived from the token it replaces, using a
key based onADMIN_SECRET, so the same token always has the same successor.
Every other check still applies. The token must be unexpired and belong to
the same client, the successor must be live in the same grant, and the
connector must be enabled. - Presenting a token two or more rotations old, or replaying an authorization
code, still revokes the whole grant. The tradeoff: someone holding the most
recently rotated token can keep pace with the real client until one of them
falls two refreshes behind. WithoutADMIN_SECRET, rotation stays strict. - The audit log records a tolerated catch-up as
oauth.refresh_reuse_tolerated.
A replay that revokes a grant is recorded once asoauth.refresh_reuse, not
again for every retry against the dead grant.
Upgrading
No new dependencies, database changes, or settings. Upgrade the main instance
and every worker together: while they run different releases, the main instance
starts nothing on a worker. Redeploys restart running browsers; their profiles
remain on the persistent volume.
Connectors approved before this release keep working, and every rotation 0.11.6
makes supports catching up, including the first one after the upgrade. The one
gap is the last rotation made before the upgrade: its successor was drawn at
random, so a client still holding the token that rotation replaced is signed out
once. Rotating ADMIN_SECRET still revokes every OAuth grant.
Tallylamp Link is unchanged apart from its version number.
Release validation
The release workflow
passed application, headed Chrome, and running-container checks before
publishing the tested image. Its anonymous registry access, digest, version and
source-revision labels were verified, along with the extension zip's manifest
version. Pin this Linux amd64 artifact:
ghcr.io/nxfi777/tallylamp@sha256:33557d1796c3ba09b3482827245a1203e2e9e45e172f49f86d07c7dd0441f179
After deploying that artifact, the production instance and its worker both
reported 0.11.6. A Claude Code connector refreshed its token through the new
code, its next MCP call succeeded, and the audit log recorded no refresh-token
reuse. The release's tests cover a client one refresh behind; production only
exercises that path when a client actually falls behind.
See the Railway upgrade instructions for
backups and deployment settings.
Tallylamp 0.11.5 — extension debugging, export and import
Tallylamp 0.11.5
Agents can now debug Chrome extensions in Tallylamp's own browsers. This
release also adds instance export and import, lets Tallylamp Link recover from
network interruptions on its own, and makes the dashboard, API and Full browser
respond faster.
Debug extensions with an agent
- A browser with the Extensions switch on starts its Chrome DevTools MCP
bridge with the extension tools.list_pageslists extension service workers,
evaluate_scriptwithserviceWorkerIdruns code inside one,
list_console_messagesincludes content-script messages, andnavigate_page
opens an extension's ownchrome-extension://pages. list_extensionslists unpacked extensions.trigger_extension_action
presses an extension's toolbar button on the selected page.
install_extensionloads an unpacked folder from the Tallylamp host's disk,
andreload_extensionanduninstall_extensionmanage it afterwards.- Only the browser's owner can install, reload or uninstall. A grant never
permits those, at either access level, because an installed extension keeps
running after the loan ends. Acontrolgrant can trigger an action and run
code in a service worker, with that extension's permissions. Areadgrant
can list extensions. - Linked browsers never get these tools. Calls are refused with a reason on a
linked browser, on a browser with extensions off, and forinstall_extension
on a browser that runs on a worker.
Export and import
node bin/tallylamp.mjs export saves the instance's stored data as one
.tar.gz archive, for a backup or to move selected browsers, saved profiles
and downloads to another machine. Export stops the browsers it includes and
leaves them stopped, so Chrome cannot write to a profile while it is read.
Import checks the archive offline and restores it into a new data directory.
The archive holds browser logins, proxy credentials and agent token hashes, so
protect it like the data volume. See export and import.
Tallylamp Link
The extension retries a dropped connection or DNS failure by itself. Shared
tabs stay shared while it reconnects, and the agent can use them again once the
panel says Connected. If the server stays unreachable for a minute, the tabs
are handed back, even when Chrome restarts the extension's background worker.
Dashboard and speed
- Navigation fits narrow screens, pages show loading and error states reliably,
forms show when they are saving, and tabs work from the keyboard. Each browser
shows who holds control. - The OAuth consent page has Select all.
- Refreshes and screen captures no longer pile up, compiled SQLite queries are
reused, and profile file work runs off the main event loop. Full browser input
has no added delays, capture pauses while the view is hidden, and the control
stream responds faster at the same image quality.
Upgrading
No database changes and no new settings. Source installs gain one npm
dependency, tar, for export and import. Upgrade the main instance and every
worker together: while they run different releases, the main instance starts
nothing on a worker. Redeploys restart running browsers; their profiles remain
on the persistent volume.
Existing Tallylamp Link installs keep working with this server. Load this
release's tallylamp-link.zip to get the reconnect behaviour.
Release validation
The release workflow
passed application, headed Chrome, and running-container checks before
publishing the tested image. Its anonymous registry access, digest, version and
source-revision labels were verified, along with the extension zip's manifest
version. Pin this Linux amd64 artifact:
ghcr.io/nxfi777/tallylamp@sha256:77c612265f08ee24b20471dc0bb63c98069491b393eb04826becce0820029667
After deploying that artifact, a live test drove the new tools through the
production instance's own /mcp, with a temporary agent and browser on headed
Chrome under Xvfb. install_extension loaded an unpacked test extension,
list_pages listed its service worker, and evaluate_script ran code inside
it. Its content script logged on example.com, its options page opened and took
a snapshot, trigger_extension_action fired its toolbar action, and
uninstall_extension removed it. The temporary browser was deleted and the test
agent disabled, which revokes its credential.
See the Railway upgrade instructions for
backups and deployment settings.
Tallylamp 0.11.4 — linked-browser worker offloading
Tallylamp 0.11.4
Linked-browser control connections now use available workers automatically.
Chrome stays on its owner's machine; the MCP bridge process and its threads
run on the worker. This frees capacity on the main instance while retaining
the per-browser routing introduced in 0.11.3.
What changes
- Each linked browser connection has its own bridge, preserving independent
page selection across MCP sessions. - New bridges prefer a healthy, compatible worker with sufficient thread
capacity. They fall back to the main instance when needed.
TALLYLAMP_PLACEMENT=localkeeps all bridges local. Existing connections
keep their placement until they are closed or recreated. - Access checks, human takeover, and the extension connection remain on the
main instance. Each worker channel can reach only its assigned linked
browser's debugging endpoint. - A lost worker closes its bridge without disconnecting the user's browser
or unsharing tabs. A later call can reconnect on another host; an interrupted
command is never automatically replayed. - Saved screenshots, snapshots, traces, script results, heap snapshots, and
Lighthouse reports are copied back to the main instance before their paths
are returned. Session shutdown removes the worker's temporary artifacts.
Upgrading
No new dependencies, database changes, or settings. Upgrade the main instance
and workers to the same release. Redeploys restart running browser processes;
profiles remain on their persistent volumes. Existing Tallylamp Link
extensions remain compatible; this release's extension package carries the
matching version.
See worker placement and recovery for
operational details.
Release validation
- All 423 unit and integration tests pass, alongside headed Chrome and desktop CI checks: PR validation.
- The published image passed headed Chrome and running-container checks: release workflow.
- Source revision:
e6e547a1eb22b4e64b0606d43413618db3d35da3. - Verified public Linux/amd64 image:
ghcr.io/nxfi777/tallylamp@sha256:7a1b02421050eb720328018abf22a7586c4e915502024b04e2a42b94bf27f52c.
Tallylamp 0.11.3 — independent browsers on one MCP connection
Tallylamp 0.11.3
Agents sharing one MCP connection can now work in different browsers at the
same time. Each browser tool call can name its target with browserId.
Previously, a connection had one active browser. If one agent selected browser
B while another was working in browser A, the other agent's next call could
land in B. An explicit ID now keeps that call on its intended browser without
changing the connection's default.
What changes
- Route each call. Driving tools, page selection, and recording start/stop
accept an optionalbrowserId. Calls to different browsers use independent
connections to Chrome and can run concurrently. Each agent should keep its
browser ID and pass it on every browser operation. Agents sharing the same
browser in one MCP session still share its selected tab. - Keep existing clients working.
tallylamp_create_browserand
tallylamp_use_browserstill set the shared default. Calls without an ID use
that default. Separate MCP sessions retain independent defaults even when
they use the same credentials. - Keep tools discoverable. The advertised tool list stays stable when the
default browser is read-only. A shared connection may also operate an owned
browser, so selecting a read-only browser no longer hides its driving tools.
Every call is checked against the permissions for its target. - Reconnect to the intended browser. Once credentials have been used with
multiple browsers, a new session asks for an explicit ID or browser selection
instead of guessing which browser to restore. Connections to different
browsers are tracked and cleaned up independently. - Check the named browser. Ownership, grants, and human takeover apply to
the actual target. Browser startup rechecks access before dispatch, and an
unavailable or unauthorized explicit target never falls back to the default.
A browser ID grants no permissions of its own.
See the multiple-agent connection guide
for call examples and reconnect guidance.
Upgrading
No schema change and no new settings. Upgrade the main instance and every
worker together: while they run different releases, the main instance starts
nothing on a worker. Redeploys interrupt active browsers; their profiles remain
on the persistent volume.
The existing Tallylamp Link extension remains compatible. This release changes
MCP routing on the server; its extension package carries the matching version.
The release workflow
passed application, headed Chrome, and running-container checks before
publishing the tested image. Its anonymous registry access, digest, version
and source-revision labels were verified, along with the extension zip's
manifest version. Pin this Linux amd64 artifact:
ghcr.io/nxfi777/tallylamp@sha256:e58b007ebb32deb4cdaf5006e02254ae3c751125ae5c8a4a4d3d61c52ba807d4
After deploying that artifact, a live test sent concurrent calls through one
MCP session to two temporary browsers. Browser B responded in 131 ms while
browser A's delayed call took 2.62 seconds, and each returned its own page.
Changing the default did not redirect the explicit call. The temporary
browsers were removed and their test credential revoked afterward. A client
that queues calls can still limit concurrency before requests reach the server.
See the Railway upgrade instructions for
backups and deployment settings.
Tallylamp 0.11.2
Tallylamp 0.11.2
You can make Tallylamp forget how many threads a browser has used, so that it
is measured again.
A browser's next start is sized from what its last start reached, plus a
quarter and 25. One heavy run could leave a browser sized past what it needs.
It was then refused starts it would have fitted, or, if pinned, held room it
would not use. The only way to clear those counts was to change a Chrome thread
setting, which clears every browser's.
What changes
- Reset a browser's thread counts. On a host with a process limit, a
browser's page has a Processes and threads row under Pinned. It says
what the browser is using, the most it has reached, and how much room its
next start needs. Reset forgets those counts, whether the browser is
running or stopped, on the main instance or a worker. A running browser is
measured again from then on, and its launch on its next start. Until then a
start is assumed to needTALLYLAMP_BROWSER_THREADS, 300 by default. The
same reset isPOST /api/v1/browsers/{id}/threads/reset. - Only the administrator can reset. A smaller estimate is room that another
browser's start was counting on, so this works like pinning. A start refused
for room now says when a reset would let it in: "That estimate comes
from an earlier start. If it needs less now, the administrator can reset its
thread counts on its page." It says so only when the browser's own
measurement is larger than the default and the default would fit. Agents are
told to pass this on to you rather than retry. - A waiting start picks up a reset. A start queued for room is sized again
every second, so a reset lets it in as soon as it fits. - Browsers report what their next start needs.
GET /api/v1/browsers
returnsstartThreadsbesidethreads,peakThreadsandlaunchThreads. - Tallylamp Link stops reporting errors for other extensions' pages. With
another extension's page in front, such as daily.dev's new tab page, the side
panel tried to load that extension's icon. Chrome refused it and listed the
refusal onchrome://extensionsas an error in Tallylamp Link. The panel now
loads only web and inline icons, and shows a letter for any other tab.
Upgrading
No schema change and no new settings. Upgrade the main instance and every
worker together: while they run different releases, the main instance starts
nothing on a worker.
Install the new tallylamp-link.zip, or reload an unpacked copy, to get the
side panel fix. A linked browser keeps working with the old extension.
Tallylamp 0.11.1
Tallylamp 0.11.1
You can choose what an agent may do while you create it.
Until now New agent asked only for a name. To let an agent load a saved
profile, you created it, copied its token, went back to its row and opened a
second form.
What changes
- New agent asks for permissions. Below the name are the five things an
agent cannot do by default: load saved profiles, save and update them, lend
its browsers, borrow other agents' browsers, and reach private addresses on
your machine. Each one says what it hands over, and each starts off. The
token screen then lists what you granted. - One Permissions editor. Profile permissions and Lending on an agent's
row are now one Permissions button with the same list. Saving tells you the
change applies from the agent's next request, with the same token. - Tunnels have a control. Reach private addresses on your machine
(browser:tunnel) could only be granted withPATCH /api/v1/agents/:id. It
is on both forms now. - The dashboard and the consent page say the same thing. Both read the
permission wording from one list, whichGET /api/v1/agentsnow returns as
permissions, alongsidedefaultScopes. The consent page used to say a
tunnel reaches the computer running Tallylamp. It reaches the machine that
runs the tunnel command, which on a hosted instance is never the server. - A failed create keeps your choices. The request runs inside the form, so
an error shows there and the name and ticks stay put. Before, the form had
already closed. - Long dialogs scroll. A dialog taller than the screen, as New agent is on
a phone, used to run off both edges with no way to reach its buttons. - Checkboxes sit beside their labels. In the permission list and in the
list of agents that may use a linked browser, each box sat about 10px below
its name.
Upgrading
No schema change and no new settings. Upgrade the main instance and every
worker together: while they run different releases, the main instance starts
nothing on a worker.
Tallylamp Link is unchanged apart from its version number, so a linked browser
does not need the extension reinstalled.
Tallylamp 0.11.0
Tallylamp 0.11.0
A browser on a worker now does everything a browser on the main instance does,
apart from being saved as a saved profile.
Until now, moving a browser to a worker cost it Full browser, agent control of
Chrome's windows, tunnels and uploads. A browser that needed any of those could
not have a host to itself, which is the reason to add a worker.
What changes
- Full browser works on a worker. The worker captures the browser's own
display and does the clicks and keystrokes there, so the dashboard's Full
browser view shows Chrome's toolbar, popups and dialogs as it does on the
main instance. Extensions can be switched on and managed through it. - Agents can use Chrome's own windows on a worker.
tallylamp_desktop_screenshotandtallylamp_desktop_actionwork once
Allow agent control is on, the same switch as on the main instance. - Tunnels reach a worker's browser. The tunnel still connects to the main
instance. When Chrome on the worker asks for a private address, the worker
checks with the main instance, which carries the traffic if a tunnel is bound
to it. Public sites never wait on that check. upload_fileworks on a worker. It takes a file from the main instance's
temp directory, the same rule as before, and copies it to the worker first.
Its answer names the path the agent gave, not the copy's.- A call made during a move keeps its browser. An agent whose call landed in
the seconds a move takes was told no browser was bound, and had to call
tallylamp_use_browseritself. Now that call is refused as retryable, and the
next one reconnects to the same browser. - A browser's page follows a move made elsewhere. A move from another tab,
or from the API, left the browser's open page naming the old host until it
was reloaded. The page now redraws when its browser moves.
On Railway, with a main instance and one worker, a running browser moved to the
worker in 0.6 seconds and was driven there through /mcp. Chrome on the worker
read a file uploaded from the main instance, loaded a page from a laptop through
a tunnel, and took keystrokes that opened chrome://extensions. Full browser
showed its first frame in 0.4 seconds.
Security
xdotool can run programs and ffmpeg can write files. So a worker runs only what
Tallylamp builds: a capture of that browser's own display, and pointer and
keyboard commands. Each is checked argument by argument. Anything else is
refused, so the secret the main instance holds cannot run other commands on a
worker.
upload_file still refuses a file outside the main instance's temp directory,
exactly as it does for a browser there. The file is only copied after that
check passes.
Upgrading
No schema change and no new settings. Upgrade the main instance and every
worker together: while they run different releases, the main instance starts
nothing on a worker.
Tallylamp Link is unchanged apart from its version number, so a linked browser
does not need the extension reinstalled.
Tallylamp 0.10.1
Tallylamp 0.10.1
Moving a browser to a worker is now one step.
What changes
- Move to… does the whole move. It is in every browser's ⋯ menu and on its
page. A running browser stops, its profile is copied across with its logins
and tabs, and it starts again on the new host. Before, you had to stop it,
find Runs on in its settings, move it, then start it again. If the copy
fails, the browser stays where it was and starts again there. - You can watch it happen. The dialog closes as soon as you pick a host.
The browser's card and page show how much of the profile has been copied,
updated every second. When it finishes, a message says where the browser
runs now. On a phone that message stays at the top while you scroll. - The agent using it is told. Its next tool call carries a note saying
where the browser went and what does not work there. A call made during the
move is refused as retryable. - The fleet keeps updating while events keep coming. The dashboard used to
wait for a quiet 1.5 seconds before it refetched. A busy agent, or a move
reporting every second, could hold the cards still for as long as it lasted.
Now it refetches at most every 1.5 seconds, and waits while a ⋯ menu is
open, so a repaint no longer closes the menu under your pointer. - A worker's browser claims less that is not true. Save profile is gone
from its menu and page, and its Pinned and Extensions rows say what applies
on a worker.
Upgrading
No schema change and no new settings. Upgrade the main instance and every
worker together: a main instance on 0.10.1 gives a worker on 0.10.0 nothing to
start.
Tallylamp Link is unchanged apart from its version number, so a linked browser
does not need the extension reinstalled.
Tallylamp 0.10.0
Tallylamp 0.10.0
Railway gives a service 1,000 processes and threads and will not raise that on
a normal plan. The 0.9 releases made one service behave inside the limit. This
one adds a way past it, workers, and turns on a Chrome setting that cuts a
browser's threads by about 40%.
What changes
- Workers. A worker is a second service running this image with
TALLYLAMP_JOINset. It runs browsers for your Tallylamp within its own
1,000. You keep one dashboard, one/mcpURL and the same agent tokens. Add
one from the new Workers page. A new browser stays on the main instance
while it has room, and starts on a worker when it has not. To move one you
already have, logins included, stop it and use Runs on on its page. The
workers guide has the rest. - Some things do not reach a worker yet. Full browser, agent control of
Chrome's own windows, tunnels, saved profiles andupload_filework only on
the main instance. A worker's browser refuses each one and says to move it
back first. The live view, takeover, guest links, lending, recording and
per-browser proxies work on both. - CPU pinning is measured, and the template turns it on. With
TALLYLAMP_CHROME_CPUS=4, one browser went from a median of 346 threads to
203, over ten minutes on three heavy pages. No tab crashed and no reload
failed. The Railway template sets it for new installs. On an existing
install, set it yourself. The numbers are in
process limit settings. - A browser is measured again when that setting changes. One browser was
measured at 606 threads before pinning. After pinning it was still sized from
that, at 783, and refused a start it would have fitted. Tallylamp now drops
its thread measurements when the CPU or renderer setting changes. TALLYLAMP_IN_PROCESS_GPUis gone. Chrome 154 dies at launch with it
here. The variable is now ignored, so remove it if you set it.
Upgrading
The database gains workers and worker_join_tokens tables and a
browsers.worker_id column. Without a worker, nothing about your browsers
changes, and older images ignore all three.
Do not roll back while any browser is on a worker. An older image would treat
that browser as its own and start it on an empty profile. Move such browsers
back to the main instance first.
Run the same release on the main instance and its workers, and upgrade them
together. While they differ, the main instance starts nothing on that worker.
Tallylamp Link is unchanged apart from its version number, so a linked browser
does not need the extension reinstalled.
The release workflow
passed application tests, headed-Chrome tests, and running-container checks
before publishing ghcr.io/nxfi777/tallylamp:0.10.0 for Linux amd64, then
attached tallylamp-link.zip. Anonymous registry access, the manifest digest,
the version and source-revision labels, and the extension's manifest version
were verified. The image was then deployed to Railway as a main instance with
one worker, and a browser was moved to the worker, driven there and moved back.
Pin this artifact on the main instance and on every worker:
ghcr.io/nxfi777/tallylamp@sha256:b149e059251d91fb6a119eb98a2d289945c31ee97f38e55f9185133f14c1b26c
Tallylamp 0.9.1
Tallylamp 0.9.1
Two fixes to the recovery and pinning that 0.9.0 added. Both turned up on the
maintainer's own Railway service within an hour of upgrading.
What changes
- A browser that loses its renderer zygote is now detected. Chrome
retitles its child processes, so on Linux a renderer's or zygote's command
line reads back as one string of flags joined by spaces. Version 0.9.0 split
command lines only on the separators Linux puts between arguments, so it found
no process type for any Chrome child and never saw a zygote to lose. Each
browser's process and thread count was right; only this check was blind. A
broken browser was still restarted, but only after three navigations had
failed withnet::ERR_ABORTED. - Pinning a browser whose start is waiting now counts. A start checked
whether its browser was pinned once, when it began. A browser pinned during
the wait was still treated as unpinned, so it could stop only idle browsers.
If a busy one held the room, the start failed withfleet_full. The start
now checks again every second while it waits.
Upgrading
No schema change and no new settings. Tallylamp Link is unchanged apart from
its version number, so a linked browser does not need the extension
reinstalled.
The release workflow
passed application tests, headed-Chrome tests, and running-container checks
before publishing ghcr.io/nxfi777/tallylamp:0.9.1 for Linux amd64, then
attached tallylamp-link.zip. Anonymous registry access, the manifest digest,
the version and source-revision labels, and the extension's manifest version
were verified. Pin this artifact:
ghcr.io/nxfi777/tallylamp@sha256:7c45912424388950b9f12783f0dc7b7f2b02b49f670f14e362a4488b4a504244