Skip to content

Releases: nxfi777/tallylamp

Tallylamp 0.11.6 — OAuth logins survive parallel clients

Choose a tag to compare

@nxfi777 nxfi777 released this 15 Oct 11:00

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 on ADMIN_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. Without ADMIN_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 as oauth.refresh_reuse, not
    again for every retry against the dead grant.

See OAuth protocol details.

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

Choose a tag to compare

@nxfi777 nxfi777 released this 12 Oct 14:35

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_pages lists extension service workers,
    evaluate_script with serviceWorkerId runs code inside one,
    list_console_messages includes content-script messages, and navigate_page
    opens an extension's own chrome-extension:// pages.
  • list_extensions lists unpacked extensions. trigger_extension_action
    presses an extension's toolbar button on the selected page.
    install_extension loads an unpacked folder from the Tallylamp host's disk,
    and reload_extension and uninstall_extension manage 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. A control grant can trigger an action and run
    code in a service worker, with that extension's permissions. A read grant
    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 for install_extension
    on a browser that runs on a worker.

See debugging an extension.

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

Choose a tag to compare

@nxfi777 nxfi777 released this 09 Oct 02:01
e6e547a

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=local keeps 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

Choose a tag to compare

@nxfi777 nxfi777 released this 09 Oct 01:30

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 optional browserId. 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_browser and
    tallylamp_use_browser still 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

Choose a tag to compare

@nxfi777 nxfi777 released this 07 Oct 13:16

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 need TALLYLAMP_BROWSER_THREADS, 300 by default. The
    same reset is POST /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
    returns startThreads beside threads, peakThreads and launchThreads.
  • 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 on chrome://extensions as 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

Choose a tag to compare

@nxfi777 nxfi777 released this 02 Oct 13:27

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 with PATCH /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, which GET /api/v1/agents now returns as
    permissions, alongside defaultScopes. 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

Choose a tag to compare

@nxfi777 nxfi777 released this 30 Sep 22:29

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_screenshot and tallylamp_desktop_action work 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_file works 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_browser itself. 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

Choose a tag to compare

@nxfi777 nxfi777 released this 30 Sep 19:16

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

Choose a tag to compare

@nxfi777 nxfi777 released this 30 Sep 16:13

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_JOIN set. It runs browsers for your Tallylamp within its own
    1,000. You keep one dashboard, one /mcp URL 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 and upload_file work 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_GPU is 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

Choose a tag to compare

@nxfi777 nxfi777 released this 29 Sep 17:26

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 with net::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 with fleet_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