relaybay 0.1.0__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.
- relaybay-0.1.0/.gitignore +34 -0
- relaybay-0.1.0/CHANGELOG.md +186 -0
- relaybay-0.1.0/LICENSE +21 -0
- relaybay-0.1.0/PKG-INFO +237 -0
- relaybay-0.1.0/README.md +207 -0
- relaybay-0.1.0/docs/PLAN.md +13 -0
- relaybay-0.1.0/docs/ROADMAP.md +90 -0
- relaybay-0.1.0/docs/SPEC.md +515 -0
- relaybay-0.1.0/docs/adr/0001-htmx-sse.md +38 -0
- relaybay-0.1.0/docs/architecture.md +169 -0
- relaybay-0.1.0/docs/changelog.md +5 -0
- relaybay-0.1.0/docs/connect-claude-code.md +149 -0
- relaybay-0.1.0/docs/design/0001-hooks-and-setup.md +62 -0
- relaybay-0.1.0/docs/design/0002-working-rules.md +57 -0
- relaybay-0.1.0/docs/design/0003-packaging-and-release.md +79 -0
- relaybay-0.1.0/docs/design/0004-navigation.md +55 -0
- relaybay-0.1.0/docs/design/0005-comments-to-agents.md +56 -0
- relaybay-0.1.0/docs/design/0006-environments-and-access.md +73 -0
- relaybay-0.1.0/docs/design/0007-review.md +101 -0
- relaybay-0.1.0/docs/design/0008-memory-and-context.md +162 -0
- relaybay-0.1.0/docs/design/0009-screenshot-annotations.md +51 -0
- relaybay-0.1.0/docs/design/0010-map-and-usage.md +50 -0
- relaybay-0.1.0/docs/design/0011-docs-in-database.md +43 -0
- relaybay-0.1.0/docs/design/0012-runner-and-embedded-terminal.md +65 -0
- relaybay-0.1.0/docs/design/index.md +22 -0
- relaybay-0.1.0/docs/getting-started/agent-install.md +121 -0
- relaybay-0.1.0/docs/getting-started/install.md +138 -0
- relaybay-0.1.0/docs/how-to/coordinator.md +8 -0
- relaybay-0.1.0/docs/how-to/lan-access.md +22 -0
- relaybay-0.1.0/docs/how-to/troubleshooting.md +57 -0
- relaybay-0.1.0/docs/how-to/uninstall.md +21 -0
- relaybay-0.1.0/docs/index.md +26 -0
- relaybay-0.1.0/docs/llms.txt +24 -0
- relaybay-0.1.0/docs/mcp-tools.md +228 -0
- relaybay-0.1.0/docs/reference/cli.md +92 -0
- relaybay-0.1.0/docs/reference/configuration.md +57 -0
- relaybay-0.1.0/docs/reference/mcp.md +227 -0
- relaybay-0.1.0/mkdocs.yml +92 -0
- relaybay-0.1.0/pyproject.toml +82 -0
- relaybay-0.1.0/scripts/changelog_notes.py +40 -0
- relaybay-0.1.0/scripts/check_dist.py +59 -0
- relaybay-0.1.0/scripts/gen_reference.py +278 -0
- relaybay-0.1.0/scripts/record_gif.md +40 -0
- relaybay-0.1.0/src/relaybay/__init__.py +8 -0
- relaybay-0.1.0/src/relaybay/__main__.py +3 -0
- relaybay-0.1.0/src/relaybay/app.py +68 -0
- relaybay-0.1.0/src/relaybay/cli.py +322 -0
- relaybay-0.1.0/src/relaybay/config.py +296 -0
- relaybay-0.1.0/src/relaybay/db/__init__.py +0 -0
- relaybay-0.1.0/src/relaybay/db/connection.py +46 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0001_init.sql +94 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0002_task_description_progress.sql +3 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0003_tracker_and_session_alias.sql +15 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0004_next_step_freshness.sql +5 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0005_tracker_history.sql +18 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0006_project_rules.sql +7 -0
- relaybay-0.1.0/src/relaybay/db/migrations/0007_hook_sessions.sql +8 -0
- relaybay-0.1.0/src/relaybay/db/repo.py +704 -0
- relaybay-0.1.0/src/relaybay/demo.py +220 -0
- relaybay-0.1.0/src/relaybay/doctor.py +146 -0
- relaybay-0.1.0/src/relaybay/domain/__init__.py +21 -0
- relaybay-0.1.0/src/relaybay/domain/errors.py +14 -0
- relaybay-0.1.0/src/relaybay/domain/hooks.py +88 -0
- relaybay-0.1.0/src/relaybay/domain/models.py +146 -0
- relaybay-0.1.0/src/relaybay/domain/reports.py +53 -0
- relaybay-0.1.0/src/relaybay/domain/rules.py +213 -0
- relaybay-0.1.0/src/relaybay/domain/sessions.py +22 -0
- relaybay-0.1.0/src/relaybay/domain/stages.py +24 -0
- relaybay-0.1.0/src/relaybay/domain/task_fields.py +92 -0
- relaybay-0.1.0/src/relaybay/domain/tasks.py +18 -0
- relaybay-0.1.0/src/relaybay/events.py +68 -0
- relaybay-0.1.0/src/relaybay/hook_client.py +49 -0
- relaybay-0.1.0/src/relaybay/logs.py +29 -0
- relaybay-0.1.0/src/relaybay/machine_setup.py +803 -0
- relaybay-0.1.0/src/relaybay/mcp_server/__init__.py +0 -0
- relaybay-0.1.0/src/relaybay/mcp_server/format.py +306 -0
- relaybay-0.1.0/src/relaybay/mcp_server/server.py +586 -0
- relaybay-0.1.0/src/relaybay/security.py +238 -0
- relaybay-0.1.0/src/relaybay/service.py +1351 -0
- relaybay-0.1.0/src/relaybay/web/__init__.py +0 -0
- relaybay-0.1.0/src/relaybay/web/hooks.py +56 -0
- relaybay-0.1.0/src/relaybay/web/markdown.py +10 -0
- relaybay-0.1.0/src/relaybay/web/routes.py +506 -0
- relaybay-0.1.0/src/relaybay/web/sse.py +59 -0
- relaybay-0.1.0/src/relaybay/web/static/app.css +690 -0
- relaybay-0.1.0/src/relaybay/web/static/app.js +357 -0
- relaybay-0.1.0/src/relaybay/web/static/htmx.min.js +1 -0
- relaybay-0.1.0/src/relaybay/web/static/sse.js +290 -0
- relaybay-0.1.0/src/relaybay/web/templates/_card.html +25 -0
- relaybay-0.1.0/src/relaybay/web/templates/_column.html +16 -0
- relaybay-0.1.0/src/relaybay/web/templates/_columns.html +3 -0
- relaybay-0.1.0/src/relaybay/web/templates/_integrations.html +101 -0
- relaybay-0.1.0/src/relaybay/web/templates/_projects.html +26 -0
- relaybay-0.1.0/src/relaybay/web/templates/_report_badges.html +6 -0
- relaybay-0.1.0/src/relaybay/web/templates/_session.html +11 -0
- relaybay-0.1.0/src/relaybay/web/templates/_task_dialog.html +14 -0
- relaybay-0.1.0/src/relaybay/web/templates/_task_form.html +72 -0
- relaybay-0.1.0/src/relaybay/web/templates/_task_view.html +119 -0
- relaybay-0.1.0/src/relaybay/web/templates/_tracker.html +16 -0
- relaybay-0.1.0/src/relaybay/web/templates/base.html +28 -0
- relaybay-0.1.0/src/relaybay/web/templates/board.html +31 -0
- relaybay-0.1.0/src/relaybay/web/templates/integrations.html +9 -0
- relaybay-0.1.0/src/relaybay/web/templates/login.html +21 -0
- relaybay-0.1.0/src/relaybay/web/templates/projects.html +9 -0
- relaybay-0.1.0/src/relaybay/web/templates/task.html +10 -0
- relaybay-0.1.0/tests/__init__.py +0 -0
- relaybay-0.1.0/tests/conftest.py +114 -0
- relaybay-0.1.0/tests/fixtures/claude_code_hooks.json +63 -0
- relaybay-0.1.0/tests/test_board.py +361 -0
- relaybay-0.1.0/tests/test_cli.py +46 -0
- relaybay-0.1.0/tests/test_config.py +100 -0
- relaybay-0.1.0/tests/test_demo.py +75 -0
- relaybay-0.1.0/tests/test_doctor.py +160 -0
- relaybay-0.1.0/tests/test_hooks.py +326 -0
- relaybay-0.1.0/tests/test_mcp.py +447 -0
- relaybay-0.1.0/tests/test_migrations.py +206 -0
- relaybay-0.1.0/tests/test_release.py +93 -0
- relaybay-0.1.0/tests/test_repo_hygiene.py +56 -0
- relaybay-0.1.0/tests/test_rules.py +374 -0
- relaybay-0.1.0/tests/test_security.py +194 -0
- relaybay-0.1.0/tests/test_service.py +319 -0
- relaybay-0.1.0/tests/test_sessions.py +235 -0
- relaybay-0.1.0/tests/test_setup.py +690 -0
- relaybay-0.1.0/tests/test_sse.py +132 -0
- relaybay-0.1.0/tests/test_tracker_archive.py +267 -0
- relaybay-0.1.0/tests/test_tracker_history.py +214 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.venv/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
.mypy_cache/
|
|
8
|
+
dist/
|
|
9
|
+
build/
|
|
10
|
+
site/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
|
|
13
|
+
# Local data
|
|
14
|
+
.dev-data/
|
|
15
|
+
.demo-data/
|
|
16
|
+
gif-data/
|
|
17
|
+
*.sqlite
|
|
18
|
+
*.sqlite3
|
|
19
|
+
*.db
|
|
20
|
+
.env
|
|
21
|
+
.env.*
|
|
22
|
+
!.env.example
|
|
23
|
+
|
|
24
|
+
# Personal AI assistant settings (keep out of the public repo)
|
|
25
|
+
CLAUDE.md
|
|
26
|
+
CLAUDE.local.md
|
|
27
|
+
.claude/
|
|
28
|
+
.mcp.json
|
|
29
|
+
|
|
30
|
+
# OS / editors
|
|
31
|
+
.DS_Store
|
|
32
|
+
Thumbs.db
|
|
33
|
+
.idea/
|
|
34
|
+
.vscode/
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
6
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-11-02
|
|
11
|
+
|
|
12
|
+
First public release: a local board and MCP server for many Claude Code sessions, installable with
|
|
13
|
+
one command (`uv tool install relaybay`, `uvx relaybay`, `pipx install relaybay` or the Docker
|
|
14
|
+
image), with Claude Code hooks for live session status, working rules served to every session,
|
|
15
|
+
`relaybay setup` and `relaybay doctor` for the machine setup, and a docs site.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Packaging and release: version `0.1.0` in `pyproject.toml` (the only place; `relaybay
|
|
20
|
+
--version` reads the installed metadata), wheel and sdist with the templates, static assets and
|
|
21
|
+
migrations, a `Dockerfile` (`python:3.12-slim`, non-root, `/data` volume) and a release workflow
|
|
22
|
+
on `v*` tags: build and check the artifacts, publish to PyPI by trusted publishing, push the
|
|
23
|
+
multi-arch image `ghcr.io/codenator81/relaybay:<version>` and `:latest`, create the GitHub
|
|
24
|
+
Release with this file's notes and deploy the docs.
|
|
25
|
+
- `relaybay doctor [--json]`: relaybay, Python and OS versions, data folder and token file, Claude
|
|
26
|
+
Code and its minimum supported version (2.0.0), the desktop app, the server with the same token,
|
|
27
|
+
MCP `initialize`, the hook endpoint, the rules hash against the running server, the hooks in the
|
|
28
|
+
user settings and the MCP registration. Read-only (it never creates the token); reports the
|
|
29
|
+
Claude Code files even when the server is down; the output has the shape of `setup --check
|
|
30
|
+
--json` and the exit code is 1 when an item fails.
|
|
31
|
+
- `relaybay demo --home <dir> [--force]`: seeds a neutral demo workspace (`acme-shop`, `demo-api`:
|
|
32
|
+
tasks in every stage with descriptions, progress and reports, tracker badges, a stale next step,
|
|
33
|
+
a decision, a desktop session shown as working). A folder that already holds a board is refused;
|
|
34
|
+
`--force` renames its database aside first.
|
|
35
|
+
- `/healthz` also returns `rules_hash`, the global rules the server started with.
|
|
36
|
+
- Docs: install on Windows, macOS and Linux (uv, uvx, pipx, Docker), "Install relaybay with your
|
|
37
|
+
coding agent" (an idempotent procedure and a copy-paste prompt), CLI, configuration and MCP
|
|
38
|
+
reference pages generated by `scripts/gen_reference.py` (CI fails when they drift).
|
|
39
|
+
- Community files: code of conduct (Contributor Covenant 2.1), security policy, governance note,
|
|
40
|
+
issue forms and a pull request template.
|
|
41
|
+
- Live session status from Claude Code hooks: `POST /hooks/claude-code` (Bearer token, same
|
|
42
|
+
Host/Origin rules as `/mcp`) maps `SessionStart` / `UserPromptSubmit` / `PreToolUse` to working
|
|
43
|
+
(with the tool name as activity), `Notification` to waiting, `Stop` to idle and `SessionEnd` to
|
|
44
|
+
ended, which also unbinds the session from its tasks (`task.session_unbound`, reason
|
|
45
|
+
`session_end`). Activity is coalesced to one `session.status_changed` event per session per 5 s.
|
|
46
|
+
Cards show a status dot on the "open in desktop" icon; the task dialog shows the status and the
|
|
47
|
+
last activity. Prompt text and tool input are never stored.
|
|
48
|
+
- Exact linking of hook sessions: the `SessionStart` answer tells the agent its hook session id,
|
|
49
|
+
and every write tool (and `task_bind_session`) accepts `hook_session`; the MCP instructions say
|
|
50
|
+
so. Without it, a hook session is linked by its working directory to the one desktop session bound
|
|
51
|
+
in that project; ambiguous cases stay unlinked and are listed on the Integrations page. Migration
|
|
52
|
+
`0007` adds `session.cc_session_id`, `activity_at` and `unlinked_reason`.
|
|
53
|
+
- `relaybay setup` (`--dry-run` default, `--apply`, `--remove`, `--check [--json]`, `--expect
|
|
54
|
+
<plan hash>`, `--mode command|http` with `command` as the default, `--claude-home`): detects
|
|
55
|
+
`claude` and its version and the desktop app, prints the exact diff of `~/.claude/settings.json`
|
|
56
|
+
and its plan hash, backs the file up before any write (through a symlink to its target), adds or
|
|
57
|
+
removes only relaybay's own hook entries (a command hook running `relaybay.hook_client` with
|
|
58
|
+
`--url …/hooks/claude-code`, or an http hook posting exactly to `/hooks/claude-code` on a
|
|
59
|
+
loopback or the configured host), never writes the token, refuses files that are not UTF-8 or
|
|
60
|
+
valid JSON, and prints the `claude mcp add` command instead of editing `~/.claude.json`.
|
|
61
|
+
`--check` also runs the hook's interpreter once. `relaybay hook` and
|
|
62
|
+
`python -m relaybay.hook_client`: a standard-library command hook that gives up after 0.3 s and
|
|
63
|
+
always exits 0.
|
|
64
|
+
- Board: **Integrations** page (header link) with detection, the plan, Apply / Remove / Run check
|
|
65
|
+
buttons (Apply and Remove write only the plan shown) and the unlinked hook sessions. Hook input
|
|
66
|
+
over 256 KB is dropped quietly (`204`). `relaybay serve --claude-home` / `RELAYBAY_CLAUDE_HOME`.
|
|
67
|
+
- Working rules: the MCP server instructions are a short working contract (snapshot first, pick or
|
|
68
|
+
create a task, keep next step / waiting on / progress current, `state · size · gist` reports,
|
|
69
|
+
`waiting_on` for decisions, `task_patch` for missing fields). Rules as structured data (report
|
|
70
|
+
format, stage requirements `report_since_stage_change` / `field_present`, description template,
|
|
71
|
+
guidance) with built-in defaults (a report before `test`, `progress` before `done`), a global
|
|
72
|
+
`[rules]` table in `config.toml` and per-project overrides in the new `project_rules` table
|
|
73
|
+
(migration `0006`); a config error stops the start, a broken project override is logged and
|
|
74
|
+
ignored (global rules apply, "project override ignored: …" is shown). Read through the tool `rules_get(project?)` and the
|
|
75
|
+
resources `relaybay://rules` and `relaybay://rules/{project}`; `project_snapshot` starts with
|
|
76
|
+
the rules hash. Stage moves that miss a rule succeed with a `Warning (rules)` line in the MCP
|
|
77
|
+
response, the board form and the event's `warnings` (`rules_mode = "warn"`, default), or are
|
|
78
|
+
refused (`rules_mode = "strict"`).
|
|
79
|
+
- `relaybay serve` (FastAPI + uvicorn, default `127.0.0.1:8765`) and `relaybay token [--rotate]`;
|
|
80
|
+
`python -m relaybay`; settings from `config.toml`, `RELAYBAY_*` environment variables and flags.
|
|
81
|
+
- SQLite storage (WAL, numbered migrations) for projects, tasks, reports, decisions, sessions and an
|
|
82
|
+
append-only event log; every write goes through one service layer and publishes an event.
|
|
83
|
+
- Token security: Bearer token on `/mcp` (and the reserved `/api` prefix), cookie login for the
|
|
84
|
+
board via `/login`, Host allow-list, Origin checks, CSRF protection for board edits,
|
|
85
|
+
`Content-Security-Policy`.
|
|
86
|
+
- MCP server (Streamable HTTP at `/mcp`) with the tools `project_list`, `project_upsert`,
|
|
87
|
+
`project_snapshot`, `task_list`, `task_get`, `task_create`, `task_update`, `task_set_stage`,
|
|
88
|
+
`task_bind_session`, `report_add`, `decision_add`, `events_since` and the resource
|
|
89
|
+
`relaybay://project/{slug}`.
|
|
90
|
+
- Board: projects list with per-stage counts, stage columns with cards, card editing, live updates
|
|
91
|
+
over Server-Sent Events with `Last-Event-ID` replay, a stage tab bar on narrow screens, light and
|
|
92
|
+
dark themes. htmx and its SSE extension are vendored.
|
|
93
|
+
- Configurable display labels for stages (`[stages.labels]`).
|
|
94
|
+
- Sign-in page: unauthenticated browser visits redirect to `/login`, which accepts the access
|
|
95
|
+
token in a form (CSRF-protected) and returns to the requested page.
|
|
96
|
+
- `relaybay serve` and `relaybay token` print their data folder; `/healthz` reports a public token
|
|
97
|
+
fingerprint (`token_id`) and `relaybay token` warns when the running server uses a different
|
|
98
|
+
token.
|
|
99
|
+
- Report state and size badges on cards and the task page (state coloured by meaning, size S/M/L,
|
|
100
|
+
both with tooltips); labels and tooltips configurable via `[reports.labels]` / `[reports.hints]`.
|
|
101
|
+
- Claude desktop app session links: write tools accept a desktop session id (`local_<uuid>`) and a
|
|
102
|
+
`session_title`; cards and the new task page (`/t/{key}`) show "Open in desktop" and a copy-link
|
|
103
|
+
button; the link template is configurable (`desktop_link_template`).
|
|
104
|
+
- Session binding history per task (`task_session`), shown on the task page and in `task_get`;
|
|
105
|
+
binding a session emits `task.session_bound`.
|
|
106
|
+
- Task `description` and `progress` (markdown, migration `0002` upgrades existing databases in
|
|
107
|
+
place): `task_create` and `task_update` accept both, `report_add` takes an optional `progress`
|
|
108
|
+
saved in the same transaction, `task_get` shows them in full and `project_snapshot` shortened.
|
|
109
|
+
- `task_unbind_session` MCP tool and an "Unbind session" button (with confirmation) on the board:
|
|
110
|
+
closes the binding, keeps the history and emits `task.session_unbound`; an optional `session`
|
|
111
|
+
refuses to unbind a session that took over meanwhile.
|
|
112
|
+
- Session aliases (migration `0003`): `task_bind_session` with a plain name on a task bound to a
|
|
113
|
+
desktop session keeps the desktop binding and records the name as that session's alias (event
|
|
114
|
+
`session.alias_added`); the name then resolves to the desktop session in writes, `task_list` and
|
|
115
|
+
`task_unbind_session`. Aliases are global; no alias is made for a name a plain session already
|
|
116
|
+
has (the call warns and changes nothing).
|
|
117
|
+
- Done column window and archive: the board's `done` column shows tasks closed within
|
|
118
|
+
`done_window_days` (default 7, `RELAYBAY_DONE_WINDOW_DAYS`); older ones are archived and shown
|
|
119
|
+
with "Show archived" (`?archived=1`). A search box filters cards by key or title (`?q=`) and also
|
|
120
|
+
searches the archive.
|
|
121
|
+
- External tracker mark (migration `0003`): task fields `tracker_ref`, `tracker_name`,
|
|
122
|
+
`tracker_url` (http/https only) and `tracker_logged`, accepted by `task_create` / `task_update`,
|
|
123
|
+
shown by `task_get` and `project_snapshot`, edited in the task dialog. Cards show the issue as a
|
|
124
|
+
badge (a link with a URL, ✓ when logged). Opt-in `require_tracker_log`
|
|
125
|
+
(`RELAYBAY_REQUIRE_TRACKER_LOG`, default false): done tasks without the mark show "not logged" and
|
|
126
|
+
are never archived.
|
|
127
|
+
- Next step freshness (migration `0004`, upgrades existing databases in place): `task_set_stage`
|
|
128
|
+
and `report_add` accept `next_step` and `waiting_on`, saved in the same transaction (`"-"`
|
|
129
|
+
clears them), and their descriptions ask sessions to keep both current. A next step set before
|
|
130
|
+
the task's last stage change shows muted with a "stale" marker on the card and in the task
|
|
131
|
+
dialog, and with `(stale)` in `task_get` / `project_snapshot`; writing it again over MCP (or editing it on the board) confirms it.
|
|
132
|
+
- Tracker history (migration `0005`, upgrades existing databases in place and backfills one entry
|
|
133
|
+
per task with an issue key): a new `tracker_ref` appends an entry and earlier ones stay; marking
|
|
134
|
+
the work log entered or not stamps `logged_at` / `unlogged_at` on the current entry. The task
|
|
135
|
+
dialog and `/t/<key>` show a "Tracker history" block and `task_get` a "Tracker history" section;
|
|
136
|
+
the card badge and `project_snapshot` keep showing only the current issue.
|
|
137
|
+
- Automatic unlog: when a logged task gets new work (a report, a changed `progress`, or a stage
|
|
138
|
+
move back out of `live` or `done` to an earlier stage), `tracker_logged` is cleared in the same
|
|
139
|
+
transaction with a `task.tracker_unlogged` event carrying the reason. Metadata edits (title,
|
|
140
|
+
branch, waiting on, next step, tracker fields) keep the mark; an explicit `tracker_logged` in
|
|
141
|
+
the same write wins. A new `tracker_ref` starts as not logged unless `tracker_logged` is passed
|
|
142
|
+
in the same write.
|
|
143
|
+
- `task_patch` MCP tool: changes any editable task fields given as one JSON object (`fields`),
|
|
144
|
+
with the same validation, clearing, stage-move and auto-unlog rules as `task_update` /
|
|
145
|
+
`task_set_stage` and optional `expected_version`; unknown names fail with the allowed list. The
|
|
146
|
+
editable fields come from one list that also drives write validation, the new resource
|
|
147
|
+
`relaybay://schema/task` and an "Editable fields: …" line at the end of `task_get`, so clients
|
|
148
|
+
that cached an older `task_update` schema can still set new fields. README and
|
|
149
|
+
`docs/mcp-tools.md` explain schema caching in long-running sessions.
|
|
150
|
+
- A test that keeps the repository English-only (no Cyrillic in `src/`, `docs/`, `tests/` and the
|
|
151
|
+
root markdown files).
|
|
152
|
+
- `"-"` clears a text field in `task_update` (and leaves it empty in `task_create`, clears
|
|
153
|
+
`progress` in `report_add`), since models cannot always send an empty string.
|
|
154
|
+
|
|
155
|
+
### Changed
|
|
156
|
+
|
|
157
|
+
- Documentation restructured: `docs/SPEC.md` (shipped behaviour with stable `#spec-…` anchors),
|
|
158
|
+
`docs/ROADMAP.md` (versions 0.1.0 to 1.0 with status), `docs/architecture.md`, one design per
|
|
159
|
+
upcoming step in `docs/design/`, configuration and CLI reference pages, `docs/llms.txt`; the
|
|
160
|
+
former `docs/PLAN.md` is now a pointer to them. A MkDocs Material site (`mkdocs.yml`, optional
|
|
161
|
+
`docs` dependency group) is built with `mkdocs build --strict` on pull requests and deployed to
|
|
162
|
+
GitHub Pages from `main`.
|
|
163
|
+
- Docs and tests use English examples for custom stage and report labels; labels in any language
|
|
164
|
+
remain configurable, the defaults are English.
|
|
165
|
+
|
|
166
|
+
- Cards show only essentials: key, tracker badge (including "not logged") and an icon-only "open
|
|
167
|
+
in desktop" link in the top row, then title, "waiting on", branch and the next step (two lines).
|
|
168
|
+
Description, progress, the last report with its badges, the session name, "no session" and
|
|
169
|
+
"Copy link" moved off the card; the task dialog and `/t/<key>` still show all of them.
|
|
170
|
+
- Done cards no longer show "waiting on" and the next step; the task dialog shows them muted.
|
|
171
|
+
- The done column is no longer cut at 20 cards; it holds the window and is capped at 200 with a
|
|
172
|
+
note.
|
|
173
|
+
- Clicking a card opens the task in a dialog over the live board instead of an inline editor: the
|
|
174
|
+
full task (description, progress, reports, session history, desktop link, unbind) and its edit
|
|
175
|
+
form. The dialog has its own URL (`/p/<project>?task=<key>`), closes with Back, Esc or a click
|
|
176
|
+
outside, and is full screen on narrow screens. The task page `/t/<key>` shows the same details.
|
|
177
|
+
|
|
178
|
+
### Fixed
|
|
179
|
+
|
|
180
|
+
- Clearing a field in the board's edit form (an empty input) now clears it; it used to keep the old
|
|
181
|
+
value.
|
|
182
|
+
- A long session title no longer widens a card past its column: the session badge shrinks with an
|
|
183
|
+
ellipsis and shows the full title on hover.
|
|
184
|
+
|
|
185
|
+
[Unreleased]: https://github.com/Codenator81/relaybay/compare/v0.1.0...HEAD
|
|
186
|
+
[0.1.0]: https://github.com/Codenator81/relaybay/releases/tag/v0.1.0
|
relaybay-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aleksandrs Poltarjonoks
|
|
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.
|
relaybay-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: relaybay
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A live board and MCP server for coordinating many Claude Code sessions across projects.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Codenator81/relaybay
|
|
6
|
+
Project-URL: Documentation, https://codenator81.github.io/relaybay/
|
|
7
|
+
Project-URL: Changelog, https://github.com/Codenator81/relaybay/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Issues, https://github.com/Codenator81/relaybay/issues
|
|
9
|
+
Author: Aleksandrs Poltarjonoks
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Web Environment
|
|
14
|
+
Classifier: Framework :: FastAPI
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: aiosqlite>=0.20
|
|
22
|
+
Requires-Dist: fastapi>=0.115
|
|
23
|
+
Requires-Dist: jinja2>=3.1
|
|
24
|
+
Requires-Dist: markdown-it-py>=3.0
|
|
25
|
+
Requires-Dist: mcp<3,>=2
|
|
26
|
+
Requires-Dist: platformdirs>=4.2
|
|
27
|
+
Requires-Dist: python-multipart>=0.0.9
|
|
28
|
+
Requires-Dist: uvicorn>=0.30
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# relaybay
|
|
32
|
+
|
|
33
|
+
[](https://github.com/Codenator81/relaybay/actions/workflows/ci.yml)
|
|
34
|
+
[](https://pypi.org/project/relaybay/)
|
|
35
|
+
[](LICENSE)
|
|
36
|
+
[](https://codenator81.github.io/relaybay/)
|
|
37
|
+
|
|
38
|
+
A live board and MCP server for people who run many Claude Code sessions across many repositories.
|
|
39
|
+
Sessions report their work through MCP tools; you watch **projects → tasks → stages → reports** update
|
|
40
|
+
in the browser, on the desktop or on your phone.
|
|
41
|
+
|
|
42
|
+
> **Status: early (0.1).** relaybay is built for my own workflow first and changes quickly. Expect
|
|
43
|
+
> rough edges; issues and ideas are welcome.
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv tool install relaybay # or: pipx install relaybay · or run it once: uvx relaybay
|
|
51
|
+
relaybay serve # prints the board's login link and the MCP URL
|
|
52
|
+
relaybay setup # shows how it connects Claude Code (then --apply --expect <hash>)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Open the login link once; the browser keeps a cookie. `relaybay token` prints the token again with
|
|
56
|
+
the `claude mcp add …` command for Claude Code. Docker, Windows/macOS/Linux details and a procedure
|
|
57
|
+
your coding agent can follow for you:
|
|
58
|
+
[Install](https://codenator81.github.io/relaybay/getting-started/install/) ·
|
|
59
|
+
[Install with your coding agent](https://codenator81.github.io/relaybay/getting-started/agent-install/).
|
|
60
|
+
Something off? `relaybay doctor`.
|
|
61
|
+
|
|
62
|
+
**Documentation:** [codenator81.github.io/relaybay](https://codenator81.github.io/relaybay/) ·
|
|
63
|
+
[Specification](docs/SPEC.md) (how it behaves now) · [Roadmap](docs/ROADMAP.md) ·
|
|
64
|
+
[Architecture](docs/architecture.md)
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- **Board** — projects with per-stage counts; per project, columns `plan → dev → test → live → done`
|
|
69
|
+
with cards showing only the essentials: key, tracker badge, an "open in desktop" icon when a
|
|
70
|
+
desktop session works on the task, title, waiting-on person, branch and the next step. Click a
|
|
71
|
+
card to open the task in a dialog over the live board (its own URL,
|
|
72
|
+
`/p/<project>?task=<key>`, full screen on a phone): description and progress in full, reports,
|
|
73
|
+
session history, "Open in desktop", unbinding the session and editing the task. Each task also has
|
|
74
|
+
a page of its own (`/t/<key>`). Live updates over Server-Sent Events, catch-up after sleep or a
|
|
75
|
+
dropped connection, a stage tab bar on narrow screens.
|
|
76
|
+
- **Next step that keeps up** — sessions pass the next step and who acts next together with a
|
|
77
|
+
stage change or a report; a next step left over from before the last stage change shows muted
|
|
78
|
+
and marked "stale".
|
|
79
|
+
- **Done column and archive** — the `done` column shows tasks closed in the last
|
|
80
|
+
`done_window_days` (default 7); older ones are archived and come back with "Show archived" or a
|
|
81
|
+
search by key or title (`/p/<project>?archived=1`, `?q=…`). Done cards hide "waiting on" and the
|
|
82
|
+
next step.
|
|
83
|
+
- **External tracker mark** — a task can carry its issue in any tracker (tracker name, issue key,
|
|
84
|
+
optional link) and a "work log entered" mark. The card shows the issue as a badge at the top (a
|
|
85
|
+
link when a URL is set, ✓ once logged). With `require_tracker_log = true` a done task without
|
|
86
|
+
the mark shows "not logged" and stays out of the archive until it is marked. Every issue key a
|
|
87
|
+
task has had is kept in its tracker history (task dialog, `/t/<key>`, `task_get`), and new work
|
|
88
|
+
on a logged task (a report, a progress change, a move back from `live` or `done`) clears the
|
|
89
|
+
mark again, so it always means "the log covers everything done".
|
|
90
|
+
- **MCP server** — Streamable HTTP at `/mcp` in the same process: create and update tasks, change
|
|
91
|
+
stages, keep a task's description and progress summary current, add reports and decisions, bind
|
|
92
|
+
and unbind sessions, get a markdown snapshot of a project. A plain session name never replaces a
|
|
93
|
+
task's desktop session binding: it becomes that session's alias. `task_patch` takes any task
|
|
94
|
+
fields as one JSON object, so clients with an older tool schema can still set new fields.
|
|
95
|
+
- **Working rules** — the server tells every connected session how to work with the board (MCP
|
|
96
|
+
instructions: read the snapshot, pick a task, keep next step / waiting on / progress current,
|
|
97
|
+
report as `state · size · gist`) and serves the rules as data: report format, what a stage move
|
|
98
|
+
needs (by default a report before `test`, `progress` before `done`), a description template and
|
|
99
|
+
free-text guidance. Global rules come from `config.toml`, a project can override them; agents read
|
|
100
|
+
them through `rules_get` or `relaybay://rules/<project>`, and `project_snapshot` starts with the
|
|
101
|
+
rules hash. A stage move that misses a rule succeeds with a warning (or is refused with
|
|
102
|
+
`rules_mode = "strict"`), in MCP responses and on the board.
|
|
103
|
+
- **Local and private** — one process, SQLite, binds to `127.0.0.1`, token-protected, no telemetry,
|
|
104
|
+
no outbound calls, no CDN.
|
|
105
|
+
|
|
106
|
+
## Try it with demo data
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
relaybay demo --home ./relaybay-demo # acme-shop and demo-api, tasks in every stage
|
|
110
|
+
relaybay serve --home ./relaybay-demo --port 8766
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Connect Claude Code
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
claude mcp add --transport http --scope user relaybay http://127.0.0.1:8765/mcp \
|
|
117
|
+
--header "Authorization: Bearer <token>"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`user` scope adds relaybay once for all repositories. See
|
|
121
|
+
[docs/connect-claude-code.md](docs/connect-claude-code.md) for `.mcp.json` and a short instruction
|
|
122
|
+
snippet for your project's `CLAUDE.md` / `AGENTS.md` that tells the agent when to call the tools.
|
|
123
|
+
|
|
124
|
+
### Live session status (hooks)
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
relaybay setup # what it found, the exact diff and its hash
|
|
128
|
+
relaybay setup --apply --expect <hash> # adds relaybay's hooks to ~/.claude/settings.json
|
|
129
|
+
relaybay setup --check # end-to-end check, one ok/FAIL line per item
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The hooks let the board show whether each session is working, waiting for you, idle or gone, and
|
|
133
|
+
unbind a session from its task when it ends. Setup adds only its own entries (other hooks stay as
|
|
134
|
+
they are), never writes the token into the file, and `--remove` takes them out again. The same plan
|
|
135
|
+
and buttons are on the board under **Integrations**. Hooks stay silent when relaybay is not
|
|
136
|
+
running. Details: [docs/connect-claude-code.md](docs/connect-claude-code.md#3-live-session-status-hooks).
|
|
137
|
+
|
|
138
|
+
### Schema changes and long-running sessions
|
|
139
|
+
|
|
140
|
+
A Claude Code session keeps the parameter schema of a tool it already loaded, even after relaybay
|
|
141
|
+
restarts and the client reconnects: new tools appear, but new parameters of an existing tool do
|
|
142
|
+
not. Use `task_patch(task, fields={...})` for fields your client does not know yet (the allowed
|
|
143
|
+
names are at the end of `task_get` and in `relaybay://schema/task`), or refresh the schemas by
|
|
144
|
+
reconnecting the server in the client (`/mcp` in the CLI) or starting a new session. See
|
|
145
|
+
[docs/mcp-tools.md](docs/mcp-tools.md#schema-changes-and-long-running-sessions).
|
|
146
|
+
The tool reference is in [docs/mcp-tools.md](docs/mcp-tools.md).
|
|
147
|
+
|
|
148
|
+
## Configuration
|
|
149
|
+
|
|
150
|
+
Settings come from defaults, then `config.toml` in the data directory, then `RELAYBAY_*` environment
|
|
151
|
+
variables, then command-line flags.
|
|
152
|
+
|
|
153
|
+
| Setting | Default | Env | Flag |
|
|
154
|
+
|---|---|---|---|
|
|
155
|
+
| data directory | per-user data dir (`platformdirs`) | `RELAYBAY_HOME` | `--home` |
|
|
156
|
+
| bind address | `127.0.0.1` | `RELAYBAY_HOST` | `--host` |
|
|
157
|
+
| port | `8765` | `RELAYBAY_PORT` | `--port` |
|
|
158
|
+
| extra allowed Host names | none | `RELAYBAY_ALLOWED_HOSTS` (comma-separated) | — |
|
|
159
|
+
| desktop session link | `claude://claude.ai/epitaxy/{id}` | `RELAYBAY_DESKTOP_LINK_TEMPLATE` | — |
|
|
160
|
+
| days a done task stays in the done column | `7` | `RELAYBAY_DONE_WINDOW_DAYS` | — |
|
|
161
|
+
| keep done tasks without the tracker work log on the board | `false` | `RELAYBAY_REQUIRE_TRACKER_LOG` | — |
|
|
162
|
+
| what a stage move that misses a rule does: `warn` or `strict` | `warn` | `RELAYBAY_RULES_MODE` | — |
|
|
163
|
+
| folder with Claude Code's `.claude/` and `.claude.json` (setup, Integrations) | your home directory | `RELAYBAY_CLAUDE_HOME` | `--claude-home` |
|
|
164
|
+
|
|
165
|
+
The data directory holds `relaybay.sqlite`, the `token` file and the optional `config.toml`:
|
|
166
|
+
|
|
167
|
+
```toml
|
|
168
|
+
port = 8765
|
|
169
|
+
allowed_hosts = ["my-laptop.lan"] # needed only when you bind to a LAN address
|
|
170
|
+
desktop_link_template = "claude://claude.ai/epitaxy/{id}" # {id} = desktop session id (local_…)
|
|
171
|
+
done_window_days = 7 # older done tasks are archived
|
|
172
|
+
require_tracker_log = false # true: done tasks without the tracker work log stay and show "not logged"
|
|
173
|
+
rules_mode = "warn" # "strict": a stage move that misses a rule is refused
|
|
174
|
+
|
|
175
|
+
[stages.labels] # display names; the stage keys stay plan/dev/test/live/done
|
|
176
|
+
dev = "in progress"
|
|
177
|
+
done = "shipped"
|
|
178
|
+
|
|
179
|
+
[reports.labels] # report badges: inspected/changed/verified/committed/pushed/blocked, S/M/L
|
|
180
|
+
verified = "checked"
|
|
181
|
+
|
|
182
|
+
[reports.hints] # badge tooltips
|
|
183
|
+
M = "medium change"
|
|
184
|
+
|
|
185
|
+
[rules] # global working rules, merged over the built-in defaults
|
|
186
|
+
guidance = "Ask the owner before anything goes live."
|
|
187
|
+
description_template = "Goal:\nWhy:\nDone when:"
|
|
188
|
+
|
|
189
|
+
[rules.report_format] # states/sizes: a subset of the built-in ones
|
|
190
|
+
sizes = ["S", "M", "L"]
|
|
191
|
+
|
|
192
|
+
[rules.stage_requirements] # per target stage; a list replaces the default, [] drops it
|
|
193
|
+
test = [{ kind = "report_since_stage_change" }]
|
|
194
|
+
done = [{ kind = "field_present", field = "progress" }]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
A rules error in `config.toml` (unknown key, stage, rule kind or field) stops `relaybay serve`
|
|
198
|
+
with a message that names the key. A broken project override never stops the server: it is
|
|
199
|
+
logged, the project falls back to the global rules, and `rules_get` and `project_snapshot` say
|
|
200
|
+
"project override ignored: <error>". Project overrides and the merge rules are described in
|
|
201
|
+
[docs/mcp-tools.md](docs/mcp-tools.md#working-rules).
|
|
202
|
+
|
|
203
|
+
`relaybay token --rotate` creates a new token; restart the server and update the Claude Code entry.
|
|
204
|
+
|
|
205
|
+
### Troubleshooting: "token not valid"
|
|
206
|
+
|
|
207
|
+
Each data folder has its own token. `relaybay serve` prints the folder it uses (`Data folder: …`);
|
|
208
|
+
run `relaybay token` with the same `--home` (or `RELAYBAY_HOME`). `relaybay token` prints its folder
|
|
209
|
+
and warns when the server on the port uses a different token (another folder, or a rotation without
|
|
210
|
+
a restart). After `relaybay token --rotate`, restart the server. `relaybay doctor` checks this and
|
|
211
|
+
everything else in one command ([troubleshooting](https://codenator81.github.io/relaybay/how-to/troubleshooting/)).
|
|
212
|
+
|
|
213
|
+
## Roadmap
|
|
214
|
+
|
|
215
|
+
- **0.1.0** — board, MCP tools, working rules, hooks and `relaybay setup`, packaging
|
|
216
|
+
(`uv tool install`, `uvx`, `pipx`, Docker), `relaybay doctor`, docs site, demo workspace.
|
|
217
|
+
- **0.2.0** — sidebar navigation and Inbox, comments to agents, project environments and access.
|
|
218
|
+
- **0.3.0** — review checklist with screenshots, memory and documents.
|
|
219
|
+
- **Later** — annotations, map and usage, rules versioning, intake, agents started from relaybay.
|
|
220
|
+
|
|
221
|
+
Details and status: [docs/ROADMAP.md](docs/ROADMAP.md). Designs of upcoming steps are in
|
|
222
|
+
[docs/design/](docs/design/index.md), decisions in [docs/adr/](docs/adr/). relaybay sends no
|
|
223
|
+
telemetry.
|
|
224
|
+
|
|
225
|
+
## Contributing and feedback
|
|
226
|
+
|
|
227
|
+
- Questions, ideas, show and tell: [Discussions](https://github.com/Codenator81/relaybay/discussions).
|
|
228
|
+
- Bugs and feature requests: [issues](https://github.com/Codenator81/relaybay/issues/new/choose)
|
|
229
|
+
(include `relaybay doctor` output for bugs).
|
|
230
|
+
- Security problems: report privately, see [SECURITY.md](SECURITY.md).
|
|
231
|
+
- Code: [CONTRIBUTING.md](CONTRIBUTING.md); AI coding tools: [AGENTS.md](AGENTS.md). Everyone
|
|
232
|
+
follows the [Code of Conduct](CODE_OF_CONDUCT.md); how decisions are made:
|
|
233
|
+
[GOVERNANCE.md](GOVERNANCE.md).
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
[MIT](LICENSE)
|