Skip to content

Releases: mlsimon734/tabglutton

v0.5.1

Choose a tag to compare

@github-actions github-actions released this 20 Oct 02:43
0136adb

Two threads. The Digest panel becomes a desk: a list beside a preview of the row you
focus, with what the page itself said kept visibly apart from what the agent claims, and
its shortlist action changes from Keep in a group to Move to top. Separately, Shift-click
selects a range of tabs in the popup and the full view. The bridge protocol and the
manifest's permissions are unchanged, so no running hub has to be stopped.

Features

  • The Digest panel is a desk: a list beside a preview. The shortlist gets a thumbnail
    and two lines of the agent's reasoning, filed items one line and where Devour would file
    them, and close rows one line with a checkbox. The row you focus opens beside the list
    with the page's own image and description, the agent's full reasoning, and Show and the
    section keys; in a narrow window it opens under the row instead. Hovering a compact row
    pops a small preview card. After Close, the closed rows fold into one line.
  • What the page said and what the agent claims now look different. Upright text and
    images come from the page, recorded by Tabglutton when the agent read the tab: its
    og:image (kept as a small thumbnail, so the panel never loads anything from the site), its
    description, site, author, date, and favicon, plus a video's length or a thread's comment
    count when the page states them. The agent's reasoning is italic behind a dashed rule
    labelled "Agent", and its quote is dropped when it only repeats the page's description.
    None of this can be supplied by the agent's report.
  • Untick a close row to leave its tab open. The row moves to "Could not read / leave
    open", and ticking it there puts it back. x ticks the focused row.
  • Shift-click selects a range of tabs. In the popup and full view, click a checkbox,
    then Shift-click another to select or deselect the rows between them. Ranges follow
    the displayed order and skip tabs hidden by filters.

Changed

  • Move to top replaces Keep in a group. The shortlist's tabs move to the top of their
    own window's tab list, right after your pinned tabs, in the digest's order. Nothing is
    grouped, pinned tabs are never touched, and Undo puts every moved tab back where it
    was.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 02:37
d84f7ba

Digests move into the extension. An agent that reads a batch of tabs now hands its verdicts
to Tabglutton through a new digest_report bridge tool, and you keep, close, and undo from a
Digest panel in the full view, while Gullet writes the matching note to your vault. This
release also folds in the never-tagged 0.4.2 work: an optional in-page duplicate notice,
YouTube transcripts in clips, a design polish pass, and a fix for row closes that lagged or
needed a second click. The bridge protocol is unchanged, so no running hub has to be stopped,
but digest_report needs this version of both the extension and Gullet.

Features

  • Digests land in Tabglutton, and you act on them there. An agent running the digest
    skill (it ships with Gullet) now reads a sitting's tabs and reports its verdicts through a
    new digest_report tool instead of writing notes and closing tabs itself. The full view
    gains a Tabs | Digest switch: the Digest side shows the report in four sections (worth
    your time, file for reference, close, could not read), each row with the agent's reason.
    Keep in a group puts the open shortlist into a "Worth your time" tab group in its
    window; Close closes the close section as one batch, and Undo brings it back, from
    the toast or later from the section head. Move a row between sections with 1–4 before
    acting. Pinned, active, and hidden tabs are left alone, and a row whose tab has changed or
    can't be told apart from another copy is refused rather than guessed at. The popup shows a
    Digest ready line until you have opened it. Nothing about the report is trusted: the
    panel shows who says they reported it, and renders every word as plain text.
  • Gullet writes each digest's note to your vault. One markdown note per digest, in
    Digests/ of the vault you clip to (or any folder, with digestMirror in Gullet's
    config), written straight to disk and exactly once however often the agent retries.
    Agent text in it is escaped, so a hostile page title cannot become a link, an embed, or a
    Dataview query. Turn it off with "digestMirror": { "enabled": false }.
  • An optional notice when duplicates pile up. Switch it on under Deduplication in
    Settings and pick a threshold, and once the badge count reaches it a small Tabglutton pill
    appears in the corner of the page you are on — the count, a Dedup button, and Undo
    after it — then takes itself down after fifteen seconds if left alone. It is a piece of the
    extension's own UI inside the browser, never a system notification. One notice per pile: it
    comes back only after the count has dropped below the threshold and climbed past it again,
    at most every thirty minutes, and restoring closed tabs with Undo counts as keeping them.
    Off by default. On Chrome the switch asks for site access, since the pill is placed on the
    page; the manifest now lists the notice page under web_accessible_resources so a page
    can embed it.
  • YouTube clips carry the transcript. The extractor now runs Defuddle's async path, which
    fetches a video's caption track instead of stopping at the description: two talks that
    clipped as 24 and 153 words now clip as 15,189 and 8,847, with timestamps. The same path
    reads a Reddit comments page from its feed and a logged-out x.com status through oEmbed when
    the page itself has nothing rendered, and falls back to the page as before when those
    fetches fail. Everything else extracts exactly as it did.

Changed

  • Update both halves together. digest_report needs this version of the extension and of
    Gullet; the skill tells the user to update when the extension doesn't know the tool. The
    bridge protocol is unchanged, so no running hub has to be stopped.
  • Design polish. The full view at narrow widths (under 980px) now stacks the inspector
    under the queue instead of squeezing both into two columns. The Obsidian handoff page
    follows the theme instead of flashing white, and says what it is doing, with a link to open
    the note by hand if the launch is blocked. Off toggles in Settings are visible (3:1 against
    the page and the track in both themes), its buttons take the same pill shape as everywhere
    else, and the Gullet link stops rendering in default blue. The duplicate notice's Dedup
    button takes the accent, and the pill keeps its edge on pages the same colour as it. Long
    duplicate URLs in the popup end in an ellipsis instead of being cut off. Setup no longer
    calls Dedup "exact-duplicate", shows a literal {URL} on Chrome, or says a rules editor is
    still to come. The window title and button labels say "full view" rather than "cockpit".

Fixed

  • Closing a tab from its row is immediate, and never needs a second click. The row
    used to stay until the whole list had been rebuilt — about a quarter of a second on a
    backlog of a few thousand tabs — and on Firefox and Zen a click that landed while that
    rebuild ran was lost. The row now goes as soon as the tab has closed, and the list never
    rebuilds while the mouse button is down, in both the toolbar popup and the Devour page.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 30 Aug 03:57
469265c

Two threads, and a fix from the security audit. Site rules stop being a built-in pair and
become a system the user writes: editable and ordered, carrying a disposition beyond a
subfolder — never devour, close without saving, always Zotero — and able to write their
matches into the browser's own tab strip. Separately, Tabglutton now remembers what it has
clipped, so a page already filed is marked wherever it turns up again and an agent stops
paying to re-read it. Tab grouping needs the new tabGroups permission, which browsers do
not surface in the install prompt.

Features

  • Site rules are user-editable on the options page — add, edit, remove, and reorder them;
    the old built-in GitHub/Social entries are now just the seed, and first match (top to
    bottom) wins. Patterns run through the same URL canonicalizer as Dedup and can pin a
    path (reddit.com/r/rust), not just a host.
  • A rule can carry a disposition beyond a subfolder: never devour (the tab is kept open and
    reported, never clipped — the agent bridge respects this too), close without saving (with
    the same undo toast a dedup close gets), or always send to Zotero (skipping the
    Connector's detection, whether or not detection-based routing is on).
  • Rule dispositions are visible before they act: matching tabs carry a pill in the popup
    and the Devour cockpit, and the cockpit inspector names the rule, its disposition, and
    the folder it files into.
  • A rule can also carry a tab-group name and colour, and the cockpit's new Group button
    writes that grouping into the browser's own tab strip — preview first, always: nothing
    moves that the preview did not show. Unmatched tabs are left alone (no fallback
    clustering), pinned tabs are excluded because grouping silently unpins them, a skip
    list parks sites that must never be reordered, and grouping never moves a tab between
    windows. Needs the new tabGroups permission, which browsers do not surface in the
    install prompt.
  • Tabglutton remembers what it has clipped. Every successful clip — Devour, the bridge's
    tab_clip, Obsidian, a markdown file, or a Zotero save — is recorded under the same
    normalized URL dedup uses, so a page filed from a newsletter link is still recognised when
    it turns up from a group chat. The Devour cockpit marks those rows and can filter the list
    down to either half, and tabs_list carries a clipped field so an agent stops paying to
    re-read pages already filed. The mark says clipped, never "in your vault": a launched
    clip means the handoff was made, and only verified means something that can see the
    filesystem saw the note — the browser watching a download complete, or Gullet finding the
    note in the vault, which it now tells the extension about. Neither is a claim about what is
    on disk now; notes get moved and deleted. The memory holds 5000 pages, dropping the
    least recently clipped first.
  • A "Copy diagnostics" button on the options page, under a new Troubleshooting heading.
    One click puts a paste-ready block on the clipboard: extension version and build target,
    engine and its full version, platform, tab and duplicate counts, the scope and clip
    destination, which of the three optional permissions are actually held, the bridge's state,
    and the last ten bridge failures with the ones that repeated collapsed into a count. It
    carries no bridge token, no page addresses and no tab titles — the block is assembled from
    a fixed set of counts and enum values rather than from a settings object, so there is
    nothing in it to redact. The bridge error log is session-scoped, which on Chrome means it
    is empty after the service worker has idled out.

Changed

  • Devour now dispatches up to three Zotero Connector saves at once instead of one at a time. That
    is the save step only — waking each tab and asking the Connector to identify it are unchanged
    and usually dominate a backlog run — and the speedup is reasoned from the serial timings rather
    than measured against a live Connector. Everything the run reports is unchanged: same counts,
    same per-tab failures, same order. The Obsidian handoff stays strictly serial, because it
    borrows the OS clipboard.

Fixed

  • Gullet's clip verification stays inside the vault. The note path tab_clip reports comes
    off the browser connection, and it was joined onto the vault directory unchecked — so a
    ../-laden path had Gullet list a directory elsewhere on disk, stat and read any note by that
    name in it, and report a verdict on what it found: a weak existence oracle for anything holding
    that connection (SECURITY-REVIEW.md §7). A path that resolves outside the vault now answers unknown before
    anything is read, the same soft contract every other "cannot check" in that module follows.
    No in-vault clip verdicts differently.
  • A clip that extracts almost nothing now keeps its tab instead of filing junk and closing
    it.
    Waking a backlog is the traffic pattern most likely to draw a bot check, and a
    challenge served at the parked URL has no translator, so it fell past the Zotero route and
    Defuddle's extraction of "Just a moment…" counted as a successful clip. Anything under 512
    characters of extracted text is refused: the tab is kept, and the popup's failure row reads
    "too little content" with the character count and what to do about it. Where a known
    interstitial signature matches too, the message says so outright. For agents, tab_clip
    refuses the page with a new thin-content error while tab_read — which files and closes
    nothing — still returns the text, with a thin note saying how little there was and
    whether it looks like a challenge. (#49)
  • The agent bridge now obeys the "Route papers to Zotero" setting. With that setting on,
    tab_clip saved papers into Obsidian anyway, so an agent clearing a backlog quietly filed them
    in the wrong place; it now runs the same routing the popup's Devour does, reports
    destination: "zotero", and closes the tab only once the Connector confirms the save. A
    Connector that cannot take a routed tab fails that clip with zotero-failed and leaves the tab
    open rather than falling back to Obsidian. Naming a vault in the call still overrides
    everything, and the wire protocol is unchanged.
  • The scrollbar in the Devour cockpit and the popup now spans the list instead of the
    window.
    It ran the full height of the viewport, starting level with — and behind — the
    floating header rather than at the first row; in full screen, with no browser chrome above
    it, it reached the top edge of the display. Both surfaces scroll a full-height container so
    rows pass under the glass, and no engine can inset a native scrollbar to a shorter band, so
    the native bar is now hidden on both and the thumb is drawn over the band between the
    header and the action bar. It follows the chrome when the warning banner or the failures
    panel changes its height, and it can be dragged. Scrolling by wheel, trackpad and keyboard
    is unchanged.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 23:46
d3c610e

Two threads. Devour no longer requires Obsidian — a clip can land as a plain markdown file
in the download folder, chosen on the options page or during onboarding. And the browser's
bridge connection now outlives the agent session that opened it, so starting a session is a
local attach rather than a fresh hunt for a socket. A third arrived late, from the audit
before Gullet's first npm publish: the bridge handshake had a relayable proof, and closing
it moves the wire protocol.

Breaking

  • The bridge wire protocol is now 3, and the token proof is bound to the channel it is
    presented on.
    Update the extension and Gullet together; there is deliberately no
    downgrade path. Protocol 2 hashed only the token and a nonce, in one function used in
    both directions, so the proof was a credential anyone could borrow: every honest client
    proves first to whatever answers the marker probe, so a local process knowing no token
    could bind a free candidate port, wait to be dialled, forward the real hub's challenge as
    its own, and replay the answer to that hub as a peer. That yielded the full tool surface —
    list, read, clip, close every tab — plus enough to retire a detached hub and hold its
    port permanently. Proven against the live hub and re-run against the fix;
    SECURITY-REVIEW.md carries the exploit and the before/after. The proof now includes the
    role it is claimed under and the loopback port it is presented at, so a proof handed to a
    squatter is worthless at the real hub. No fallback and no negotiated downgrade: an
    attacker who can imitate the marker can also claim to be old.

    Upgrading needs one manual step, once. A background hub started by the previous
    version outlives the session that spawned it and keeps its port, and a protocol bump
    cannot ask it to stand aside — retiring requires proving the token, and the proof is
    itself protocol-shaped. If the bridge does not come back after updating, stop the old
    hub: pkill -f "gullet.*--detached-hub". Tabglutton's settings now say "Sidecar
    version mismatch — update both halves"
    instead of sitting on "Waiting for a sidecar",
    and Gullet names the port and this command in its own error.

Features

  • Devour can write plain markdown files instead of filing into Obsidian
    (#36). Same frontmatter, the same
    Clippings/<site subfolder>/ layout and the same note names, written to the browser's
    download folder. downloads is an optional permission, requested when you pick the
    destination rather than at install. It is a chosen mode and never an automatic fallback:
    the extension provably cannot tell a refused obsidian:// handoff from a successful one,
    so anything shaped like "we noticed that failed, saving a file instead" would be a guess.
  • Onboarding asks where clips land, at step 2
    (#42). Choosing markdown files hides
    the vault field and drops the obsidian:// approval step out of the walkthrough entirely
    — a walkthrough that files to disk never needed it. Step 2 previously refused to advance
    without a vault name, putting the install gate #36 exists to remove straight back on first
    run.
  • The bridge's tab_clip obeys the same destination setting as the popup's Devour
    (#41), with one stated exception: a
    vault override still names Obsidian for that call, because it is a destination the
    caller asked for outright. Before this the bridge read the vault directly and an agent
    clip failed with vault-missing for anyone in file mode.
  • Duplicates are shown, not just counted
    (#39). The popup and the cockpit both
    open with a Duplicates section: one group per canonical URL, the copy Dedup keeps marked
    keep, and the cost of closing the rest. Select extras puts those copies into the
    normal selection, so duplicates can be devoured rather than only closed.
  • The browser connection outlives the agent session
    (#40,
    #29). The first Gullet to find no hub
    spawns a detached one and attaches to it as a peer, so session start is a local attach and
    the socket is won once per browser session rather than once per agent session. The hub
    exits by itself after six idle hours, stands aside for a newer Gullet, and takes a
    SIGTERM; --no-detach keeps the old session-scoped shape. The extension arms its
    keepalive only while the hub reports at least one attached session, so a hub with nobody
    waiting no longer pins the event page.

Changed

  • tab_clip's result is a discriminated union, and two of its fields are no longer
    unconditional.
    destination is "obsidian" or "file"; vault and contentHash
    exist only on the Obsidian variant, and file is absent exactly when nothing could
    confirm the write. confirmedBy — "browser", "gullet" or "nobody" — names who
    proved the clip landed, replacing a boolean whose false meant "could not check" and
    read as "did not land". This shape needed no protocol bump of its own — Gullet is its
    only consumer and ships alongside the extension — though the handshake fix above moves
    the protocol anyway.
  • A bridge clip's destination follows the user's setting rather than always being the
    vault. No existing install can notice the difference: file mode ships in this same
    release, so there is no state in which the old and new behaviour disagree.
  • Revoking the downloads permission is now handled instead of merely failing
    (#43). The grant is optional and can
    be taken back from the browser's own add-on settings, and it is checked once per Devour
    run before any tab is woken — with it gone, a run over 50 discarded tabs used to reload
    all 50 and then fail every one of them. The options page now re-checks it on load and, if
    it is gone, moves the destination back to Obsidian and says so. That revert is the fix,
    not the wording: re-selecting an already-checked radio fires no event, so the file
    destination previously had no way left to ask for the permission again. Onboarding
    already did this; the popup, the background page and the bridge now name a remedy the
    user can actually perform.
  • A clippings folder is sanitized the same way a note name is in file mode. A base
    folder containing : " < > ? or a control character reached the downloads API unfiltered,
    where Chrome silently rewrote it and Firefox on Windows could refuse the call outright.
  • Gullet reads ./.env last, below the global token file, instead of above it. It is
    the only token source read out of a directory the user did not choose — an MCP host sets
    the sidecar's working directory to whatever project the agent session started in — so a
    cloned repository shipping a .env could silently replace the token the options page
    wrote, putting the session in a realm its author also knows. It can still supply a token
    when no global one exists, and it never answers for a global file that merely failed to
    read, so a locked secret manager still surfaces its own error and still heals on retry.
  • A hub's log can no longer be flooded by anything that can open a socket. The refused-
    upgrade line carried the caller's raw Origin, which is unauthenticated input: one
    loopback client sustained ~480 MB/s into hub.log, a file the README calls small by
    construction. It is now one line a minute with a count of what it suppressed, and the
    origin is truncated.

v0.3.1

Choose a tag to compare

@github-actions github-actions released this 13 Aug 01:36
7f45735

Identical to 0.3.0. That version went to AMO's self-distribution channel by mistake, and
AMO rejects a version number that already exists on the add-on — measured, not assumed:
uploading 0.3.0 to the listed channel answers "Version 0.3.0 already exists." A version's
channel cannot be changed after upload and a number is never freed, so the store release
of this code has to carry the next one.

The submission page is what makes this easy to get wrong. It states the current channel as
prose ("On your own.") with a small Change link, and the file picker sits directly beneath
it — the radio buttons live on a separate /versions/submit/distribution page, defaulting
to whatever was used last, which for this add-on is every sign:dev build ever signed.
Go to that page first: ?channel=listed arrives preselected.

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 13 Aug 00:38
34419e3

Mostly about trusting the bridge on a real backlog: a clip is now confirmed on disk
before its tab is closed, and tabs_list is usable at the scale this product is for.

Breaking

  • The bridge wire protocol is now 2, and mixed versions are refused rather than
    allowed to look successful.
    Update the extension and Gullet together. A protocol-1
    Gullet would omit tabs_list's limit and silently lose tabs; a protocol-1 extension
    would ignore tab_clip's vault override and file the note somewhere the caller did
    not ask for. Neither is recoverable downstream and both would be reported as success.

Features

  • tabs_list works on a large backlog. Filter with a query, group by domain, and
    cap the result — and every answer reports matched and truncated, so a complete
    listing is distinguishable from a partial one. The tool description now pushes callers
    to triage on metadata before reading anything.
  • A clip is verified on disk before the tab closes. Gullet runs beside the vault, so
    it can answer what the browser cannot: a refused obsidian:// handoff is
    indistinguishable from a successful one from inside the extension. A note is matched by
    freshness, by the source it records, and by a SHA-256 of exactly the text handed to
    Obsidian — so a clip that never landed can no longer cost you the tab. Being unable to
    check is never treated as failure.
  • tab_clip can name its vault, validated against Obsidian's own registry rather
    than trusted blindly.
  • Academic papers can route to Zotero instead of Obsidian, opt-in and off by default,
    using the Zotero Connector's own classification rather than a hostname list. Requires a
    Connector exposing the external API — see docs/ZOTERO_POC.md.
  • Gullet is globally configurable and publishable. Settings live at
    ${XDG_CONFIG_HOME:-$HOME/.config}/tabglutton/config.json, which is deliberately safe
    to commit — an inline token is refused. Tokens resolve by an additive precedence chain
    ending at a 0600 file.

Fixed

  • Obsidian handoffs no longer fail silently on Firefox. The launch now goes through
    an extension-origin page, so the one-time external-protocol approval has a principal
    the browser can remember (#18).
  • A transient tab-read failure is retried without masking a genuinely restricted page.
    Firefox reports both as Missing host permission for the tab, and a page on its
    restricted-domains list can never satisfy a retry, so those report the engine's own
    message instead of advice that cannot be followed.
  • The toolbar icon is the extension's own mark. It had drifted to an unrelated
    drawing, unnoticed because the toolbar icon and the popup header are never in frame
    together; the copies are now pinned to each other by a test.
  • The cockpit's chrome floats over the list rather than displacing it.

v0.2.0

Choose a tag to compare

@mlsimon734 mlsimon734 released this 10 Aug 23:21
c4f95f1

Published on AMO: https://addons.mozilla.org/firefox/addon/tabglutton/

First public release. Every earlier 0.1.x was an unlisted build signed for local
testing, so all of this is new to anyone installing from a store.

Features

  • Dedup. Finds duplicate tabs by canonicalized URL — fragments and tracking
    parameters stripped, with the strip list configurable — and closes all but one
    keeper. Scoped to the current window, or to visible tabs where the browser
    exposes that. Needs no access to page content.
  • Devour. A full-screen cockpit over the open tabs, grouped by host with
    duplicates flagged and a per-tab inspector showing exactly where a clip will
    land. Every close is undoable from a toast.
  • Obsidian clipping. Pages are extracted with Defuddle and filed as markdown
    with Web Clipper-compatible frontmatter, by clipboard handoff or obsidian://.
    Per-site subfolder routing and a configurable Clippings folder.
  • Chrome support alongside Firefox and Zen, from one source tree.
  • Agent bridge. An MCP sidecar (Gullet) exposing six tools — tabs_list,
    tabs_load, tab_read, tab_clip, tabs_close, undo_close — over a
    token-authenticated loopback WebSocket, so an agent can triage a tab backlog.
    Off until switched on. Several agent sessions share one browser connection,
    and nothing is closed that undo_close could not put back.
  • Automatic bridge port. Both ends discover each other across a small
    ordered candidate set, so there is no port to configure and nothing to keep in
    sync. A fixed port remains available for advanced setups.
  • First-run onboarding, and a settings page that opens in a tab or embedded
    in the Add-ons Manager.

Changed

  • Chrome asks for site access at first use rather than at install, so the
    install prompt no longer warns about reading data on all websites. Dedup — the
    default flow — never needs it.
  • Note names are sanitized per platform (Windows, macOS, other) rather than
    applying the macOS rules everywhere, matching Obsidian Web Clipper on each.

v0.1.2.1

Choose a tag to compare

@mlsimon734 mlsimon734 released this 18 May 02:11
ebbb933

Published on AMO: https://addons.mozilla.org/firefox/addon/tabglutton/

Patch release after v0.1.2:

  • Update the fullscreen Devour cockpit tab favicon to use the new Tabglutton chomp icon.

Artifacts include the unsigned extension zip, source zip, and signed AMO XPI.

v0.1.2

Choose a tag to compare

@mlsimon734 mlsimon734 released this 18 May 02:04
040745a

Published on AMO: https://addons.mozilla.org/firefox/addon/tabglutton/

Changes since v0.1.1:

  • Replace the extension icon with the new Tabglutton chomp mark.
  • Add onboarding/settings copy for Devour.
  • Improve Devour clipping reliability and progress behavior.
  • Standardize release signing on a repo-local .env file with .env.sample.

Artifacts include the unsigned extension zip, source zip, and signed AMO XPI.

v0.1.1

Choose a tag to compare

@mlsimon734 mlsimon734 released this 16 May 19:45
523d35d

Published on AMO: https://addons.mozilla.org/firefox/addon/tabglutton/

Backfilled GitHub release for the version that shipped on AMO. The full changelog for development since then will appear in the next stable release.