Releases: thejdubb02/clique
Release list
0.67.0
The three things a phone still could not do, all from a mobile review a second model wrote, and all confirmed against the code first.
The long-press menu scrolls. A live session's menu is fifteen to twenty rows, and at the padding a thumb needs that is taller than a phone. It ran off both ends at once: Open cut off above the screen, Kill below it, nothing to scroll. The menu whose whole reason for existing is that a phone can archive, lock and kill from it could do none of the three.
A working group answers a long press. Rename and delete were right-click only, so from a phone you could launch a group and never change or remove one.
You can hand a session a file, and get text back off the pane. Drop needs a mouse and paste needs the file already on the clipboard, so a phone had no route in at all. There is a paperclip next to Run now, and an entry in both menus. Coming the other way, long-pressing the output offers the line you pressed, what is on screen, and the last twenty lines.
And one the paperclip uncovered. On a 320px phone the prompt box measured 26 pixels, narrower than one word, because every other control in the bar refuses to shrink. Under 460px the bar wraps and the box takes the row.
0.66.1
The other half of the Android fix. 0.66.0 gave a phone the panel's own prompt box and then handed the keyboard to the terminal anyway: opening a session focused the pane, and tapping Esc or Ctrl-C on the key row took focus back. So the box was there and Gboard was still typing into the terminal, and still duplicating the line. On a touch device showing the box, nothing takes focus on its own now, and the first thing you tap decides.
The installed app no longer draws under the notch. The standalone rule that pads for the safe area has been in the stylesheet for a while and was doing nothing, because the safe-area values report 0 without viewport-fit=cover in the viewport tag, and only the sign-in page had it. The panel has it now, and the toast clears the home indicator, which is where Undo after a kill lives.
Both found by having a second model read the mobile surface and say what it thought. The write-up is in docs/mobile-review-grok.md.
0.66.0
Typing on an Android phone no longer repeats the line you just sent. With a suggestion from the keyboard, or a paste, the same sentence would arrive in the pane over and over.
A CLI that draws its own prompt box gets the terminal to itself, so on a phone you were typing straight into the terminal, one keystroke at a time, through the keyboard's input method. Gboard predicts, autocorrects and pastes into a hidden field the terminal keeps emptying under it, loses track of what it believes is there, and re-commits the whole line. A touch device now always gets CLIque's own prompt box instead, where a finished line is sent in one piece. Setting the prompt-box mode to Terminal still overrides it.
Two more found on the way, live on a desktop too: an Enter arriving mid-word from an input method is no longer treated as send, and a second Enter is refused while the first is still waiting on a confirm or a request.
A different theme on a schedule. Tick the themes you like under Appearance, pick an interval and a time, and CLIque puts a different one on. Every 24 hours from 07:00 is a fresh theme each morning; every 6 hours changes at 07:00, 13:00, 19:00 and 01:00. Random, and never the one already on. Change now does it on the spot.
POST /api/themes/rotate and five new settings.
0.65.0
A session whose saved conversation is gone now starts anyway. Clicking one did nothing at all: no pane, no error, nothing to click again.
A resume key can outlive the thing it points at. Open a session, never type in it, let the idle reaper stop it six hours later, and the CLI has nothing on disk to come back to. CLIque asks for it anyway, the CLI refuses in about a second and a half, and the tab goes quiet.
The panel now watches a resume for up to eight seconds and, the moment the pane turns out to be gone, drops the key and starts the session clean. Usually over in two seconds, and there is nothing to click, learn or turn on. It only does this for a key that is CLIque's own session id, which is the one case where we know how it got there and can derive it again. Stopping a session inside that window wins, so nothing is ever resurrected behind you.
POST /api/sessions/<id>/start now answers with resumed, saying whether the resume form was used.
0.64.0
Tapping the prompt on an iPhone no longer zooms the whole page. Safari zooms when it focuses an input whose text is under 16px, and the prompt box was 13px, so the single most common thing you do on a phone moved the layout under your thumb every time. Every input, textarea and select is at least 16px on a touch device now, and untouched on a desktop.
The status bar stopped hanging off the screen. 460px of controls in a 393px phone, which is what the clipped icons actually were. The readings already dropped out in order of how much they decide; the controls on the right never did. The two that go first are the two a phone cannot use anyway: a keyboard-shortcut sheet and a font stepper that Settings also has.
Tap targets: 34 under 44px, now 9. Growing a 17px tab close button to 44 would wreck a 35px strip, so the hit area grows instead and nothing moves by a pixel. Nothing changes on a mouse. The nine left are the key row, a correct 44px tall and as wide as seven keys can be on a phone.
Tetris is now Bricks and Pacman is now Chompy. The artwork was never the issue: every figure is an original design. The names were. The id is what gets stored, so the two old ids are aliased to the new ones and nobody wearing one loses their theme.
0.63.0
Working groups: sessions you always open together. A group holds a Claude, a Gemini and a Grok, or three of the same, from one directory or three unrelated ones. One click opens all of them, side by side, under a band that says they belong together.
Not folders, and the difference is the whole feature. A folder files a session in the sidebar and a session has exactly one. A group is about launching several things at once and telling at a glance which tabs belong to which piece of work, so it can pull from several folders or none, and a session can sit in more than one.
The band is inside the tab strip, not above it. Chrome hangs a labelled band over its tab groups and spends a row of height on it. There is no row to spare: the strip is 35px and on a phone it is competing with the pane for the only screen there is. So it is a rule along the bottom edge of the tabs, which costs nothing and is the same on a desktop and a phone. The group's name lives in the sidebar, where there is room for words and where you launch it from anyway.
Opening a group gathers its tabs into one run. That is not decoration: the same colour scattered through the strip reads as unrelated pills rather than one band. Tabs already open are moved rather than duplicated, so opening a group twice tidies the strip instead of growing it.
A member is a snapshot, not a pointer. Each stores the session's CLI, directory and name beside its id, so a member whose session has been deleted is reported rather than quietly missing, and is recreated only when you ask.
POST /api/groups/<id>/open is the whole thing, so a script can open a working group too.
0.62.1
A reload button, for the installed app that has nowhere else to get one. A PWA has no address bar, so a panel that ever needs a fresh load leaves you closing it and reopening it from the home screen. It sits in the status bar, which is outside the sidebar and therefore still there when the drawer is shut on a phone.
Shown only where it is the only way in: the installed app, full screen, and the iOS home screen, which has its own flag because it predates the standard. A browser tab does not get one, because it would be a button doing what the browser's own reload already does, in a row that is already full. The command palette offers it everywhere either way.
The service worker is asked to update before the page reloads. It does not cache, so a plain reload already fetches fresh code, but the worker is the one thing a reload would otherwise keep, and "reload" meaning "all of it except the part that serves you" is a promise not worth making.
Sessions keep running, and the tabs and layout come back, because the workspace has always lived on the server rather than in the tab.
0.62.0
The active CLI's logo, faint in the top-right of the pane. Opposite corner to the theme character, so a theme with one and a session with the other never sit on top of each other.
The pane edge has carried the CLI's colour for a while, and that answers "which one am I in" for anyone who has learned the colours. This answers it for everyone else, and across a screen of panes rather than by reading a tab. At seven percent it is a thing you notice when you look for it and not when you are reading output.
Two shapes of icon, the same split the sidebar markers already make. A single-colour glyph becomes a mask tinted with the CLI's own colour, which is what lets one file serve the tinted, grey and watermark modes at once. A logo that carries its own colours cannot be a mask, because it flattens to a solid square, so it is drawn as the image it is. A CLI with no icon draws nothing rather than inventing a letter.
Desktop only, on the same size rule the theme character uses. One checkbox under CLI markers turns it off.
0.61.0
Scrolling the terminal with a finger works. It never had, and there were three separate reasons, each of which had to be found before the next was visible.
tmux was keeping no scrollback at all. Every agent CLI enters the alternate screen at startup, and an alternate-screen pane keeps no history by design: measured history_size=0 against a 20000 limit on every live session. tmux is now told to ignore the switch, which puts output in the normal buffer where it scrolls into history: 279 lines against 0 for the identical program.
The browser was showing the wrong buffer. The alternate-screen switch was stripped only for CLIs that own their input; everything else parked xterm in the alternate buffer, which holds one screen and no scrollback by definition. Measured 360 lines sitting in buffer.normal while the pane displayed the 45-line alternate one.
And nothing was listening for a finger. Scrolling has always been this panel's own wheel handler, because xterm needs telling which buffer a scroll belongs to, and there was no touch equivalent: not a broken gesture, an absent one. touch-action: none on the pane is what lets a drag arrive at all, because otherwise the browser claims it for the native scroll of an area exactly one screen tall.
The trade, stated plainly: a full-screen program that exits no longer has its screen restored, so vim in a shell session leaves its last frame behind. For a panel whose whole purpose is reading what an agent did, keeping the transcript is the better half of that bargain.
0.60.0
CLIque installs as an app on a phone, from the page you actually arrive on. The panel had a correct manifest, a service worker and every icon size. The sign-in page had none of it, and the sign-in page is what a phone meets first, so "Add to Home Screen" gave you a bookmark with a screenshot for an icon and Safari's chrome around the result.
The cause was an allow-list that had quietly gone dead. PUBLIC_ASSETS names what may be served before login, and a past fix for a real traversal hole (/brand/../app.js resolved back to the app shell) replaced the whole check with a single "is it inside brand/" test. That closed the hole and, with it, silently un-published the manifest and the favicon: the constant was still declared, still read like documentation, and referenced by nothing. A browser cannot offer to install an app whose manifest it is not allowed to read.
The allow-list is honoured again and the traversal stays closed, because the comparison is between resolved paths rather than prefixes. sw.js joins the list, because Chrome judges installability from the page in front of it.
Three things fixed on the sign-in page, all found by tooling rather than by looking. The password field was 14px, so iOS zoomed the entire page the moment you tapped it. The field and the button were 42px against a 44px thumb. At 320px the page scrolled sideways for want of box-sizing: border-box.
tools/smoke_http.py now asserts both halves of the allow-list from a logged-out client, including four traversal attempts through brand/... That is the test whose absence let the list go dead.