v0.3.4 — the app, not the workshop
Download the repository, double-click install.command, and you have the app.
That sentence is the release. Until today this repository was a mirror of the
development tree — panel sources, a 108-file test suite, build tooling, an Electron
shell, planning notes — and finding the app inside it was your problem. Now it
publishes the product: one index.html, the daemon it talks to, and an installer.
Getting it
- Download the source zip below (or
clone-frame-hub-0.3.4.htmlalone if you only
want the app file). - Unzip, double-click
install.command. - It builds
CLONE FRAME HUB.appinto~/Applicationswith the whole program
inside the bundle and opens it. The folder you downloaded can then go in the Trash.
macOS quarantines anything from the web, so Finder may refuse the first double-click:
right-click → Open once, or run zsh install.command in Terminal, which never asks.
Updating is what you would guess. Trash the old app, download the new release, run
its installer. Your data is never inside the app — it lives in ~/CloneFrame and
~/.clone-frame-hub — so an update leaves every setting, session and folder alone.
Removing: uninstall.command stops the daemon, removes the app, and asks
separately about your data.
Closing an iT window now closes what was inside it
This is the fix that was costing you something. The code claimed to "reap every live
pty session". It dropped the sockets instead — and for a persistent session, which is
the default, a dropped socket means detach, not close.
So every shell in a window you closed kept running for the full sixty-minute detach
timeout. Builds still building. Dev servers still holding ports. Agents still spending
tokens. Invisible, against a 24-session cap you could not see, with nothing on screen to
tell you. Closing the window looked like closing the window.
Now it ends those sessions three ways, because a socket is not the only way one stays
alive: live tabs are killed in band; every session id the window owns is named to the
daemon, which reaches the ones whose sockets had already dropped and no in-band kill
could touch; and workspaces you restored but never opened — no terminal on screen, real
shells running — are reaped by the window that owns that layout.
Measured against a real daemon, with real login shells and a real marker process:
new 18/18 close kills · reload survives · detached sessions reachable
old 12/18 "no such fn: killMany" — the marker still running, unreachable
A reload still keeps your shells. That distinction is the entire value of persistent
sessions and it is untouched: ⌘R detaches and reattaches, scrollback and all. Keeper
sessions (the ⟳ tab) survive too, deliberately — they are this app's tmux: created on
purpose, listed by it sess list, ended by it sess kill. Closing a terminal window
does not kill your tmux, and nothing about them is hidden from you.
Every panel is one window. iT is the exception, and always was the point
Opening NOTES twice gave you two NOTES windows — the same store drawn twice, two scroll
positions, one set of data underneath. Asking for a panel you already have means show
it to me, and now it does: including a window you had tucked into a frame square, which
comes back instead of a second empty copy opening on top of the live one.
iT is untouched and infinite on purpose. Terminal windows side by side, each with
its own workspaces, split panes and live shells, is the whole reason it exists.
BROWSER lost its second window, and it was never a decision that it had one. A single
list answered two different questions — may this panel have several windows? and does
docking hide this window or destroy it? — and BROWSER only ever needed the second
answer, because a docked browser must keep its live pages. It got the first for free.
Two lists now: one window with tabs, docking still keeps every page alive, and the "New
browser window" button is gone. It could only have opened a copy of the window you were
already looking at; the tab strip's + is the control that does what that icon depicted.
Two things about this repository, said here rather than left to be found
- You cannot rebuild
index.htmlfrom this clone. Its sources are not here. You can
read it — it is one plain document — and check its hash against the line below. The
daemon is different:bridge/is its source, every line of it, and it is the half
that touches your machine. - The publisher's file list went from everything except a denylist to exactly these
paths. A denylist fails open: anything not named is public by default, so every new
folder was published until someone remembered to exclude it. A folder added tomorrow
is private until it is named.
Also fixed
make-app.shread the version through${BASH_SOURCE[0]}under a#!/bin/zsh
shebang. zsh leaves that empty, so the version came from whatever directory you were
standing in — it looked right only because everyone ran it frombridge/.- The model's own tool list told it
browse{newWindow:true}opens "a SEPARATE browser
window… use several to research side-by-side", and thatopen_panelreached 27 panels.
There are 20, and there is one browser window. - The publisher's secret scan aborted with
GITLEAKS_CFG[@]: unbound variablethe first
time it ran without its config in staging — bash 3.2 underset -u. It died on the
safety gate, skipping the two checks after it.
sha256 e04cf62990f65679d25a5b5dd5133a33c9e2fa9cc4de1a134abb5b558b666557
shasum -a 256 index.html must print that line. 923 tests pass upstream.