clique-panel 0.50.54__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clique_panel-0.50.54/LICENSE +21 -0
- clique_panel-0.50.54/PKG-INFO +217 -0
- clique_panel-0.50.54/README.md +168 -0
- clique_panel-0.50.54/clique/__init__.py +40 -0
- clique_panel-0.50.54/clique/__main__.py +231 -0
- clique_panel-0.50.54/clique/app.py +1838 -0
- clique_panel-0.50.54/clique/artifacts.py +155 -0
- clique_panel-0.50.54/clique/attention.py +236 -0
- clique_panel-0.50.54/clique/auth.py +253 -0
- clique_panel-0.50.54/clique/changelog.py +127 -0
- clique_panel-0.50.54/clique/config/clis.toml +299 -0
- clique_panel-0.50.54/clique/files.py +132 -0
- clique_panel-0.50.54/clique/gitinfo.py +200 -0
- clique_panel-0.50.54/clique/history.py +567 -0
- clique_panel-0.50.54/clique/migrate.py +84 -0
- clique_panel-0.50.54/clique/notify.py +310 -0
- clique_panel-0.50.54/clique/registry.py +427 -0
- clique_panel-0.50.54/clique/services.py +204 -0
- clique_panel-0.50.54/clique/store.py +696 -0
- clique_panel-0.50.54/clique/stream.py +185 -0
- clique_panel-0.50.54/clique/sysinfo.py +249 -0
- clique_panel-0.50.54/clique/termstrip.py +126 -0
- clique_panel-0.50.54/clique/tmux.py +562 -0
- clique_panel-0.50.54/clique/tokens.py +172 -0
- clique_panel-0.50.54/clique/web/app.css +1500 -0
- clique_panel-0.50.54/clique/web/app.js +6439 -0
- clique_panel-0.50.54/clique/web/brand/SOURCE.md +51 -0
- clique_panel-0.50.54/clique/web/brand/apple-touch-icon.png +0 -0
- clique_panel-0.50.54/clique/web/brand/favicon.ico +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-128.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-16.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-180.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-192.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-256.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-32.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-512.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-64.png +0 -0
- clique_panel-0.50.54/clique/web/brand/icon-maskable-512.png +0 -0
- clique_panel-0.50.54/clique/web/brand/lockup.svg +17 -0
- clique_panel-0.50.54/clique/web/brand/logo.svg +11 -0
- clique_panel-0.50.54/clique/web/brand/mark-mono.svg +4 -0
- clique_panel-0.50.54/clique/web/brand/mark.svg +10 -0
- clique_panel-0.50.54/clique/web/brand/social-preview.png +0 -0
- clique_panel-0.50.54/clique/web/icons/README.md +55 -0
- clique_panel-0.50.54/clique/web/icons/antigravity.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/claude.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/cline.png +0 -0
- clique_panel-0.50.54/clique/web/icons/codex.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/copilot.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/cursor.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/default.svg +4 -0
- clique_panel-0.50.54/clique/web/icons/droid.svg +6 -0
- clique_panel-0.50.54/clique/web/icons/gemini.svg +10 -0
- clique_panel-0.50.54/clique/web/icons/goose.svg +10 -0
- clique_panel-0.50.54/clique/web/icons/grok.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/ollama.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/opencode.svg +7 -0
- clique_panel-0.50.54/clique/web/icons/qwen.svg +1 -0
- clique_panel-0.50.54/clique/web/icons/shell.svg +1 -0
- clique_panel-0.50.54/clique/web/index.html +634 -0
- clique_panel-0.50.54/clique/web/manifest.webmanifest +21 -0
- clique_panel-0.50.54/clique/web/sw.js +18 -0
- clique_panel-0.50.54/clique/web/themes.js +157 -0
- clique_panel-0.50.54/clique/web/vendor/README.md +26 -0
- clique_panel-0.50.54/clique/web/vendor/addon-canvas.js +2 -0
- clique_panel-0.50.54/clique/web/vendor/addon-fit.js +2 -0
- clique_panel-0.50.54/clique/web/vendor/addon-unicode11.js +2 -0
- clique_panel-0.50.54/clique/web/vendor/xterm.LICENSE +21 -0
- clique_panel-0.50.54/clique/web/vendor/xterm.css +285 -0
- clique_panel-0.50.54/clique/web/vendor/xterm.js +2 -0
- clique_panel-0.50.54/clique/working.py +136 -0
- clique_panel-0.50.54/clique/workspace.py +205 -0
- clique_panel-0.50.54/clique/wsproto.py +230 -0
- clique_panel-0.50.54/clique_panel.egg-info/PKG-INFO +217 -0
- clique_panel-0.50.54/clique_panel.egg-info/SOURCES.txt +78 -0
- clique_panel-0.50.54/clique_panel.egg-info/dependency_links.txt +1 -0
- clique_panel-0.50.54/clique_panel.egg-info/entry_points.txt +2 -0
- clique_panel-0.50.54/clique_panel.egg-info/top_level.txt +1 -0
- clique_panel-0.50.54/pyproject.toml +88 -0
- clique_panel-0.50.54/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Justin Willhite
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clique-panel
|
|
3
|
+
Version: 0.50.54
|
|
4
|
+
Summary: Your private clique of CLIs. Folder-organised, CLI-agnostic coding sessions in a browser, persisted in tmux
|
|
5
|
+
Author: Justin Willhite
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Justin Willhite
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/thejdubb02/clique
|
|
29
|
+
Project-URL: Changelog, https://github.com/thejdubb02/clique/blob/main/CHANGELOG.md
|
|
30
|
+
Project-URL: Issues, https://github.com/thejdubb02/clique/issues
|
|
31
|
+
Project-URL: API, https://github.com/thejdubb02/clique/blob/main/API.md
|
|
32
|
+
Keywords: tmux,terminal,session-manager,web-terminal,coding-agents,claude-code,self-hosted,multi-agent
|
|
33
|
+
Classifier: Development Status :: 4 - Beta
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Classifier: Environment :: Web Environment
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
39
|
+
Classifier: Operating System :: MacOS
|
|
40
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Topic :: Software Development
|
|
43
|
+
Classifier: Topic :: Terminals :: Terminal Emulators/X Terminals
|
|
44
|
+
Classifier: Topic :: Utilities
|
|
45
|
+
Requires-Python: >=3.11
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
License-File: LICENSE
|
|
48
|
+
Dynamic: license-file
|
|
49
|
+
|
|
50
|
+
<p align="center">
|
|
51
|
+
<img src="clique/web/brand/social-preview.png" alt="CLIque: a folder for every CLI on the box" width="800">
|
|
52
|
+
</p>
|
|
53
|
+
|
|
54
|
+
<p align="center">
|
|
55
|
+
<strong>A folder for every CLI on the box. Coding sessions in the browser, kept alive in tmux.</strong><br>
|
|
56
|
+
Claude Code, Codex, Gemini, Grok, Antigravity, or anything you add in four lines of config.
|
|
57
|
+
</p>
|
|
58
|
+
|
|
59
|
+
<p align="center">
|
|
60
|
+
<a href="#quick-start"><img src="https://img.shields.io/badge/python-3.11%2B-3776AB?style=flat-square" alt="Python 3.11+"></a>
|
|
61
|
+
<a href="#why-it-is-stdlib-only"><img src="https://img.shields.io/badge/deps-none-22c55e?style=flat-square" alt="No dependencies"></a>
|
|
62
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-5FA8F5?style=flat-square" alt="MIT"></a>
|
|
63
|
+
<a href="https://github.com/thejdubb02/clique/actions/workflows/tests.yml"><img src="https://github.com/thejdubb02/clique/actions/workflows/tests.yml/badge.svg" alt="tests"></a>
|
|
64
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-0.50.54-A855F7?style=flat-square" alt="0.50.54"></a>
|
|
65
|
+
<a href="https://github.com/thejdubb02/clique/stargazers"><img src="https://img.shields.io/github/stars/thejdubb02/clique?style=flat-square" alt="GitHub stars"></a>
|
|
66
|
+
<a href="https://buymeacoffee.com/jdubb"><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-FFDD00?style=flat-square&logo=buymeacoffee&logoColor=black" alt="Buy me a coffee"></a>
|
|
67
|
+
<a href="#support-the-dev"><img src="https://img.shields.io/badge/Donate-BTC%20%7C%20SHIB%20%7C%20DOGE-5FA8F5?style=flat-square" alt="Donate"></a>
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
CLIque is a **driver, not an IDE**. It does not parse a vendor's protocol, impersonate a model, or reimplement the tools you already have. It keeps a private tmux server, puts every CLI session in a folder you can actually find, and gives you a browser to jump between them.
|
|
73
|
+
|
|
74
|
+
If you run more than two coding agents at once, you already know the problem: terminals everywhere, no idea which one is waiting on you, a conversation you cannot get back to. CLIque is the panel for that.
|
|
75
|
+
|
|
76
|
+
**24 MB resident.** No framework, no `node_modules`, no build step. `tmux`, a PTY, and the Python standard library.
|
|
77
|
+
|
|
78
|
+
## Who it's for
|
|
79
|
+
|
|
80
|
+
**Using one AI coding agent?** Claude Code, Codex, Cursor's CLI, Gemini, Grok, Antigravity — CLIque puts it in your browser. Kick off a task, close the laptop, and check on it from your phone on the couch. Nothing to babysit, nothing to install but Python and tmux.
|
|
81
|
+
|
|
82
|
+
**Running several at once?** You already know the problem: terminals everywhere, no idea which one is waiting on you, a conversation you cannot get back to. CLIque is the one screen in front of all of them — folders, a status ring on each, one click to jump, and a real phone notification when one wants you.
|
|
83
|
+
|
|
84
|
+
**Driving a fleet?** Run ten agents across ten repos, each in its own git worktree so they do not step on each other, reap the idle ones to reclaim memory and resume them later exactly where they left off, and script the whole thing over an HTTP API.
|
|
85
|
+
|
|
86
|
+
It is **not** an IDE, not another AI, and not a replacement for your CLIs — it is the control panel in front of the tools you already use. If you want the tool to *be* the agent, look elsewhere.
|
|
87
|
+
|
|
88
|
+
## What it does
|
|
89
|
+
|
|
90
|
+
| | |
|
|
91
|
+
|---|---|
|
|
92
|
+
| **Command palette** | `Ctrl`/`Cmd`+`K`: fuzzy jump between sessions, most-recently-used first. `>` commands, `@` sessions, `~` past conversations. |
|
|
93
|
+
| **History** | Every conversation your CLIs have kept, filed by directory, resumable in one click. Repeated runs of the same scheduled agent fold into one row. |
|
|
94
|
+
| **Resume & reap** | An idle tab has its process stopped after a few hours — ~700 MB freed for an idle Claude — and its tab greys out. Click it and it resumes exactly where it was. Ten open tabs cost what two do. |
|
|
95
|
+
| **Worktrees** | Start a session in its own git worktree, so several agents work the same repo at once without touching each other's files. Delete the session and the worktree goes too — unless it has uncommitted work. |
|
|
96
|
+
| **Conversation view** | A CLI that draws full-screen keeps no scrollback; **View conversation** reads its transcript back — your turns and the assistant's prose, tools and thinking left out — in a clean sheet. |
|
|
97
|
+
| **Agent-drivable** | A one-word `state` per session, a `wait`-until-done call, and a skill, so an agent can drive CLIque itself: fan one task across many repos and collect the results. |
|
|
98
|
+
| **Filter** | One button in the sidebar hides every stopped session — and any folder left empty by it — so a list of two dozen collapses to what is actually running. |
|
|
99
|
+
| **Folders** | A tree. Drag to reorder folders and sessions, or drop a session on a folder to file it. Double-click rename, right-click, search, collapse to a rail (`Ctrl`/`Cmd`+`B`). Each row names the git branch it is on, and how many files have changed. |
|
|
100
|
+
| **Tabs** | Drag to reorder, `Alt`+`1`–`9` to jump. Names shrink first; what still will not fit lands in **N more**, wearing the same working / waiting ring. Closing a tab is not killing the session. |
|
|
101
|
+
| **Terminal** | Live output, full scrollback on reattach, resize, auto-reconnect, themed to the panel. Drag to copy, even when the CLI wants the mouse. `Ctrl`/`Cmd`+`C` copies a selection and interrupts when there isn't one; `Ctrl`/`Cmd`+`Shift`+`C` copies the screen. |
|
|
102
|
+
| **Links** | URLs in the pane are clickable: a new tab, or a new window with `Ctrl`/`Cmd`. `http(s)` only. A URL that wrapped onto the next line is still one link. A file path opens a read-only look — copy it, or drop it into the prompt. |
|
|
103
|
+
| **Scroll lock** | Scroll up and the view detaches from the stream. A badge says how far behind you are; the bottom, the lock, or `Ctrl`/`Cmd`+`Shift`+`L` catches you up. |
|
|
104
|
+
| **Paste a screenshot** | `Ctrl`/`Cmd`+`V` saves the image into the session's own directory and drops the path where you were typing. Nothing is sent until you press enter. |
|
|
105
|
+
| **See what it made** | An agent writes a screenshot into the session's directory and a count appears in the tab bar. Grid, full size, and the path back into your prompt in one click. |
|
|
106
|
+
| **Prompt drafts** | A half-typed instruction survives a tab switch, a reload, and a closed laptop. Per session, on the server, so it follows you to another device. |
|
|
107
|
+
| **Workspace** | Open tabs, their order, the one in front, and which groups are collapsed live on the server. A reload attaches the tab you are looking at, then warms the rest in the background without resizing the pane. Sign in somewhere else and the strip is where you left it. |
|
|
108
|
+
| **Status** | A ring around the CLI's own logo: an arc turning means working, a steady pulse means finished and waiting for you, idle draws nothing. The logo is never recoloured. |
|
|
109
|
+
| **The box** | CPU, memory, disk and **VIEWS** in the bottom bar. Views is live connections on the box, not open tabs — hover if the number looks high; extras are another window or a phone. |
|
|
110
|
+
| **Waiting on you** | Three tiers: tmux's clock, regexes you declare per CLI, and a `POST .../attention` a session fires from your own hook. Nothing here knows which vendor is talking. |
|
|
111
|
+
| **Unread** | A dot on anything that produced output while you were elsewhere, and a rule in the pane where you stopped reading. |
|
|
112
|
+
| **Which CLI** | The pane edge, the active tab and the prompt box carry the CLI's colour, so switching tabs tells you where you are typing. Colours editable per CLI. |
|
|
113
|
+
| **Themes** | Nine presets, light / dark / system, custom CSS in three slots, independent font sizes, a monospace picker that falls back on every OS. |
|
|
114
|
+
| **API** | Every action in the panel is an HTTP call, with bearer tokens and read-only ones. Full reference in [API.md](API.md), kept honest by a drift check in the test suite. |
|
|
115
|
+
| **Changelog** | Settings → Changelog: the last few releases, with a link to the rest on GitHub. After an upgrade, **What's new** sits on the bottom bar and goes straight there. |
|
|
116
|
+
| **Told, not checked** | One webhook URL, POSTed when a session wants you, errors, finishes or dies. ntfy, Gotify, Discord, Mattermost and Uptime Kuma push all speak it. Real phone notifications, no app of ours. |
|
|
117
|
+
| **Monitoring** | `GET /healthz` answers without a login. Point Uptime Kuma, Gatus or Healthchecks at it. Anonymously it says `{"ok": true}` and nothing else. |
|
|
118
|
+
| **Security** | Password login (scrypt), API tokens, CSRF, `Origin` and `Host` checks, CSP with per-response nonces. See [SECURITY.md](SECURITY.md). |
|
|
119
|
+
| **Touch** | Long press a session for the menu right-click gives, with tap targets sized for a finger. |
|
|
120
|
+
| **Phone & PWA** | Install it as its own app — no tabs, no URL bar, full screen from the bottom bar. Built for a phone browser too: a drawer sidebar, a full-width pane, an on-screen row for the keys a terminal needs (Esc, Tab, Ctrl+C, arrows), and a wheel that scrolls a full-screen CLI's own view. |
|
|
121
|
+
|
|
122
|
+
Not built, on purpose: subagent visualisation, a respawn controller, multi-host, a Ralph loop. Those need to know which vendor is talking. This product does not.
|
|
123
|
+
|
|
124
|
+
What is next, and why that order: [ROADMAP.md](ROADMAP.md). What shipped: [CHANGELOG.md](CHANGELOG.md).
|
|
125
|
+
|
|
126
|
+
## Quick start
|
|
127
|
+
|
|
128
|
+
Needs **Python 3.11+** and **tmux**. Nothing else.
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git clone https://github.com/thejdubb02/clique.git
|
|
132
|
+
cd clique
|
|
133
|
+
python3 -m clique password # prompted; stored as an scrypt hash
|
|
134
|
+
python3 -m clique # http://127.0.0.1:3200
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
State lives in `$CLIQUE_HOME`, default `~/.clique`. To edit the CLI catalogue,
|
|
138
|
+
`python3 -m clique config` drops one where your edits survive an upgrade.
|
|
139
|
+
|
|
140
|
+
Once it is on PyPI, `pip install clique-panel` gives you a `clique` command
|
|
141
|
+
(the package is `clique-panel` because `clique` there is an unrelated library).
|
|
142
|
+
|
|
143
|
+
It binds to loopback on purpose. Put a tunnel in front of it (Tailscale Serve, Caddy, nginx) if you want it from another machine. Do not bind it to the public internet. Anyone who reaches the panel has a terminal as the user that started it.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
# optional: behind Tailscale
|
|
147
|
+
tailscale serve --bg --set-path /clique http://127.0.0.1:3200
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
A systemd user unit is in [`deploy/`](deploy/README.md).
|
|
151
|
+
|
|
152
|
+
`GET /healthz` answers without a login (`{"ok":true}` and nothing else), so Uptime Kuma, Gatus or Healthchecks can watch it.
|
|
153
|
+
|
|
154
|
+
## Adding a CLI
|
|
155
|
+
|
|
156
|
+
A block in [`clique/config/clis.toml`](clique/config/clis.toml). Reload the page. No restart, no code:
|
|
157
|
+
|
|
158
|
+
```toml
|
|
159
|
+
[cli.grok]
|
|
160
|
+
label = "Grok CLI"
|
|
161
|
+
command = "grok"
|
|
162
|
+
args = []
|
|
163
|
+
color = "#6f42c1"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
There is no per-CLI branch in the codebase. If adding one ever needs a code change, the design has failed.
|
|
167
|
+
|
|
168
|
+
Claude Code and Gemini CLI can also declare an **autonomy pill** (the mode above the prompt). That is four keys in the same block (`modes`, `mode_key`, `mode_label`), documented in the comments of `clis.toml`. Omit them and the pill stays hidden, which is the right default for a CLI whose approval is a launch flag.
|
|
169
|
+
|
|
170
|
+
## Why it is stdlib-only
|
|
171
|
+
|
|
172
|
+
A coding-agent session already costs hundreds of megabytes. The manager's job is to disappear into that budget. Measured: **24 MB resident**.
|
|
173
|
+
|
|
174
|
+
That also means the real ceiling on concurrent sessions is the agents, not this. On a 16 GB box with ~9 GB free, roughly a dozen at once.
|
|
175
|
+
|
|
176
|
+
## Design notes that are easy to get wrong
|
|
177
|
+
|
|
178
|
+
- **Own tmux server** (`tmux -L clique`). Isolated from everything else on the box.
|
|
179
|
+
- **A PTY exists only while a browser is attached.** An idle session costs this process nothing; cost scales with open tabs, not with session count.
|
|
180
|
+
- **Each viewer gets its own grouped tmux session.** Plain `attach` makes every client share one size, so tmux shrinks the pane to the smallest watcher.
|
|
181
|
+
- **Closing a tab is not killing a session.** Detach sends SIGHUP; tmux and the CLI carry on.
|
|
182
|
+
- **`kill()` refuses sessions that are not ours** unless forced.
|
|
183
|
+
|
|
184
|
+
## Tests
|
|
185
|
+
|
|
186
|
+
Neither suite is mocked. The failure modes worth catching (tmux quoting, a PTY that never gets its first byte) only exist across a real socket. GitHub Actions runs all three on every push. They start their own panel and tmux server, so they cannot touch the one you are using.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python3 tools/smoke.py # engine, against a real tmux server
|
|
190
|
+
python3 tools/smoke_http.py # server, over real HTTP + WebSocket
|
|
191
|
+
python3 tools/api_drift.py # API.md still covers every route and setting
|
|
192
|
+
ruff check .
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
They will not catch a UI that renders wrong. Open the page for that.
|
|
196
|
+
|
|
197
|
+
## Contributing
|
|
198
|
+
|
|
199
|
+
Patches welcome, with a short filter: [CONTRIBUTING.md](CONTRIBUTING.md). Feature ideas that need to know which vendor is talking get refused. That is the product, not a freeze.
|
|
200
|
+
|
|
201
|
+
## Support the dev
|
|
202
|
+
|
|
203
|
+
Free, and staying that way. If it saved you an afternoon, this is the tip jar.
|
|
204
|
+
|
|
205
|
+
**[Buy me a coffee](https://buymeacoffee.com/jdubb)**
|
|
206
|
+
|
|
207
|
+
| | Network | Address |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| **BTC** | Bitcoin | `3A3nA8BQFmXdvyUQokHhPd8HAd99wRDYFQ` |
|
|
210
|
+
| **SHIB** | Ethereum | `0x6b5DEd92946692D50642dC3af169727225E32D3b` |
|
|
211
|
+
| **DOGE** | Dogecoin | `DNiJeUJUVaVTDuteLXCtP7JVgvdL2NqoYp` |
|
|
212
|
+
|
|
213
|
+
## License
|
|
214
|
+
|
|
215
|
+
[MIT](LICENSE). Built by [Justin Willhite](https://github.com/thejdubb02).
|
|
216
|
+
|
|
217
|
+
A hole that reaches a terminal is a [private advisory](https://github.com/thejdubb02/clique/security/advisories/new), not a public issue. See [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="clique/web/brand/social-preview.png" alt="CLIque: a folder for every CLI on the box" width="800">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<strong>A folder for every CLI on the box. Coding sessions in the browser, kept alive in tmux.</strong><br>
|
|
7
|
+
Claude Code, Codex, Gemini, Grok, Antigravity, or anything you add in four lines of config.
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="#quick-start"><img src="https://img.shields.io/badge/python-3.11%2B-3776AB?style=flat-square" alt="Python 3.11+"></a>
|
|
12
|
+
<a href="#why-it-is-stdlib-only"><img src="https://img.shields.io/badge/deps-none-22c55e?style=flat-square" alt="No dependencies"></a>
|
|
13
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-5FA8F5?style=flat-square" alt="MIT"></a>
|
|
14
|
+
<a href="https://github.com/thejdubb02/clique/actions/workflows/tests.yml"><img src="https://github.com/thejdubb02/clique/actions/workflows/tests.yml/badge.svg" alt="tests"></a>
|
|
15
|
+
<a href="CHANGELOG.md"><img src="https://img.shields.io/badge/version-0.50.54-A855F7?style=flat-square" alt="0.50.54"></a>
|
|
16
|
+
<a href="https://github.com/thejdubb02/clique/stargazers"><img src="https://img.shields.io/github/stars/thejdubb02/clique?style=flat-square" alt="GitHub stars"></a>
|
|
17
|
+
<a href="https://buymeacoffee.com/jdubb"><img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-FFDD00?style=flat-square&logo=buymeacoffee&logoColor=black" alt="Buy me a coffee"></a>
|
|
18
|
+
<a href="#support-the-dev"><img src="https://img.shields.io/badge/Donate-BTC%20%7C%20SHIB%20%7C%20DOGE-5FA8F5?style=flat-square" alt="Donate"></a>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
CLIque is a **driver, not an IDE**. It does not parse a vendor's protocol, impersonate a model, or reimplement the tools you already have. It keeps a private tmux server, puts every CLI session in a folder you can actually find, and gives you a browser to jump between them.
|
|
24
|
+
|
|
25
|
+
If you run more than two coding agents at once, you already know the problem: terminals everywhere, no idea which one is waiting on you, a conversation you cannot get back to. CLIque is the panel for that.
|
|
26
|
+
|
|
27
|
+
**24 MB resident.** No framework, no `node_modules`, no build step. `tmux`, a PTY, and the Python standard library.
|
|
28
|
+
|
|
29
|
+
## Who it's for
|
|
30
|
+
|
|
31
|
+
**Using one AI coding agent?** Claude Code, Codex, Cursor's CLI, Gemini, Grok, Antigravity — CLIque puts it in your browser. Kick off a task, close the laptop, and check on it from your phone on the couch. Nothing to babysit, nothing to install but Python and tmux.
|
|
32
|
+
|
|
33
|
+
**Running several at once?** You already know the problem: terminals everywhere, no idea which one is waiting on you, a conversation you cannot get back to. CLIque is the one screen in front of all of them — folders, a status ring on each, one click to jump, and a real phone notification when one wants you.
|
|
34
|
+
|
|
35
|
+
**Driving a fleet?** Run ten agents across ten repos, each in its own git worktree so they do not step on each other, reap the idle ones to reclaim memory and resume them later exactly where they left off, and script the whole thing over an HTTP API.
|
|
36
|
+
|
|
37
|
+
It is **not** an IDE, not another AI, and not a replacement for your CLIs — it is the control panel in front of the tools you already use. If you want the tool to *be* the agent, look elsewhere.
|
|
38
|
+
|
|
39
|
+
## What it does
|
|
40
|
+
|
|
41
|
+
| | |
|
|
42
|
+
|---|---|
|
|
43
|
+
| **Command palette** | `Ctrl`/`Cmd`+`K`: fuzzy jump between sessions, most-recently-used first. `>` commands, `@` sessions, `~` past conversations. |
|
|
44
|
+
| **History** | Every conversation your CLIs have kept, filed by directory, resumable in one click. Repeated runs of the same scheduled agent fold into one row. |
|
|
45
|
+
| **Resume & reap** | An idle tab has its process stopped after a few hours — ~700 MB freed for an idle Claude — and its tab greys out. Click it and it resumes exactly where it was. Ten open tabs cost what two do. |
|
|
46
|
+
| **Worktrees** | Start a session in its own git worktree, so several agents work the same repo at once without touching each other's files. Delete the session and the worktree goes too — unless it has uncommitted work. |
|
|
47
|
+
| **Conversation view** | A CLI that draws full-screen keeps no scrollback; **View conversation** reads its transcript back — your turns and the assistant's prose, tools and thinking left out — in a clean sheet. |
|
|
48
|
+
| **Agent-drivable** | A one-word `state` per session, a `wait`-until-done call, and a skill, so an agent can drive CLIque itself: fan one task across many repos and collect the results. |
|
|
49
|
+
| **Filter** | One button in the sidebar hides every stopped session — and any folder left empty by it — so a list of two dozen collapses to what is actually running. |
|
|
50
|
+
| **Folders** | A tree. Drag to reorder folders and sessions, or drop a session on a folder to file it. Double-click rename, right-click, search, collapse to a rail (`Ctrl`/`Cmd`+`B`). Each row names the git branch it is on, and how many files have changed. |
|
|
51
|
+
| **Tabs** | Drag to reorder, `Alt`+`1`–`9` to jump. Names shrink first; what still will not fit lands in **N more**, wearing the same working / waiting ring. Closing a tab is not killing the session. |
|
|
52
|
+
| **Terminal** | Live output, full scrollback on reattach, resize, auto-reconnect, themed to the panel. Drag to copy, even when the CLI wants the mouse. `Ctrl`/`Cmd`+`C` copies a selection and interrupts when there isn't one; `Ctrl`/`Cmd`+`Shift`+`C` copies the screen. |
|
|
53
|
+
| **Links** | URLs in the pane are clickable: a new tab, or a new window with `Ctrl`/`Cmd`. `http(s)` only. A URL that wrapped onto the next line is still one link. A file path opens a read-only look — copy it, or drop it into the prompt. |
|
|
54
|
+
| **Scroll lock** | Scroll up and the view detaches from the stream. A badge says how far behind you are; the bottom, the lock, or `Ctrl`/`Cmd`+`Shift`+`L` catches you up. |
|
|
55
|
+
| **Paste a screenshot** | `Ctrl`/`Cmd`+`V` saves the image into the session's own directory and drops the path where you were typing. Nothing is sent until you press enter. |
|
|
56
|
+
| **See what it made** | An agent writes a screenshot into the session's directory and a count appears in the tab bar. Grid, full size, and the path back into your prompt in one click. |
|
|
57
|
+
| **Prompt drafts** | A half-typed instruction survives a tab switch, a reload, and a closed laptop. Per session, on the server, so it follows you to another device. |
|
|
58
|
+
| **Workspace** | Open tabs, their order, the one in front, and which groups are collapsed live on the server. A reload attaches the tab you are looking at, then warms the rest in the background without resizing the pane. Sign in somewhere else and the strip is where you left it. |
|
|
59
|
+
| **Status** | A ring around the CLI's own logo: an arc turning means working, a steady pulse means finished and waiting for you, idle draws nothing. The logo is never recoloured. |
|
|
60
|
+
| **The box** | CPU, memory, disk and **VIEWS** in the bottom bar. Views is live connections on the box, not open tabs — hover if the number looks high; extras are another window or a phone. |
|
|
61
|
+
| **Waiting on you** | Three tiers: tmux's clock, regexes you declare per CLI, and a `POST .../attention` a session fires from your own hook. Nothing here knows which vendor is talking. |
|
|
62
|
+
| **Unread** | A dot on anything that produced output while you were elsewhere, and a rule in the pane where you stopped reading. |
|
|
63
|
+
| **Which CLI** | The pane edge, the active tab and the prompt box carry the CLI's colour, so switching tabs tells you where you are typing. Colours editable per CLI. |
|
|
64
|
+
| **Themes** | Nine presets, light / dark / system, custom CSS in three slots, independent font sizes, a monospace picker that falls back on every OS. |
|
|
65
|
+
| **API** | Every action in the panel is an HTTP call, with bearer tokens and read-only ones. Full reference in [API.md](API.md), kept honest by a drift check in the test suite. |
|
|
66
|
+
| **Changelog** | Settings → Changelog: the last few releases, with a link to the rest on GitHub. After an upgrade, **What's new** sits on the bottom bar and goes straight there. |
|
|
67
|
+
| **Told, not checked** | One webhook URL, POSTed when a session wants you, errors, finishes or dies. ntfy, Gotify, Discord, Mattermost and Uptime Kuma push all speak it. Real phone notifications, no app of ours. |
|
|
68
|
+
| **Monitoring** | `GET /healthz` answers without a login. Point Uptime Kuma, Gatus or Healthchecks at it. Anonymously it says `{"ok": true}` and nothing else. |
|
|
69
|
+
| **Security** | Password login (scrypt), API tokens, CSRF, `Origin` and `Host` checks, CSP with per-response nonces. See [SECURITY.md](SECURITY.md). |
|
|
70
|
+
| **Touch** | Long press a session for the menu right-click gives, with tap targets sized for a finger. |
|
|
71
|
+
| **Phone & PWA** | Install it as its own app — no tabs, no URL bar, full screen from the bottom bar. Built for a phone browser too: a drawer sidebar, a full-width pane, an on-screen row for the keys a terminal needs (Esc, Tab, Ctrl+C, arrows), and a wheel that scrolls a full-screen CLI's own view. |
|
|
72
|
+
|
|
73
|
+
Not built, on purpose: subagent visualisation, a respawn controller, multi-host, a Ralph loop. Those need to know which vendor is talking. This product does not.
|
|
74
|
+
|
|
75
|
+
What is next, and why that order: [ROADMAP.md](ROADMAP.md). What shipped: [CHANGELOG.md](CHANGELOG.md).
|
|
76
|
+
|
|
77
|
+
## Quick start
|
|
78
|
+
|
|
79
|
+
Needs **Python 3.11+** and **tmux**. Nothing else.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git clone https://github.com/thejdubb02/clique.git
|
|
83
|
+
cd clique
|
|
84
|
+
python3 -m clique password # prompted; stored as an scrypt hash
|
|
85
|
+
python3 -m clique # http://127.0.0.1:3200
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
State lives in `$CLIQUE_HOME`, default `~/.clique`. To edit the CLI catalogue,
|
|
89
|
+
`python3 -m clique config` drops one where your edits survive an upgrade.
|
|
90
|
+
|
|
91
|
+
Once it is on PyPI, `pip install clique-panel` gives you a `clique` command
|
|
92
|
+
(the package is `clique-panel` because `clique` there is an unrelated library).
|
|
93
|
+
|
|
94
|
+
It binds to loopback on purpose. Put a tunnel in front of it (Tailscale Serve, Caddy, nginx) if you want it from another machine. Do not bind it to the public internet. Anyone who reaches the panel has a terminal as the user that started it.
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# optional: behind Tailscale
|
|
98
|
+
tailscale serve --bg --set-path /clique http://127.0.0.1:3200
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
A systemd user unit is in [`deploy/`](deploy/README.md).
|
|
102
|
+
|
|
103
|
+
`GET /healthz` answers without a login (`{"ok":true}` and nothing else), so Uptime Kuma, Gatus or Healthchecks can watch it.
|
|
104
|
+
|
|
105
|
+
## Adding a CLI
|
|
106
|
+
|
|
107
|
+
A block in [`clique/config/clis.toml`](clique/config/clis.toml). Reload the page. No restart, no code:
|
|
108
|
+
|
|
109
|
+
```toml
|
|
110
|
+
[cli.grok]
|
|
111
|
+
label = "Grok CLI"
|
|
112
|
+
command = "grok"
|
|
113
|
+
args = []
|
|
114
|
+
color = "#6f42c1"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
There is no per-CLI branch in the codebase. If adding one ever needs a code change, the design has failed.
|
|
118
|
+
|
|
119
|
+
Claude Code and Gemini CLI can also declare an **autonomy pill** (the mode above the prompt). That is four keys in the same block (`modes`, `mode_key`, `mode_label`), documented in the comments of `clis.toml`. Omit them and the pill stays hidden, which is the right default for a CLI whose approval is a launch flag.
|
|
120
|
+
|
|
121
|
+
## Why it is stdlib-only
|
|
122
|
+
|
|
123
|
+
A coding-agent session already costs hundreds of megabytes. The manager's job is to disappear into that budget. Measured: **24 MB resident**.
|
|
124
|
+
|
|
125
|
+
That also means the real ceiling on concurrent sessions is the agents, not this. On a 16 GB box with ~9 GB free, roughly a dozen at once.
|
|
126
|
+
|
|
127
|
+
## Design notes that are easy to get wrong
|
|
128
|
+
|
|
129
|
+
- **Own tmux server** (`tmux -L clique`). Isolated from everything else on the box.
|
|
130
|
+
- **A PTY exists only while a browser is attached.** An idle session costs this process nothing; cost scales with open tabs, not with session count.
|
|
131
|
+
- **Each viewer gets its own grouped tmux session.** Plain `attach` makes every client share one size, so tmux shrinks the pane to the smallest watcher.
|
|
132
|
+
- **Closing a tab is not killing a session.** Detach sends SIGHUP; tmux and the CLI carry on.
|
|
133
|
+
- **`kill()` refuses sessions that are not ours** unless forced.
|
|
134
|
+
|
|
135
|
+
## Tests
|
|
136
|
+
|
|
137
|
+
Neither suite is mocked. The failure modes worth catching (tmux quoting, a PTY that never gets its first byte) only exist across a real socket. GitHub Actions runs all three on every push. They start their own panel and tmux server, so they cannot touch the one you are using.
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
python3 tools/smoke.py # engine, against a real tmux server
|
|
141
|
+
python3 tools/smoke_http.py # server, over real HTTP + WebSocket
|
|
142
|
+
python3 tools/api_drift.py # API.md still covers every route and setting
|
|
143
|
+
ruff check .
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
They will not catch a UI that renders wrong. Open the page for that.
|
|
147
|
+
|
|
148
|
+
## Contributing
|
|
149
|
+
|
|
150
|
+
Patches welcome, with a short filter: [CONTRIBUTING.md](CONTRIBUTING.md). Feature ideas that need to know which vendor is talking get refused. That is the product, not a freeze.
|
|
151
|
+
|
|
152
|
+
## Support the dev
|
|
153
|
+
|
|
154
|
+
Free, and staying that way. If it saved you an afternoon, this is the tip jar.
|
|
155
|
+
|
|
156
|
+
**[Buy me a coffee](https://buymeacoffee.com/jdubb)**
|
|
157
|
+
|
|
158
|
+
| | Network | Address |
|
|
159
|
+
|---|---|---|
|
|
160
|
+
| **BTC** | Bitcoin | `3A3nA8BQFmXdvyUQokHhPd8HAd99wRDYFQ` |
|
|
161
|
+
| **SHIB** | Ethereum | `0x6b5DEd92946692D50642dC3af169727225E32D3b` |
|
|
162
|
+
| **DOGE** | Dogecoin | `DNiJeUJUVaVTDuteLXCtP7JVgvdL2NqoYp` |
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
[MIT](LICENSE). Built by [Justin Willhite](https://github.com/thejdubb02).
|
|
167
|
+
|
|
168
|
+
A hole that reaches a terminal is a [private advisory](https://github.com/thejdubb02/clique/security/advisories/new), not a public issue. See [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""CLIque — Your private clique of CLIs.
|
|
2
|
+
|
|
3
|
+
Folder-organised, CLI-agnostic terminal sessions in a browser, kept alive in tmux.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import subprocess
|
|
9
|
+
from functools import lru_cache
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
#: Semver, bumped with every release-worthy change and shown in the sidebar.
|
|
13
|
+
#: Minor for features, patch for fixes. The version alone is not enough to
|
|
14
|
+
#: identify a build during active development, which is what build_id is for.
|
|
15
|
+
__version__ = "0.50.54"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@lru_cache(maxsize=1)
|
|
19
|
+
def build_id() -> str:
|
|
20
|
+
"""Short commit of the working tree, or "" outside a checkout.
|
|
21
|
+
|
|
22
|
+
A bug report that says "0.2.0" during a week of daily commits names a
|
|
23
|
+
range, not a build. This makes it name a commit.
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
result = subprocess.run(
|
|
27
|
+
["git", "-C", str(Path(__file__).resolve().parents[1]),
|
|
28
|
+
"rev-parse", "--short", "HEAD"],
|
|
29
|
+
capture_output=True, text=True, timeout=5,
|
|
30
|
+
)
|
|
31
|
+
if result.returncode == 0:
|
|
32
|
+
return result.stdout.strip()
|
|
33
|
+
except (OSError, subprocess.SubprocessError):
|
|
34
|
+
pass
|
|
35
|
+
return ""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def version_string() -> str:
|
|
39
|
+
build = build_id()
|
|
40
|
+
return f"{__version__}+{build}" if build else __version__
|