bugcap 0.2.2__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.
Files changed (81) hide show
  1. bugcap-0.2.2/LICENSE +21 -0
  2. bugcap-0.2.2/PKG-INFO +225 -0
  3. bugcap-0.2.2/README.md +209 -0
  4. bugcap-0.2.2/pyproject.toml +29 -0
  5. bugcap-0.2.2/setup.cfg +4 -0
  6. bugcap-0.2.2/src/bugcap/__init__.py +1 -0
  7. bugcap-0.2.2/src/bugcap/agent_api.py +221 -0
  8. bugcap-0.2.2/src/bugcap/backends.py +133 -0
  9. bugcap-0.2.2/src/bugcap/capture.py +84 -0
  10. bugcap-0.2.2/src/bugcap/cli.py +942 -0
  11. bugcap-0.2.2/src/bugcap/config.py +86 -0
  12. bugcap-0.2.2/src/bugcap/dashboard/__init__.py +3 -0
  13. bugcap-0.2.2/src/bugcap/dashboard/api.py +105 -0
  14. bugcap-0.2.2/src/bugcap/dashboard/media.py +73 -0
  15. bugcap-0.2.2/src/bugcap/dashboard/server.py +213 -0
  16. bugcap-0.2.2/src/bugcap/dashboard/static/app.css +43 -0
  17. bugcap-0.2.2/src/bugcap/dashboard/static/app.js +179 -0
  18. bugcap-0.2.2/src/bugcap/dashboard/static/index.html +45 -0
  19. bugcap-0.2.2/src/bugcap/drafts.py +83 -0
  20. bugcap-0.2.2/src/bugcap/errors.py +30 -0
  21. bugcap-0.2.2/src/bugcap/ghcli.py +175 -0
  22. bugcap-0.2.2/src/bugcap/ingest.py +210 -0
  23. bugcap-0.2.2/src/bugcap/live.py +292 -0
  24. bugcap-0.2.2/src/bugcap/live_session.py +125 -0
  25. bugcap-0.2.2/src/bugcap/logs.py +74 -0
  26. bugcap-0.2.2/src/bugcap/mcp_server.py +221 -0
  27. bugcap-0.2.2/src/bugcap/paths.py +116 -0
  28. bugcap-0.2.2/src/bugcap/recorder.py +390 -0
  29. bugcap-0.2.2/src/bugcap/refs.py +213 -0
  30. bugcap-0.2.2/src/bugcap/repo.py +138 -0
  31. bugcap-0.2.2/src/bugcap/service.py +418 -0
  32. bugcap-0.2.2/src/bugcap/store.py +485 -0
  33. bugcap-0.2.2/src/bugcap/sync.py +424 -0
  34. bugcap-0.2.2/src/bugcap/tomlio.py +37 -0
  35. bugcap-0.2.2/src/bugcap/validation.py +74 -0
  36. bugcap-0.2.2/src/bugcap.egg-info/PKG-INFO +225 -0
  37. bugcap-0.2.2/src/bugcap.egg-info/SOURCES.txt +79 -0
  38. bugcap-0.2.2/src/bugcap.egg-info/dependency_links.txt +1 -0
  39. bugcap-0.2.2/src/bugcap.egg-info/entry_points.txt +2 -0
  40. bugcap-0.2.2/src/bugcap.egg-info/requires.txt +9 -0
  41. bugcap-0.2.2/src/bugcap.egg-info/top_level.txt +1 -0
  42. bugcap-0.2.2/tests/test_agent_api.py +165 -0
  43. bugcap-0.2.2/tests/test_backends.py +77 -0
  44. bugcap-0.2.2/tests/test_capture.py +95 -0
  45. bugcap-0.2.2/tests/test_cli_attach.py +171 -0
  46. bugcap-0.2.2/tests/test_cli_dashboard.py +46 -0
  47. bugcap-0.2.2/tests/test_cli_init_capture_list.py +88 -0
  48. bugcap-0.2.2/tests/test_cli_live_headless.py +27 -0
  49. bugcap-0.2.2/tests/test_cli_media.py +145 -0
  50. bugcap-0.2.2/tests/test_cli_record.py +123 -0
  51. bugcap-0.2.2/tests/test_cli_setup.py +81 -0
  52. bugcap-0.2.2/tests/test_cli_triage.py +62 -0
  53. bugcap-0.2.2/tests/test_dashboard_api.py +99 -0
  54. bugcap-0.2.2/tests/test_dashboard_media.py +63 -0
  55. bugcap-0.2.2/tests/test_dashboard_mutations.py +45 -0
  56. bugcap-0.2.2/tests/test_dashboard_security.py +94 -0
  57. bugcap-0.2.2/tests/test_dashboard_ui_static.py +24 -0
  58. bugcap-0.2.2/tests/test_drafts.py +43 -0
  59. bugcap-0.2.2/tests/test_ghcli.py +77 -0
  60. bugcap-0.2.2/tests/test_github_media_sync.py +111 -0
  61. bugcap-0.2.2/tests/test_github_pull.py +85 -0
  62. bugcap-0.2.2/tests/test_github_sync.py +184 -0
  63. bugcap-0.2.2/tests/test_ingest.py +77 -0
  64. bugcap-0.2.2/tests/test_ingest_url.py +78 -0
  65. bugcap-0.2.2/tests/test_live_session.py +125 -0
  66. bugcap-0.2.2/tests/test_mcp.py +116 -0
  67. bugcap-0.2.2/tests/test_mcp_logging.py +174 -0
  68. bugcap-0.2.2/tests/test_paths.py +59 -0
  69. bugcap-0.2.2/tests/test_recorder_argv.py +72 -0
  70. bugcap-0.2.2/tests/test_recorder_devices.py +22 -0
  71. bugcap-0.2.2/tests/test_recorder_media_real.py +52 -0
  72. bugcap-0.2.2/tests/test_recorder_run.py +254 -0
  73. bugcap-0.2.2/tests/test_refs.py +61 -0
  74. bugcap-0.2.2/tests/test_refs_validate_rewrite.py +48 -0
  75. bugcap-0.2.2/tests/test_regression_output.py +50 -0
  76. bugcap-0.2.2/tests/test_repo_config.py +81 -0
  77. bugcap-0.2.2/tests/test_repo_values.py +281 -0
  78. bugcap-0.2.2/tests/test_service_media.py +101 -0
  79. bugcap-0.2.2/tests/test_service_refs.py +123 -0
  80. bugcap-0.2.2/tests/test_store_migration.py +226 -0
  81. bugcap-0.2.2/tests/test_sync_consent.py +142 -0
bugcap-0.2.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Konrad Tagnon Amen ALAHASSA
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.
bugcap-0.2.2/PKG-INFO ADDED
@@ -0,0 +1,225 @@
1
+ Metadata-Version: 2.4
2
+ Name: bugcap
3
+ Version: 0.2.2
4
+ Summary: Local-first, agent-readable bug capture: annotated screenshots + notes, stored locally, synced to trackers on your own schedule.
5
+ Author: Konrad Tagnon Amen ALAHASSA
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: tomli>=2; python_version < "3.11"
11
+ Provides-Extra: mcp
12
+ Requires-Dist: mcp<2,>=1.2; extra == "mcp"
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=7; extra == "dev"
15
+ Dynamic: license-file
16
+
17
+ <p align="center">
18
+ <img src="docs/assets/logo.svg" alt="bugcap" width="96">
19
+ </p>
20
+
21
+ <h1 align="center">bugcap</h1>
22
+
23
+ <p align="center">
24
+ <b>Bug reports your AI agent can actually read.</b><br>
25
+ Annotated screenshots and notes, stored on your machine, readable by coding agents over MCP, and synced to GitHub issues when you choose.
26
+ </p>
27
+
28
+ <p align="center">
29
+ <a href="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml"><img alt="tests" src="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml/badge.svg"></a>
30
+ <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
31
+ <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
32
+ <a href="https://amenalahassa.github.io/bugcap/"><img alt="docs" src="https://img.shields.io/badge/docs-website-d9480f"></a>
33
+ </p>
34
+
35
+ <p align="center">
36
+ <a href="https://amenalahassa.github.io/bugcap/">Website</a> ·
37
+ <a href="https://amenalahassa.github.io/bugcap/usage.html">Usage guide</a> ·
38
+ <a href="#quick-start">Quick start</a> ·
39
+ <a href="#connect-your-agent-mcp">Agents (MCP)</a> ·
40
+ <a href="CHANGELOG.md">Changelog</a>
41
+ </p>
42
+
43
+ <p align="center">
44
+ <img src="docs/assets/demo.gif" alt="bugcap capturing an annotated bug and listing the report" width="760">
45
+ </p>
46
+
47
+ ---
48
+
49
+ ## Why bugcap
50
+
51
+ Reviewing an app for bugs usually leaves you with two disconnected things: a screenshot and a
52
+ mental note. By the time you file the issue, the context is gone. Once the screenshot is attached
53
+ to a GitHub issue, it becomes **unreadable to an API token**. The CDN only resolves in a browser
54
+ session, so an agent using `gh` can read the text but never the picture that explains the bug.
55
+
56
+ bugcap keeps the whole loop in one place:
57
+
58
+ | | |
59
+ |---|---|
60
+ | 📸 **Capture at the moment** | Annotated screenshots through `flameshot`, `satty` or `screencapture`. No new annotation UI. |
61
+ | 🗂️ **Local record** | A SQLite index and PNGs on disk. Nothing depends on GitHub being reachable. |
62
+ | 🤖 **Agent-readable** | A stdio MCP server hands reports, images included, to Claude Code and other agents. |
63
+ | 🔁 **Sync when ready** | Push to a GitHub issue with the usual inline image, plus a plain copy agents can read. |
64
+ | 🎞️ **Record what happens** | Short screen recordings as animated GIF, video or keyframes, with size caps. |
65
+ | 🖥️ **Triage in a browser** | A local dashboard on `127.0.0.1` to browse, filter and set statuses. |
66
+ | 🪟 **Live mode** | An always-on-top window for reporting many bugs in a row. |
67
+
68
+ ## Quick start
69
+
70
+ ```bash
71
+ # install (from GitHub until the PyPI release is live)
72
+ pipx install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap'
73
+
74
+ bugcap setup --yes # detects or installs a capture tool
75
+ cd ~/code/myproject && bugcap init # scope reports to this repo
76
+
77
+ bugcap capture --title "Login fails" --note "Error toast after submit" --tag auth
78
+ bugcap list
79
+ bugcap dashboard --open # browse and triage in the browser
80
+ ```
81
+
82
+ The [usage guide](https://amenalahassa.github.io/bugcap/usage.html) covers every command: images
83
+ and labels, recording, live mode, `@` references, GitHub pull and sync, and the MCP tools.
84
+
85
+ ## Connect your agent (MCP)
86
+
87
+ Requires the `mcp` extra. Then give your agent access to the reports:
88
+
89
+ ```bash
90
+ claude mcp add bugcap -- bugcap mcp-serve
91
+ ```
92
+
93
+ Or in a project's `.mcp.json`:
94
+
95
+ ```json
96
+ { "mcpServers": { "bugcap": { "command": "bugcap", "args": ["mcp-serve"] } } }
97
+ ```
98
+
99
+ The server exposes six tools: `list_reports`, `get_report` (returns the screenshot), `request_screenshot`,
100
+ `pull_issues`, `attach_image` and `update_notes`. Logs go to `logs/mcp-server.log` in the data
101
+ directory, never to stdout.
102
+
103
+ Ask your agent something like *"list the open bugcap reports for this repo and fix the one with
104
+ the error toast"*. It can read the picture because it's a local file, not a CDN link.
105
+
106
+ ## How it works
107
+
108
+ ```
109
+ capture ──► local store (SQLite + images/) ──► MCP / dashboard / CLI (read by agents and you)
110
+ │
111
+ └──► sync ──► GitHub issue + committed image copy (readable with gh api)
112
+ ```
113
+
114
+ - **`capture` / `attach` / `record`** write to the store.
115
+ - **`mcp-serve`, `dashboard`, `list`, `show`** read from it.
116
+ - **`sync`** is the only thing that talks to a tracker, and only when you run it.
117
+
118
+ ## Status
119
+
120
+ Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images,
121
+ `@` references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other
122
+ trackers (item 9) are deferred. The `Destination` seam is in place, so they can be added without
123
+ changing the CLI. See [ROADMAP.md](ROADMAP.md).
124
+
125
+ ## Installation
126
+
127
+ Requires Python 3.10 or newer. The core CLI uses only the standard library (plus `tomli` before
128
+ Python 3.11). The MCP server is an optional extra.
129
+
130
+ ```bash
131
+ pipx install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap' # recommended
132
+ uv tool install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap'
133
+ pip install -e '.[dev,mcp]' # development
134
+ ```
135
+
136
+ Supported capture backends: [`flameshot`](https://flameshot.org/) (cross-platform, recommended),
137
+ [`satty`](https://github.com/Satty-org/Satty) with `grim` (Linux/Wayland), and `screencapture`
138
+ (macOS). Run `bugcap setup` to see what's detected. You can always import an existing image with
139
+ `bugcap capture --image PATH`.
140
+
141
+ ## Documentation
142
+
143
+ Full guide: **[amenalahassa.github.io/bugcap/usage.html](https://amenalahassa.github.io/bugcap/usage.html)**
144
+ covers capture, images, recording, live mode, triage, `@` references, the dashboard, GitHub
145
+ pull and sync, MCP, and where data lives per OS.
146
+
147
+ Notes on the more involved behaviour:
148
+
149
+ - **`@` references.** `@1` or `@login-error` in a note points at an image. They are validated on save, and relabelling or removing a referenced image needs `--force`.
150
+ - **Repo values** (`init`, `sync`, `config repo set`) are checked for format and, with `gh`, for existence. Changing the repo identity offers to move existing reports.
151
+ - **Media sync** over `[sync] max_upload_mb` (default 25) is skipped with a warning.
152
+
153
+ ## Development
154
+
155
+ See [DEVELOPMENT.md](DEVELOPMENT.md). Run the tests with:
156
+
157
+ ```bash
158
+ uv run --extra dev --extra mcp pytest -q
159
+ ```
160
+
161
+ ## Architecture
162
+
163
+ Module map (`src/bugcap/`):
164
+
165
+ | Module | Responsibility |
166
+ |---|---|
167
+ | `paths.py` | Per-OS data/config dirs; `BUGCAP_HOME` override. |
168
+ | `capture.py` | Import or capture images (`flameshot`/`satty`+`grim`/`screencapture`); `has_display()`. |
169
+ | `backends.py` | Capture-tool detection, per-OS install commands, manual guidance. |
170
+ | `store.py` | SQLite store (`reports`, `media`, `media_frames`; schema v2), `PRAGMA user_version` migrations, report API, `transaction()`. |
171
+ | `service.py` | **Shared rules** used by the CLI, MCP, dashboard and live mode: media add/relabel/remove, notes validation, reference rewrite, queries. Raises `ServiceError`. |
172
+ | `ingest.py` | Path/glob/URL inputs: magic-byte validation, size/timeout/redirect limits, atomic copy into `images/`. |
173
+ | `refs.py` | `@` reference parsing (code/email aware), validation, rewrite, display. |
174
+ | `recorder.py` | `ffmpeg`/`wf-recorder` argv per OS, stop/caps watchdogs, animated/frames post-processing. |
175
+ | `live.py` + `live_session.py` + `drafts.py` | Tk control window (thin) over a pure state machine; drafts on disk. |
176
+ | `dashboard/` | `http.server` UI + JSON API (loopback, Host/Origin checks, write token, Range media, static allowlist). |
177
+ | `repo.py` + `tomlio.py` | `.bugcap.toml` discovery/read/write (tag, github slug, `[sync]`). |
178
+ | `config.py` | Global `config.toml`: `[sync]` defaults, `[consent]` for image commits, `[log]`. |
179
+ | `validation.py` | Format checks for repo slugs, images path and branch names. |
180
+ | `logs.py` | `mcp-serve` logging (rotating file + stderr, never stdout). |
181
+ | `ghcli.py` | Thin `gh` wrapper (argv lists; large payloads via stdin). **Transport.** |
182
+ | `sync.py` | `Destination` protocol, `GitHubDestination`, `pull_issues`, `sync_report`. **Policy.** |
183
+ | `agent_api.py` | SDK-free tool logic for the six MCP tools. |
184
+ | `mcp_server.py` | Lazy-imports the `mcp` SDK; registers the `agent_api` tools over stdio. |
185
+ | `cli.py` | All subcommands. |
186
+
187
+ The **store is the one shared surface**. Capture writes to it; the CLI, the MCP server, and the
188
+ sync layer only read/update it — nothing talks to a tracker except `sync.py` (via `ghcli.py`), and
189
+ nothing requires a tracker to exist for capture to be useful.
190
+
191
+ **Extension seam (roadmap 6 & 9):** `sync.py` depends only on the small `Destination` protocol
192
+ (`ensure_ready`, `repo_visibility`, `get_file`, `put_file`, `create_issue`, `comment`,
193
+ `supports_attach`) and on the report's `synced_refs`. A future object store or tracker implements
194
+ that protocol — the CLI and store don't change. Refs are namespaced per destination:
195
+
196
+ - `github.issue` → `owner/repo#N`
197
+ - `github.comment_hash` → sha256 of the last synced content (so re-sync comments only on change)
198
+ - `github.image.<basename>` / `github.media.<basename>` → `owner/repo:path@commit` (so each file is committed at most once)
199
+ - `github.frame.<idx>.<n>` and `github.frames.<idx>` → keyframes of a recording (one commit per frame; GitHub's contents API commits one file at a time)
200
+
201
+ These refs also make pull and sync **idempotent and resumable**: each step is persisted as it
202
+ succeeds, so a re-run skips what is already recorded.
203
+
204
+ ## Roadmap
205
+
206
+ See [ROADMAP.md](ROADMAP.md).
207
+
208
+ ## Design notes / deliberate non-goals
209
+
210
+ - **No cloud storage by default, no vendor account.** The store is plain files on your disk. Sync
211
+ (GitHub, and optionally an S3/R2 object store) is opt-in and explicit, per report.
212
+ - **Not a GitHub attachment replacement.** The CDN-attached image stays for humans browsing the
213
+ issue normally; the repo-committed copy exists purely so agents can read it. Both are written
214
+ on sync, deliberately redundant.
215
+ - **Not using Git LFS for synced copies.** GitHub's Contents API returns LFS pointer files, not
216
+ the real bytes, for LFS-tracked paths — which would silently defeat the entire point of
217
+ committing the copy. Plain commits are used instead; if screenshot volume ever outgrows that,
218
+ the right next step is an external object store with its own token-authable download URLs, not
219
+ LFS.
220
+ - **Annotation UI is not reinvented.** `bugcap` is glue around an existing capture/annotate tool,
221
+ not a new one.
222
+
223
+ ## License
224
+
225
+ MIT — see [LICENSE](LICENSE).
bugcap-0.2.2/README.md ADDED
@@ -0,0 +1,209 @@
1
+ <p align="center">
2
+ <img src="docs/assets/logo.svg" alt="bugcap" width="96">
3
+ </p>
4
+
5
+ <h1 align="center">bugcap</h1>
6
+
7
+ <p align="center">
8
+ <b>Bug reports your AI agent can actually read.</b><br>
9
+ Annotated screenshots and notes, stored on your machine, readable by coding agents over MCP, and synced to GitHub issues when you choose.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml"><img alt="tests" src="https://github.com/amenalahassa/bugcap/actions/workflows/release.yml/badge.svg"></a>
14
+ <img alt="python" src="https://img.shields.io/badge/python-3.10%2B-3776ab?logo=python&logoColor=white">
15
+ <a href="LICENSE"><img alt="license" src="https://img.shields.io/badge/license-MIT-green"></a>
16
+ <a href="https://amenalahassa.github.io/bugcap/"><img alt="docs" src="https://img.shields.io/badge/docs-website-d9480f"></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://amenalahassa.github.io/bugcap/">Website</a> ·
21
+ <a href="https://amenalahassa.github.io/bugcap/usage.html">Usage guide</a> ·
22
+ <a href="#quick-start">Quick start</a> ·
23
+ <a href="#connect-your-agent-mcp">Agents (MCP)</a> ·
24
+ <a href="CHANGELOG.md">Changelog</a>
25
+ </p>
26
+
27
+ <p align="center">
28
+ <img src="docs/assets/demo.gif" alt="bugcap capturing an annotated bug and listing the report" width="760">
29
+ </p>
30
+
31
+ ---
32
+
33
+ ## Why bugcap
34
+
35
+ Reviewing an app for bugs usually leaves you with two disconnected things: a screenshot and a
36
+ mental note. By the time you file the issue, the context is gone. Once the screenshot is attached
37
+ to a GitHub issue, it becomes **unreadable to an API token**. The CDN only resolves in a browser
38
+ session, so an agent using `gh` can read the text but never the picture that explains the bug.
39
+
40
+ bugcap keeps the whole loop in one place:
41
+
42
+ | | |
43
+ |---|---|
44
+ | 📸 **Capture at the moment** | Annotated screenshots through `flameshot`, `satty` or `screencapture`. No new annotation UI. |
45
+ | 🗂️ **Local record** | A SQLite index and PNGs on disk. Nothing depends on GitHub being reachable. |
46
+ | 🤖 **Agent-readable** | A stdio MCP server hands reports, images included, to Claude Code and other agents. |
47
+ | 🔁 **Sync when ready** | Push to a GitHub issue with the usual inline image, plus a plain copy agents can read. |
48
+ | 🎞️ **Record what happens** | Short screen recordings as animated GIF, video or keyframes, with size caps. |
49
+ | 🖥️ **Triage in a browser** | A local dashboard on `127.0.0.1` to browse, filter and set statuses. |
50
+ | 🪟 **Live mode** | An always-on-top window for reporting many bugs in a row. |
51
+
52
+ ## Quick start
53
+
54
+ ```bash
55
+ # install (from GitHub until the PyPI release is live)
56
+ pipx install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap'
57
+
58
+ bugcap setup --yes # detects or installs a capture tool
59
+ cd ~/code/myproject && bugcap init # scope reports to this repo
60
+
61
+ bugcap capture --title "Login fails" --note "Error toast after submit" --tag auth
62
+ bugcap list
63
+ bugcap dashboard --open # browse and triage in the browser
64
+ ```
65
+
66
+ The [usage guide](https://amenalahassa.github.io/bugcap/usage.html) covers every command: images
67
+ and labels, recording, live mode, `@` references, GitHub pull and sync, and the MCP tools.
68
+
69
+ ## Connect your agent (MCP)
70
+
71
+ Requires the `mcp` extra. Then give your agent access to the reports:
72
+
73
+ ```bash
74
+ claude mcp add bugcap -- bugcap mcp-serve
75
+ ```
76
+
77
+ Or in a project's `.mcp.json`:
78
+
79
+ ```json
80
+ { "mcpServers": { "bugcap": { "command": "bugcap", "args": ["mcp-serve"] } } }
81
+ ```
82
+
83
+ The server exposes six tools: `list_reports`, `get_report` (returns the screenshot), `request_screenshot`,
84
+ `pull_issues`, `attach_image` and `update_notes`. Logs go to `logs/mcp-server.log` in the data
85
+ directory, never to stdout.
86
+
87
+ Ask your agent something like *"list the open bugcap reports for this repo and fix the one with
88
+ the error toast"*. It can read the picture because it's a local file, not a CDN link.
89
+
90
+ ## How it works
91
+
92
+ ```
93
+ capture ──► local store (SQLite + images/) ──► MCP / dashboard / CLI (read by agents and you)
94
+ │
95
+ └──► sync ──► GitHub issue + committed image copy (readable with gh api)
96
+ ```
97
+
98
+ - **`capture` / `attach` / `record`** write to the store.
99
+ - **`mcp-serve`, `dashboard`, `list`, `show`** read from it.
100
+ - **`sync`** is the only thing that talks to a tracker, and only when you run it.
101
+
102
+ ## Status
103
+
104
+ Working. Roadmap items 1–5, 7 and 8 are implemented and tested, along with spec 002 (images,
105
+ `@` references, recording, live mode and the dashboard). S3/R2 object storage (item 6) and other
106
+ trackers (item 9) are deferred. The `Destination` seam is in place, so they can be added without
107
+ changing the CLI. See [ROADMAP.md](ROADMAP.md).
108
+
109
+ ## Installation
110
+
111
+ Requires Python 3.10 or newer. The core CLI uses only the standard library (plus `tomli` before
112
+ Python 3.11). The MCP server is an optional extra.
113
+
114
+ ```bash
115
+ pipx install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap' # recommended
116
+ uv tool install 'bugcap[mcp] @ git+https://github.com/amenalahassa/bugcap'
117
+ pip install -e '.[dev,mcp]' # development
118
+ ```
119
+
120
+ Supported capture backends: [`flameshot`](https://flameshot.org/) (cross-platform, recommended),
121
+ [`satty`](https://github.com/Satty-org/Satty) with `grim` (Linux/Wayland), and `screencapture`
122
+ (macOS). Run `bugcap setup` to see what's detected. You can always import an existing image with
123
+ `bugcap capture --image PATH`.
124
+
125
+ ## Documentation
126
+
127
+ Full guide: **[amenalahassa.github.io/bugcap/usage.html](https://amenalahassa.github.io/bugcap/usage.html)**
128
+ covers capture, images, recording, live mode, triage, `@` references, the dashboard, GitHub
129
+ pull and sync, MCP, and where data lives per OS.
130
+
131
+ Notes on the more involved behaviour:
132
+
133
+ - **`@` references.** `@1` or `@login-error` in a note points at an image. They are validated on save, and relabelling or removing a referenced image needs `--force`.
134
+ - **Repo values** (`init`, `sync`, `config repo set`) are checked for format and, with `gh`, for existence. Changing the repo identity offers to move existing reports.
135
+ - **Media sync** over `[sync] max_upload_mb` (default 25) is skipped with a warning.
136
+
137
+ ## Development
138
+
139
+ See [DEVELOPMENT.md](DEVELOPMENT.md). Run the tests with:
140
+
141
+ ```bash
142
+ uv run --extra dev --extra mcp pytest -q
143
+ ```
144
+
145
+ ## Architecture
146
+
147
+ Module map (`src/bugcap/`):
148
+
149
+ | Module | Responsibility |
150
+ |---|---|
151
+ | `paths.py` | Per-OS data/config dirs; `BUGCAP_HOME` override. |
152
+ | `capture.py` | Import or capture images (`flameshot`/`satty`+`grim`/`screencapture`); `has_display()`. |
153
+ | `backends.py` | Capture-tool detection, per-OS install commands, manual guidance. |
154
+ | `store.py` | SQLite store (`reports`, `media`, `media_frames`; schema v2), `PRAGMA user_version` migrations, report API, `transaction()`. |
155
+ | `service.py` | **Shared rules** used by the CLI, MCP, dashboard and live mode: media add/relabel/remove, notes validation, reference rewrite, queries. Raises `ServiceError`. |
156
+ | `ingest.py` | Path/glob/URL inputs: magic-byte validation, size/timeout/redirect limits, atomic copy into `images/`. |
157
+ | `refs.py` | `@` reference parsing (code/email aware), validation, rewrite, display. |
158
+ | `recorder.py` | `ffmpeg`/`wf-recorder` argv per OS, stop/caps watchdogs, animated/frames post-processing. |
159
+ | `live.py` + `live_session.py` + `drafts.py` | Tk control window (thin) over a pure state machine; drafts on disk. |
160
+ | `dashboard/` | `http.server` UI + JSON API (loopback, Host/Origin checks, write token, Range media, static allowlist). |
161
+ | `repo.py` + `tomlio.py` | `.bugcap.toml` discovery/read/write (tag, github slug, `[sync]`). |
162
+ | `config.py` | Global `config.toml`: `[sync]` defaults, `[consent]` for image commits, `[log]`. |
163
+ | `validation.py` | Format checks for repo slugs, images path and branch names. |
164
+ | `logs.py` | `mcp-serve` logging (rotating file + stderr, never stdout). |
165
+ | `ghcli.py` | Thin `gh` wrapper (argv lists; large payloads via stdin). **Transport.** |
166
+ | `sync.py` | `Destination` protocol, `GitHubDestination`, `pull_issues`, `sync_report`. **Policy.** |
167
+ | `agent_api.py` | SDK-free tool logic for the six MCP tools. |
168
+ | `mcp_server.py` | Lazy-imports the `mcp` SDK; registers the `agent_api` tools over stdio. |
169
+ | `cli.py` | All subcommands. |
170
+
171
+ The **store is the one shared surface**. Capture writes to it; the CLI, the MCP server, and the
172
+ sync layer only read/update it — nothing talks to a tracker except `sync.py` (via `ghcli.py`), and
173
+ nothing requires a tracker to exist for capture to be useful.
174
+
175
+ **Extension seam (roadmap 6 & 9):** `sync.py` depends only on the small `Destination` protocol
176
+ (`ensure_ready`, `repo_visibility`, `get_file`, `put_file`, `create_issue`, `comment`,
177
+ `supports_attach`) and on the report's `synced_refs`. A future object store or tracker implements
178
+ that protocol — the CLI and store don't change. Refs are namespaced per destination:
179
+
180
+ - `github.issue` → `owner/repo#N`
181
+ - `github.comment_hash` → sha256 of the last synced content (so re-sync comments only on change)
182
+ - `github.image.<basename>` / `github.media.<basename>` → `owner/repo:path@commit` (so each file is committed at most once)
183
+ - `github.frame.<idx>.<n>` and `github.frames.<idx>` → keyframes of a recording (one commit per frame; GitHub's contents API commits one file at a time)
184
+
185
+ These refs also make pull and sync **idempotent and resumable**: each step is persisted as it
186
+ succeeds, so a re-run skips what is already recorded.
187
+
188
+ ## Roadmap
189
+
190
+ See [ROADMAP.md](ROADMAP.md).
191
+
192
+ ## Design notes / deliberate non-goals
193
+
194
+ - **No cloud storage by default, no vendor account.** The store is plain files on your disk. Sync
195
+ (GitHub, and optionally an S3/R2 object store) is opt-in and explicit, per report.
196
+ - **Not a GitHub attachment replacement.** The CDN-attached image stays for humans browsing the
197
+ issue normally; the repo-committed copy exists purely so agents can read it. Both are written
198
+ on sync, deliberately redundant.
199
+ - **Not using Git LFS for synced copies.** GitHub's Contents API returns LFS pointer files, not
200
+ the real bytes, for LFS-tracked paths — which would silently defeat the entire point of
201
+ committing the copy. Plain commits are used instead; if screenshot volume ever outgrows that,
202
+ the right next step is an external object store with its own token-authable download URLs, not
203
+ LFS.
204
+ - **Annotation UI is not reinvented.** `bugcap` is glue around an existing capture/annotate tool,
205
+ not a new one.
206
+
207
+ ## License
208
+
209
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,29 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "bugcap"
7
+ version = "0.2.2"
8
+ description = "Local-first, agent-readable bug capture: annotated screenshots + notes, stored locally, synced to trackers on your own schedule."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Konrad Tagnon Amen ALAHASSA" }]
13
+ dependencies = ["tomli>=2; python_version < '3.11'"]
14
+
15
+ [project.optional-dependencies]
16
+ mcp = ["mcp>=1.2,<2"]
17
+ dev = ["pytest>=7"]
18
+
19
+ [project.scripts]
20
+ bugcap = "bugcap.cli:main"
21
+
22
+ [tool.setuptools.packages.find]
23
+ where = ["src"]
24
+
25
+ [tool.setuptools.package-data]
26
+ bugcap = ["dashboard/static/*"]
27
+
28
+ [tool.pytest.ini_options]
29
+ testpaths = ["tests"]
bugcap-0.2.2/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__ = "0.2.2"