claudecord 0.2.2__py3-none-win_amd64.whl

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.
@@ -0,0 +1,271 @@
1
+ Metadata-Version: 2.4
2
+ Name: claudecord
3
+ Version: 0.2.2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Operating System :: POSIX :: Linux
6
+ Classifier: Operating System :: MacOS
7
+ Classifier: Operating System :: Microsoft :: Windows
8
+ Summary: Run Claude Code, agy and Codex agents on any machine as a Discord team
9
+ Keywords: claude,codex,agents,discord,tmux,orchestrator
10
+ License: MIT
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
13
+ Project-URL: Repository, https://github.com/kanavdhanda/claudeCord
14
+
15
+ # claudeCord
16
+
17
+ Run coding agents on any machines and manage them from a group chat.
18
+
19
+ You put Claude Code, Codex or agy to work in a folder. Each agent shows up in a Discord channel under its own name, talks to
20
+ the other agents like a teammate, and asks you when it is stuck. You answer in Discord. Nothing about it depends on which agent
21
+ program is behind a name.
22
+
23
+ ## How it works, in plain words
24
+
25
+ - A **hub** is one small program on a server you control. It knows who is on the team, who may do what, and where every message
26
+ goes. It keeps a record of the conversation.
27
+ - A **daemon** runs on each machine that has agents. It starts the agents in terminals it owns, types messages into them at a
28
+ safe moment (never over a half-typed line), and tells the hub what they are doing. Machines only ever dial out, so no ports
29
+ are opened and it works behind a home router, a company firewall or a web proxy.
30
+ - **Discord** is where people watch and steer. Each project is a channel, each task a thread, each agent a name. Questions and
31
+ permission requests arrive with buttons.
32
+ - Agents talk back by running short shell commands (`claudecord say`, `ask`, `done`, ...). There are no tools to load into the
33
+ agent, so they cost almost nothing.
34
+
35
+ ```
36
+ people <-> Discord <-> hub <-> machine daemons <-> agents in terminals
37
+ |
38
+ history, roles, saved state (SQLite) and old history in a bucket
39
+ ```
40
+
41
+ ## Try it
42
+
43
+ claudeCord is a hosted service: you sign in on its website with Discord, add your own Discord bot there, and connect your machines.
44
+ You do not run a server unless you want to (see "Run your own" below).
45
+
46
+ 1. **Install** with `pip install claudecord` or `npm install -g claudecord` (no compiler needed; Linux, macOS and Windows), or `cargo install`.
47
+ 2. **Run `claudecord`** (or `npx claudecord`) on a machine. The first time, it opens your browser: sign in with Discord and approve the machine.
48
+ 3. **Add a project** on the dashboard. A wizard takes you through it: save a Discord bot token (checked with Discord, stored encrypted, never shown
49
+ again), pick a server and a channel (or make a new one), and name the project and its first agent. One bot can serve any number of servers.
50
+ 4. **Start an agent** in a project folder with the command the wizard shows, for example `claudecord start --project myproject`.
51
+ A channel in Discord now carries the agent, which posts under its own name. Type there and the agent hears you. Leave with the usual tmux
52
+ detach (Ctrl-b d); the agent keeps running. `claudecord attach NAME` returns to it. Where tmux is not installed (native Windows) a built-in
53
+ terminal is used instead, and Ctrl-] leaves it.
54
+
55
+ The dashboard shows machines, agents, what is waiting on a person, and how the team behaves: who talks to whom, each agent's state over time,
56
+ how tasks and questions flow, and what the turns cost. Spawning another agent is a button there too. It does not show chats (those live in
57
+ Discord threads).
58
+
59
+ ### Run your own
60
+
61
+ claudecord serve --data claudecord-data --public-url https://claudecord.example.com --client-id DISCORD_APP_ID --secret-file secret.txt
62
+
63
+ With Docker (built on the server itself, nothing is pulled from a registry): `deploy/compose.yml` has the steps; put nginx or Caddy in front for TLS. `deploy/baremetal/bootstrap.sh` does it without Docker on a fresh Ubuntu or Debian machine (service, TLS, firewall). The Discord application given here only signs people
64
+ in; their bots are saved on the dashboard, encrypted with a key the program makes in the data folder (**back up the file `kek`**). To try everything
65
+ on your own computer with no Discord at all: `claudecord serve --dev --public-url http://127.0.0.1:8787`, then `cd web && npm run dev`.
66
+
67
+ The older single-team mode still exists for one team on one server: `claudecord hub`, `claudecord discord set`, `claudecord token`.
68
+
69
+ `claudecord start` does exactly what you ask and nothing more. Every extra is a flag you choose:
70
+
71
+ | Flag | Does |
72
+ |---|---|
73
+ | `--worktree` | gives the agent its own git worktree and branch (without it, a second agent in a busy folder is refused) |
74
+ | `--pickup` | hands over the state the previous session saved |
75
+ | `--restart N` | starts the agent again up to N times if it dies (default: never) |
76
+ | `-- COMMAND...` | runs that program instead of the adapter's default |
77
+
78
+ Start-up dialogs (such as a trust question) are never answered for you: they reach the chat as a permission request.
79
+
80
+ ## Agents cannot act as each other
81
+
82
+ Each agent is started with its own secret key and works in its own folder. Its commands (`say`, `ask`, `done`, ...) are
83
+ checked against that key by the daemon, so an agent cannot speak, ask or finish a task as another agent. This stops mistakes
84
+ and confusion, not a hostile program running as the same user: such a program could read another agent's folder, and agents
85
+ share one private tmux server, so an agent that runs `tmux` itself can reach other agents' sessions.
86
+
87
+ ## Logs and handoff
88
+
89
+ Everything an agent does is written to a private log with secrets removed: an event log (messages delivered, said, asked,
90
+ decisions, start, end) and a copy of its terminal.
91
+
92
+ claudecord logs otter # recent events
93
+ claudecord logs otter --terminal # recent terminal text, control codes removed
94
+ claudecord handoff otter # writes a markdown note of what happened, for the next session or person
95
+
96
+ ## Who can do what
97
+
98
+ People are known by their Discord account, never by what a message says. Each project has three roles:
99
+
100
+ | Role | May |
101
+ |---|---|
102
+ | viewer | read everything |
103
+ | operator | instruct agents, answer questions, allow normal actions once, stop or pause an agent |
104
+ | owner | everything, including standing permissions, roles, stopping everything, starting agents, raw terminal input |
105
+
106
+ Anyone not on the list is ignored. Agents can ask and request but never approve anything. Messages from bots and webhooks (which
107
+ includes every agent's own posts) are never treated as a person.
108
+
109
+ ## Slash commands in Discord
110
+
111
+ `/agents` `/devices` `/status` `/pause` `/resume` `/stop` `/killall` `/btw` `/grant` `/revoke` `/role` `/dump` `/pickup` `/raw`
112
+ `/spawn`. Roles are checked by the hub for each one.
113
+
114
+ ## Permissions
115
+
116
+ When an agent wants to do something that needs a person, a message appears with buttons: Deny, Allow once, Allow this kind, Allow
117
+ all. Normal actions can be allowed by an operator; risky ones (leaving the project, installing, pushing, unknown hosts) need an
118
+ owner. "This kind" and "all" are standing permissions: only an owner can give them, and every one expires (an hour by default;
119
+ `/grant` sets another time). Files that should never be touched (keys, credentials, claudeCord's own settings) are refused
120
+ without asking, whatever has been allowed. Answering at the terminal instead also works, and the Discord message is closed.
121
+
122
+ ## Slash and at-sign in messages
123
+
124
+ Agent programs treat some characters specially (a leading `/` for commands, `@` for files or plugins). claudeCord stays out of
125
+ that: **every ordinary message is delivered as data behind a header** such as `[kd (owner)] /clear`, so the first character the
126
+ agent program sees is never `/` or `@`, and nothing a person types in chat can run a command by accident. To send a command on
127
+ purpose, an owner uses `/raw agent:otter text:/compact`, which types exactly that text with no header. The hub knows nothing
128
+ about what any command means, so it works the same for every agent program. Every use is recorded.
129
+
130
+ ## Dashboard
131
+
132
+ A React app (source in `web/`, the build is committed in `web/dist` and embedded in the program, so `cargo install` needs no Node). Pages: Overview,
133
+ Add a project (the wizard, also how a new place is chosen), Discord bots, Machines, Insights. After changing `web/`, run `npm run build` in it.
134
+ Everything is scoped to the signed-in account; nobody sees another account's machines, bots, history or numbers.
135
+
136
+ ## What is guaranteed about messages
137
+
138
+ Nothing is acknowledged before it is on disk. Each batch of changes (the history rows and what changed in the saved state) is written to the
139
+ database as one transaction, and only then are frames sent, chat posts made, reactions added or callers answered. So a message that was
140
+ acknowledged survives a crash, and the saved state and the history always agree. This is tested by killing the real hub with SIGKILL at random
141
+ moments while messages flow.
142
+
143
+ - **Machine to hub:** every frame is numbered, acknowledged only once saved, kept by the machine until then (even while the hub is away) and sent
144
+ again after a reconnect. The hub takes each numbered frame once, also across its own restarts.
145
+ - **Discord to hub:** the hub remembers the newest message taken from each channel, saved in the same commit as the message, so a message read
146
+ twice (a resumed connection, a restart) is taken once. After a fresh connection the bridge reads back what was said while it was away, oldest first.
147
+ - **Hub to agent:** waiting messages are part of the saved state and are delivered again after a restart; the machine drops a message it already
148
+ has by its id (at-least-once, effectively once).
149
+
150
+ What is not covered: if the machine's own program restarts, frames it had not yet had acknowledged are lost with it; answers, permission decisions
151
+ and files the hub sends to a machine that is away are not queued for it; a post to Discord can be lost if the hub is killed between saving a message
152
+ and posting it (the history has it); and a disk that fails leaves the hub carrying on without durability, which it logs loudly.
153
+
154
+ ## Logs and what survives what
155
+
156
+ The hub writes one line per event to the terminal and to `hub.log` in its data folder (kept to about 20 MB in two files; read it with
157
+ `tail -f`, or `journalctl -u claudecord-hub` under systemd). The machine daemon logs to `daemon.log` in `~/.claudecord`, and each agent has
158
+ its own event and terminal logs (`claudecord logs`). Set `CLAUDECORD_LOG=debug` for more, or `error` for less. Every line is scrubbed of
159
+ secrets, and a panic anywhere is logged with where it happened.
160
+
161
+ What each part does when something goes wrong: a bug while handling one device's frame, one command or one terminal costs only that step,
162
+ is logged, and the hub or daemon carries on; the Discord bridge restarts itself if it panics, and keeps retrying if Discord is down at start-up;
163
+ a bug caught inside the hub is reported to the affected projects' chats (owner pinged) before anything else; each agent on a machine is looked at on its own, so one agent's fault is reported and the others carry on, and one that keeps failing is stopped and reported; a device that misbehaves or stops reading is cut off with the reason in the log, and nobody else notices; a normal stop (Ctrl-C, or SIGTERM from
164
+ `systemctl stop` or Docker) saves everything and is recorded as a stop, while a kill is counted as downtime from the last heartbeat.
165
+
166
+ The log can also be read over HTTP, `GET /api/v1/logs?lines=200&level=warn&q=text` (a dashboard token or a signed-in workspace owner; the dashboard
167
+ shows it as a panel for them), and the hub is set up for systemd to restart it if its core hangs, not only if it dies (`deploy/baremetal/claudecord-hub.service`:
168
+ never gives up restarting, `Type=notify` with a watchdog); the Docker image has a health check. Database backups to the bucket run hourly.
169
+
170
+ Failures are also prevented where they can be: the hub checks before serving that its data folder is writable and its database is sound
171
+ (and says what to do if not), explains a port already in use, warns if the process may open too few files, refuses devices past a limit
172
+ instead of running out of file handles, caps agents per project, and logs when its core stops answering. A machine refuses an agent whose
173
+ program is not installed or whose folder is gone, immediately and with the reason.
174
+
175
+ ## Is it up?
176
+
177
+ The hub records its own state and the Discord bridge's (a crash counts as down from the last heartbeat), answers `/healthz` (the
178
+ process is there) and `/readyz` (it can do its job, including Discord), and serves Prometheus text at `/metrics`.
179
+
180
+ claudecord uptime --target 99.9 # availability over 1 hour, 1 day, 1 week, 1 month, and the error budget left
181
+ claudecord probe https://hub.example.com --name eu # on ANOTHER machine: an outside check with its own record
182
+
183
+ A scheduled GitHub Actions check (`.github/workflows/uptime.yml`, set the repository variable `HUB_URL`) is the free safety net.
184
+ `deploy/baremetal/` has a Caddyfile (automatic TLS), a systemd unit, and `bootstrap.sh`, which sets up a hub on a fresh Ubuntu or Debian machine in one command (not yet tried on a real server).
185
+
186
+ ## Keeping cost down
187
+
188
+ For an agent, the cost of a message is the turn it causes, because every turn rereads the whole conversation. So:
189
+
190
+ - everything waiting for an agent is delivered as **one** input;
191
+ - a plain `say` between agents is information and waits to ride along with the next message that needs a reply (use `@name` or
192
+ `ask` to need an answer);
193
+ - nothing is broadcast: a message goes to who it names, otherwise to the lead;
194
+ - permissions, mirroring to Discord, history and files cost the agent nothing; a file is one short line, however big.
195
+
196
+ Measured on real Claude Code with a scripted lead-and-two-workers task: **9 turns instead of 32**, about **28% of a plain group
197
+ chat's input tokens** on Sonnet. Run `scripts/cost/team_benchmark.py` (it spends tokens) to repeat it.
198
+
199
+ ## When a session runs out
200
+
201
+ At 97% of the session allowance (or an agent's context), every affected agent is told to save its state with `claudecord dump`.
202
+ A fresh session asks for it with `claudecord pickup` and carries on from the saved state, not from a replay of the old
203
+ conversation. Finished work is never handed over again.
204
+
205
+ ## History, old files and Obsidian
206
+
207
+ Recent history is hot and old history is cold, the way large chat systems keep it: the newest messages live in the database; older days
208
+ move out into immutable compressed files, one per project per day (a huge day is split so rolling over never needs much memory), which are
209
+ joined if a day ends up with several and, with a bucket set up, uploaded and then removed from the disk. Reading goes the other way: the
210
+ dashboard's "Load older" button pages back through the database and then the files, newest first, keeping the last few files unpacked. So the
211
+ database stays small and fast however many messages there are.
212
+
213
+ The last two weeks of conversation stay in the hub's database. Older history is compressed into files and moved to an
214
+ S3-compatible bucket (Oracle Cloud's free tier first, Cloudflare R2 later), so a small free server never fills its disk:
215
+
216
+ claudecord storage oracle --namespace NS --region us-ashburn-1 --bucket claudecord-history --key-id KEY --secret-file secret.txt
217
+ claudecord storage test
218
+ claudecord storage move r2.json # later: copy everything to another provider, verify, switch
219
+ claudecord storage backup # the hub also copies the live database to the bucket every few hours
220
+ claudecord storage restore # on a host that lost its disk: bring the database back
221
+
222
+ To read and graph the whole conversation in Obsidian (messages, plans, questions and answers, permission decisions, tasks and the agents' reports),
223
+ open a folder as a vault and let the hub keep it up to date while it runs, and once more when it stops:
224
+
225
+ claudecord hub --data claudecord-hub --vault ~/Vault/claudeCord # refreshed every 30 s (--vault-every)
226
+ claudecord export --data claudecord-hub --out ~/Vault/claudeCord # or write it once, or with --watch 30
227
+
228
+ It writes plain Markdown notes with links: a note per day and thread, one per person or agent, one per task, one per question (who asked, what, who
229
+ answered, the answer), one per permission request (what, and who decided) and one per report (title, summary and the files it named). Each project
230
+ has an index page that links them all. It includes history that has already moved into files or the bucket, and running it again changes nothing.
231
+ Use Obsidian's graph view to see who talked to whom.
232
+
233
+ ## Several machines
234
+
235
+ Each machine reports its size, how many agents it should run and labels such as `gpu`. `/spawn` places a new agent on the least
236
+ loaded machine with room. A machine refuses agents beyond its limit, and a second agent in the same git folder is given its own
237
+ worktree and branch so two agents never edit the same files. Machines that are asleep reconnect the moment they wake.
238
+
239
+ ## Safety
240
+
241
+ - Secrets are removed from anything an agent posts, from files before they are sent, and from the environment an agent starts with.
242
+ - Tokens are stored only as hashes. Bucket keys and the Discord token live in files only you can read.
243
+ - A device can only act for agents it registered. Frames are size-limited and rate-limited; a device that goes quiet or stops
244
+ reading is dropped.
245
+ - Text pasted into an agent has every control character removed, so it cannot escape the paste.
246
+ - The hub survives a bug in one handler by rebuilding from its last save, and restarts lose nothing it had acknowledged.
247
+
248
+ ## Checking that it works
249
+
250
+ scripts/check.sh # format, lints, every test, then a live check of every feature, then the shipped binary
251
+ scripts/check.sh --fix # repairs formatting, simple lints and the code map, then checks
252
+ claudecord selftest # starts the real pieces and proves each feature is alive
253
+
254
+ `CODEMAP.md` lists every file and what it is, generated from each file's own header. CI runs the same checks on Linux (x86 and ARM)
255
+ and macOS.
256
+
257
+ ## Honest limits
258
+
259
+ - The Discord side is tested against a stand-in Discord, not against the real service yet.
260
+ - Typing into Claude Code, Codex and agy is done through the terminal. The screen-reading rules for agy and Codex are generic and
261
+ unverified against the live programs; whether a pasted `/command` runs the same way in every program is also unverified.
262
+ - The hosted service, its dashboard and the sign-in are tested against a stand-in Discord, not the real one yet. The dashboard cannot send messages or
263
+ show chats; it places projects, spawns agents and shows status and numbers.
264
+ - A load test exists (`scripts/load/`, k6, users with three bots each); it was run only up to about 9,000 users on a laptop, where k6
265
+ itself ran out of threads. The 10,000-user runs on free-server sizes are a CI job (`load.yml`) that has not been run yet.
266
+ - The pip and npm packages are built and tested by `scripts/test_packaging.py`, but nothing has been published yet.
267
+ - Windows is built in CI but has not been run by me. Use tmux inside WSL for the tested route; native Windows uses the
268
+ built-in ConPTY terminal, and the stand-in-agent tests skip themselves there.
269
+ - tmux cannot see a half-typed line, only that someone was recently active, so messages wait for quiet instead.
270
+ - Only the generic terminal driver exists. Structured drivers for Claude Code hooks, ACP and the Codex app server are not built.
271
+
@@ -0,0 +1,5 @@
1
+ claudecord-0.2.2.data/scripts/claudecord.exe,sha256=nZ0EvrJdADrN26pfjo0GG6hfGJn4_joGxZnky7B92n8,20992512
2
+ claudecord-0.2.2.dist-info/METADATA,sha256=U7dEuAWe8I__MTLas9FKdZlChuiowP1bFeVbahYza2I,19886
3
+ claudecord-0.2.2.dist-info/WHEEL,sha256=8Aej0W0a6Cz6apA3IzJrTnxLRVLAt-w0Oh8SA3Con_c,94
4
+ claudecord-0.2.2.dist-info/sboms/claudecord.cyclonedx.json,sha256=6WT3PEcivRHYzm9u6pVkvZLJYlJGBMaWnVXUFTi_mRU,285174
5
+ claudecord-0.2.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.15.0)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64