Metadata-Version: 2.5
Name: claude-fleet
Version: 0.1.0
Summary: One local page showing every Claude Code session on your machine, and where they overwrite each other's memory
Project-URL: Homepage, https://github.com/harry329/claude-fleet
Project-URL: Issues, https://github.com/harry329/claude-fleet/issues
Author: Harry
License: MIT License
        
        Copyright (c) 2026 Harry
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: claude,claude-code,cli,dashboard,monitoring
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# Claude Fleet

One local page showing every Claude Code session running on your machine, so you stop
cycling through terminals to find the one waiting on you. It also tells you where your
sessions are quietly overwriting each other's memory.

![The dashboard](https://raw.githubusercontent.com/harry329/claude-fleet/main/docs/dashboard.jpg)

*Screenshots show `--demo` data. Nothing real appears in them.*

Python standard library only. No dependencies, no build step, no network calls.

## Install and run

```bash
uvx claude-fleet                 # no install
pipx install claude-fleet        # or keep it around
claude-fleet
```

Try it before you trust it:

```bash
claude-fleet --demo          # a fabricated fleet, reads nothing on your machine
```

It prints a URL carrying a one-time key. Open that URL.

```
Claude Fleet: http://127.0.0.1:8799/?t=Wc3l...
  read-only; --enable-send to allow sending. Tested against Claude Code 2.1.266.
```

## What it shows

Sessions sort so the ones needing you come first.

| bucket | meaning |
| --- | --- |
| waiting for you | the turn finished and it is sitting at the prompt |
| working | mid-turn. "silent for Nm" usually means a permission prompt is blocking it |
| parked | someone dropped that session to a shell |
| unlabelled | a live `claude` process that never registered a status, typically a session another session started |

Each card names the terminal the session lives in, so once you know which one wants
you, you know which tab to switch to. Click a card to replay its recent turns: your
prompts, the replies, thinking, tool calls and truncated tool output.

Tick **notify me** for a browser notification the moment a session starts waiting.

## Memory conflicts

![The memory conflict panel](https://raw.githubusercontent.com/harry329/claude-fleet/main/docs/memory-conflicts.jpg)

Claude Code keys a session's memory folder to the directory the session started in.
Run several sessions from one parent directory and they share a memory folder, where a
save rewrites the whole file with no locking. The last writer wins and the others are
lost silently. The `memory:` pill counts what it finds.

| finding | meaning |
| --- | --- |
| written by several sessions | one memory file, or one `MEMORY.md`, has more than one author |
| duplicate index line | a `MEMORY.md` links the same file twice |
| broken index link | a `MEMORY.md` links a file that is gone |
| missing from the index | a memory file no `MEMORY.md` line points at |
| differs between projects | the same memory name says different things in different projects |

Expanding a finding lists every write with its time, the session behind it, and whether
that version survived. Rows are labelled by evidence quality: `file-history` is exact,
`shell` is inferred from the session's own transcript, `observed` means the watcher saw
a change nothing else explains. The panel never writes inside a memory directory, and a
test asserts it.

## Sending commands

Off by default. Start with `--enable-send` to turn the composer on.

Tick the checkbox on any card to add it as a recipient, or leave them all clear to
address the session you are viewing. Enter sends, Shift+Enter starts a new line.

Delivery goes through Claude Code's own peer messaging. Each send spawns a one-shot
`claude -p` that calls `SendMessage`, which takes a few seconds and costs one small
Claude call. The recipient sees a short-lived relay session as the sender and starts
acting on the message immediately.

## Security

The dashboard is single-user and local, and it is guarded as such.

- Every route requires the per-run token, compared with `secrets.compare_digest`.
- Cross-site requests are refused by `Origin`, so no page you browse can drive it.
- A non-loopback `Host` is refused, which blocks DNS rebinding.
- The cookie it sets is `SameSite=Strict`.

Two things to know if you share the machine with other people. The token is printed on
startup, so redirecting that output into a log file leaves it there. And a relayed
message is passed to `claude -p` as a command line argument, which means its text is
visible in `ps` to any other user while the send is in flight. Neither matters on a
single-user machine; on a shared one, avoid `--enable-send`.

Sending stays off unless you ask for it. Anyone who can already run code as your user
can read `~/.claude` directly, so the dashboard adds no exposure beyond that.

## Compatibility

Tested against **Claude Code 2.1.266** on Linux. macOS support is implemented and unit
tested but has not been run on real macOS hardware; reports welcome. Windows is not
supported, because this depends on POSIX process listing and on Claude Code's Unix
domain sockets.

This reads files Claude Code does not document: the session registry, transcripts and
file-history backups. **A Claude Code upgrade may change them and break this tool.**
It degrades rather than crashing when a file looks unfamiliar, but expect to update it.

## Where the data comes from

- `~/.claude/sessions/<pid>.json` — live registry: pid, session id, cwd, name, status
- `~/.claude/projects/<slug>/<session-id>.jsonl` — transcripts
- `~/.claude/file-history/<session-id>/<sha256 of path>@vN` — past versions of edited files
- `ps`, and `/proc` on Linux or `lsof` on macOS — liveness, terminal, uptime

Only the tail of each transcript is parsed for the list, so files of tens of megabytes
stay cheap to poll.

## Endpoints

| route | purpose |
| --- | --- |
| `GET /api/sessions` | every live session with status and summary |
| `GET /api/session/<id>` | recent events for one session |
| `GET /api/memory` | memory conflict findings across all projects |
| `GET /api/outbox` | recent sends and their state |
| `POST /api/send` | `{"targets": ["<session-id>"], "text": "…"}` |

`--demo` serves fabricated payloads on all of these, starts no watchers, and refuses
to send.

## Development

```bash
git clone https://github.com/harry329/claude-fleet && cd claude-fleet
python -m unittest discover -s tests -v
python -m claude_fleet --port 8799
```

Work here is spec driven. Each change starts as `specs/NNN-slug.md`, and the tests are
its acceptance criteria, one test per criterion. See [specs/README.md](specs/README.md).

## Licence

MIT.
