ghosttrap-cli 0.3.13__tar.gz → 0.3.15__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghosttrap-cli
3
- Version: 0.3.13
3
+ Version: 0.3.15
4
4
  Summary: Watch for errors streaming from ghosttrap.io
5
5
  Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-cli
6
6
  Requires-Python: >=3.10
@@ -56,10 +56,11 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
56
56
 
57
57
  ## How it works
58
58
 
59
- - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
59
+ - **Setup** authenticates with GitHub (via the active `gh` account) to prove you have access to the repo, then saves a repo token locally. If your active `gh` account can't see the repo, setup fails with a clear message; switch with `gh auth switch` and retry.
60
60
  - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
61
61
  - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
62
- - Local state is stored in `~/.ghosttrap/config.json`
62
+ - Repos are tracked by GitHub's immutable repo id, so a rename or transfer doesn't require any action — the next connect picks up the new `owner/name` and your token keeps working
63
+ - Local state is stored in `~/.ghosttrap/config.json`, keyed by GitHub repo id
63
64
 
64
65
  ## Requirements
65
66
 
@@ -70,4 +71,8 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
70
71
 
71
72
  ## Privacy
72
73
 
73
- Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo ownership; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
74
+ Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo access; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
75
+
76
+ User context (Django user id + username) is **never** sent unless you opt in with `ghosttrap.init(token, send_user=True)` in your app. Server hostname is captured automatically.
77
+
78
+ Run `ghosttrap nuke` from inside a repo to permanently delete every server-side row for that repo (errors + the token itself). Requires typing the repo name to confirm.
@@ -47,10 +47,11 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
47
47
 
48
48
  ## How it works
49
49
 
50
- - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
50
+ - **Setup** authenticates with GitHub (via the active `gh` account) to prove you have access to the repo, then saves a repo token locally. If your active `gh` account can't see the repo, setup fails with a clear message; switch with `gh auth switch` and retry.
51
51
  - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
52
52
  - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
53
- - Local state is stored in `~/.ghosttrap/config.json`
53
+ - Repos are tracked by GitHub's immutable repo id, so a rename or transfer doesn't require any action — the next connect picks up the new `owner/name` and your token keeps working
54
+ - Local state is stored in `~/.ghosttrap/config.json`, keyed by GitHub repo id
54
55
 
55
56
  ## Requirements
56
57
 
@@ -61,4 +62,8 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
61
62
 
62
63
  ## Privacy
63
64
 
64
- Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo ownership; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
65
+ Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo access; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
66
+
67
+ User context (Django user id + username) is **never** sent unless you opt in with `ghosttrap.init(token, send_user=True)` in your app. Server hostname is captured automatically.
68
+
69
+ Run `ghosttrap nuke` from inside a repo to permanently delete every server-side row for that repo (errors + the token itself). Requires typing the repo name to confirm.
@@ -21,9 +21,10 @@ KNOWN_SKILL_HASHES = {
21
21
  "38810f43867a2a91420cc3dacbc71d2acabd7125596fd5b43f222b49725c9696", # v0.3.10
22
22
  "19b67d913dc5214ee4db3610bd8749da67324c174b904b5da71ee6de13e23e63", # v0.3.11
23
23
  "bf7768c3de266b7018d5c722c6c9991b487e7897786b3a406c460842cdcde8b5", # v0.3.12
24
+ "d3f594c4c3601a4594c18ebc5e16dfd4abad4ab97d56285ecc20634b919b6731", # v0.3.14
24
25
  }
25
26
 
26
- __version__ = "0.3.13"
27
+ __version__ = "0.3.15"
27
28
 
28
29
  GHOSTTRAP_SERVER = "wss://ghosttrap.io/stream/"
29
30
  CONFIG_DIR = os.path.expanduser("~/.ghosttrap")
@@ -70,7 +71,7 @@ Read `~/.ghosttrap/config.json` for state. It contains:
70
71
 
71
72
  1. Detect the current repo from `git config --get remote.origin.url` (returns `owner/name`).
72
73
  2. Find a matching entry in config by looking for one whose `owner`/`name` equals the detected slug. If no match, tell the user to run `ghosttrap setup`. (The owner/name on a config entry auto-refreshes from the server when the repo is renamed or transferred, so always match against the entry's stored owner/name, not the config key.)
73
- 3. If `sdk_installed` is false or missing: install the SDK (`pip install ghosttrap-sdk`), wire `ghosttrap.init("<token>")` into the app startup. For Django projects, also add `"ghosttrap.django.GhostTrapApp"` to INSTALLED_APPS (re-attaches logging handler after Django's dictConfig) and `"ghosttrap.django.GhostTrapMiddleware"` to MIDDLEWARE (catches unhandled view exceptions). The SDK auto-hooks into Celery task_failure if Celery is installed, and attaches a logging handler for logger.exception() calls. Use whatever pattern the project already uses for configuration (env vars, settings files, hardcoded — match the existing style). Then update the config: set `sdk_installed: true`, `sdk_version`, `init_file` to record what you did.
74
+ 3. If `sdk_installed` is false or missing: install the SDK (`pip install ghosttrap-sdk`), wire `ghosttrap.init("<token>")` into the app startup. For Django projects, also add `"ghosttrap.django.GhostTrapApp"` to INSTALLED_APPS (re-attaches logging handler after Django's dictConfig) and `"ghosttrap.django.GhostTrapMiddleware"` to MIDDLEWARE (catches unhandled view exceptions). The SDK auto-hooks into Celery task_failure if Celery is installed, and attaches a logging handler for logger.exception() calls. Use whatever pattern the project already uses for configuration (env vars, settings files, hardcoded — match the existing style). Then update the config: set `sdk_installed: true`, `sdk_version`, `init_file` to record what you did. Only pass `send_user=True` to `init()` if the user explicitly asks for user context in reports — it's PII and stays off by default.
74
75
  4. Run `ghosttrap peek --clear` with `run_in_background: true`. The `--clear` flag skips any stale backlog from prior sessions so you only get fresh errors.
75
76
 
76
77
  ## When peek returns
@@ -225,6 +226,10 @@ async def _connect_and_handle(server_url, token, config, once=False):
225
226
  async for message in ws:
226
227
  event = json.loads(message)
227
228
 
229
+ if event.get("type") == "rejected":
230
+ print(f"error: {event.get('message', event.get('code', 'rejected by server'))}", file=sys.stderr)
231
+ sys.exit(1)
232
+
228
233
  if event.get("type") == "subscribed":
229
234
  repos = event.get("repos", [])
230
235
  print(f"watching {len(repos)} repo(s)", file=sys.stderr)
@@ -316,8 +321,12 @@ async def setup(server_url, token):
316
321
  message = await asyncio.wait_for(ws.recv(), timeout=30)
317
322
  event = json.loads(message)
318
323
 
324
+ if event.get("type") == "rejected":
325
+ print(f"error: {event.get('message', event.get('code', 'rejected by server'))}", file=sys.stderr)
326
+ sys.exit(1)
327
+
319
328
  if event.get("type") != "subscribed":
320
- print("error: unexpected response from server", file=sys.stderr)
329
+ print(f"error: unexpected response from server: {event}", file=sys.stderr)
321
330
  sys.exit(1)
322
331
 
323
332
  repos = event.get("repos", [])
@@ -334,6 +343,8 @@ async def setup(server_url, token):
334
343
 
335
344
  print("done — Claude Code will take it from here\n", file=sys.stderr)
336
345
 
346
+ except SystemExit:
347
+ raise
337
348
  except Exception as e:
338
349
  print(f"error: {e}", file=sys.stderr)
339
350
  sys.exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ghosttrap-cli
3
- Version: 0.3.13
3
+ Version: 0.3.15
4
4
  Summary: Watch for errors streaming from ghosttrap.io
5
5
  Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-cli
6
6
  Requires-Python: >=3.10
@@ -56,10 +56,11 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
56
56
 
57
57
  ## How it works
58
58
 
59
- - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
59
+ - **Setup** authenticates with GitHub (via the active `gh` account) to prove you have access to the repo, then saves a repo token locally. If your active `gh` account can't see the repo, setup fails with a clear message; switch with `gh auth switch` and retry.
60
60
  - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
61
61
  - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
62
- - Local state is stored in `~/.ghosttrap/config.json`
62
+ - Repos are tracked by GitHub's immutable repo id, so a rename or transfer doesn't require any action — the next connect picks up the new `owner/name` and your token keeps working
63
+ - Local state is stored in `~/.ghosttrap/config.json`, keyed by GitHub repo id
63
64
 
64
65
  ## Requirements
65
66
 
@@ -70,4 +71,8 @@ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to
70
71
 
71
72
  ## Privacy
72
73
 
73
- Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo ownership; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
74
+ Error data (tracebacks, exception messages, file paths) is routed through ghosttrap.io. The server is not open source yet — if there's demand for self-hosting, we'll open it up. Your GitHub token is used only during `setup` to verify repo access; it's never stored on the server. After setup, all communication uses a repo-specific token that grants access only to that repo's error stream — it cannot access your GitHub account.
75
+
76
+ User context (Django user id + username) is **never** sent unless you opt in with `ghosttrap.init(token, send_user=True)` in your app. Server hostname is captured automatically.
77
+
78
+ Run `ghosttrap nuke` from inside a repo to permanently delete every server-side row for that repo (errors + the token itself). Requires typing the repo name to confirm.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ghosttrap-cli"
7
- version = "0.3.13"
7
+ version = "0.3.15"
8
8
  description = "Watch for errors streaming from ghosttrap.io"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes