ghosttrap-cli 0.3.0__tar.gz → 0.3.1__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.
@@ -0,0 +1,68 @@
1
+ Metadata-Version: 2.4
2
+ Name: ghosttrap-cli
3
+ Version: 0.3.1
4
+ Summary: Watch for errors streaming from ghosttrap.io
5
+ Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-cli
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: websockets>=12.0
9
+
10
+ # ghosttrap-cli
11
+
12
+ The developer-side listener for [ghosttrap](https://ghosttrap.io). Connects errors from remote servers to Claude Code in real time.
13
+
14
+ Works with any Python app. Django and Celery get deep integration (middleware, app config, task failure hooks). Flask and other frameworks work via Python's logging and excepthook.
15
+
16
+ ## Setup
17
+
18
+ Requires the [GitHub CLI](https://cli.github.com) (`gh`) and [Claude Code](https://claude.ai/code).
19
+
20
+ ```
21
+ pip install ghosttrap-cli
22
+ cd ~/your-project
23
+ ghosttrap setup
24
+ ```
25
+
26
+ Then in Claude Code:
27
+
28
+ ```
29
+ /ghosttrap
30
+ ```
31
+
32
+ That's it. `setup` authenticates via `gh`, claims the repo, and installs a Claude Code skill. The `/ghosttrap` skill handles everything else — it installs the SDK into your app, wires in the error hooks, and starts monitoring.
33
+
34
+ ## What happens next
35
+
36
+ The skill file tells Claude Code to run `ghosttrap peek` in the background. Peek opens a WebSocket to ghosttrap.io and waits. When a production error arrives, Claude sees the full traceback — exception type, message, file, line, function — and starts fixing.
37
+
38
+ After fixing, Claude restarts peek and waits for the next one. Errors become a real-time stream that your AI agent dispatches automatically.
39
+
40
+ ## The SDK
41
+
42
+ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to report errors. The Claude Code skill handles the integration automatically — it installs the SDK, wires it into your app, and adds Django/Celery hooks if applicable. You shouldn't need to touch the SDK manually.
43
+
44
+ ## Commands
45
+
46
+ | Command | What it does |
47
+ |---------|-------------|
48
+ | `ghosttrap setup` | Claim a repo, install the Claude Code skill |
49
+ | `ghosttrap peek` | Wait for the next error, print it, exit |
50
+ | `ghosttrap watch` | Stream all errors continuously |
51
+
52
+ ## How it works
53
+
54
+ - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
55
+ - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
56
+ - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
57
+ - Local state is stored in `~/.ghosttrap/config.json`
58
+
59
+ ## Requirements
60
+
61
+ - Python 3.10+
62
+ - [GitHub CLI](https://cli.github.com) (`gh`) — used for authentication during setup
63
+ - [Claude Code](https://claude.ai/code) — the AI agent that fixes your errors
64
+ - macOS or Linux (Windows is untested)
65
+
66
+ ## Privacy
67
+
68
+ 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.
@@ -0,0 +1,59 @@
1
+ # ghosttrap-cli
2
+
3
+ The developer-side listener for [ghosttrap](https://ghosttrap.io). Connects errors from remote servers to Claude Code in real time.
4
+
5
+ Works with any Python app. Django and Celery get deep integration (middleware, app config, task failure hooks). Flask and other frameworks work via Python's logging and excepthook.
6
+
7
+ ## Setup
8
+
9
+ Requires the [GitHub CLI](https://cli.github.com) (`gh`) and [Claude Code](https://claude.ai/code).
10
+
11
+ ```
12
+ pip install ghosttrap-cli
13
+ cd ~/your-project
14
+ ghosttrap setup
15
+ ```
16
+
17
+ Then in Claude Code:
18
+
19
+ ```
20
+ /ghosttrap
21
+ ```
22
+
23
+ That's it. `setup` authenticates via `gh`, claims the repo, and installs a Claude Code skill. The `/ghosttrap` skill handles everything else — it installs the SDK into your app, wires in the error hooks, and starts monitoring.
24
+
25
+ ## What happens next
26
+
27
+ The skill file tells Claude Code to run `ghosttrap peek` in the background. Peek opens a WebSocket to ghosttrap.io and waits. When a production error arrives, Claude sees the full traceback — exception type, message, file, line, function — and starts fixing.
28
+
29
+ After fixing, Claude restarts peek and waits for the next one. Errors become a real-time stream that your AI agent dispatches automatically.
30
+
31
+ ## The SDK
32
+
33
+ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to report errors. The Claude Code skill handles the integration automatically — it installs the SDK, wires it into your app, and adds Django/Celery hooks if applicable. You shouldn't need to touch the SDK manually.
34
+
35
+ ## Commands
36
+
37
+ | Command | What it does |
38
+ |---------|-------------|
39
+ | `ghosttrap setup` | Claim a repo, install the Claude Code skill |
40
+ | `ghosttrap peek` | Wait for the next error, print it, exit |
41
+ | `ghosttrap watch` | Stream all errors continuously |
42
+
43
+ ## How it works
44
+
45
+ - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
46
+ - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
47
+ - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
48
+ - Local state is stored in `~/.ghosttrap/config.json`
49
+
50
+ ## Requirements
51
+
52
+ - Python 3.10+
53
+ - [GitHub CLI](https://cli.github.com) (`gh`) — used for authentication during setup
54
+ - [Claude Code](https://claude.ai/code) — the AI agent that fixes your errors
55
+ - macOS or Linux (Windows is untested)
56
+
57
+ ## Privacy
58
+
59
+ 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.
@@ -6,15 +6,41 @@ import json
6
6
  import os
7
7
  import subprocess
8
8
  import sys
9
+ import time
10
+ import urllib.request
9
11
 
10
12
  import websockets
11
13
 
14
+ __version__ = "0.3.0"
12
15
 
13
16
  GHOSTTRAP_SERVER = "wss://ghosttrap.io/stream/"
14
17
  CONFIG_DIR = os.path.expanduser("~/.ghosttrap")
15
18
  CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
16
19
  SKILL_DIR = os.path.expanduser("~/.claude/skills/ghosttrap")
17
20
  SKILL_FILE = os.path.join(SKILL_DIR, "SKILL.md")
21
+ GITHUB_CLI_RELEASES = "https://api.github.com/repos/alex-rowley/ghosttrap-cli/releases/latest"
22
+ VERSION_CHECK_TTL = 86400 # check once per day
23
+
24
+
25
+ def _check_cli_version(config):
26
+ """Check if a newer CLI version is available. Caches for 24h."""
27
+ last_check = config.get("cli_version_check", 0)
28
+ if time.time() - last_check < VERSION_CHECK_TTL:
29
+ return
30
+ try:
31
+ req = urllib.request.Request(GITHUB_CLI_RELEASES, headers={
32
+ "Accept": "application/vnd.github+json",
33
+ "User-Agent": "ghosttrap-cli",
34
+ })
35
+ with urllib.request.urlopen(req, timeout=3) as resp:
36
+ data = json.loads(resp.read())
37
+ latest = data.get("tag_name", "").lstrip("v")
38
+ if latest and latest != __version__:
39
+ print(f"ghosttrap-cli {latest} available (you have {__version__})", file=sys.stderr)
40
+ except Exception:
41
+ pass
42
+ config["cli_version_check"] = time.time()
43
+ _save_config(config)
18
44
 
19
45
  SKILL_CONTENT = """\
20
46
  ---
@@ -32,7 +58,7 @@ Read `~/.ghosttrap/config.json` for state. It contains:
32
58
 
33
59
  1. Detect the current repo from `git config --get remote.origin.url`.
34
60
  2. Look it up in the config. If the repo isn't there, tell the user to run `ghosttrap setup`.
35
- 3. If `sdk_installed` is false or missing: install the SDK (`pip install git+https://github.com/arowley-predictive-power/ghosttrap-sdk.git`), 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.
61
+ 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.
36
62
  4. Run `ghosttrap peek` with `run_in_background: true`.
37
63
 
38
64
  ## When peek returns
@@ -114,7 +140,7 @@ def _print_setup_snippet(repo):
114
140
  token = repo["token"]
115
141
 
116
142
  print(f"\nadd to your app:\n", file=sys.stderr)
117
- print(f" pip install git+https://github.com/arowley-predictive-power/ghosttrap-sdk.git\n", file=sys.stderr)
143
+ print(f" pip install ghosttrap-sdk\n", file=sys.stderr)
118
144
  print(f" import ghosttrap\n", file=sys.stderr)
119
145
  print(f" # option 1: token (recommended)", file=sys.stderr)
120
146
  print(f' ghosttrap.init("{token}")\n', file=sys.stderr)
@@ -130,11 +156,13 @@ def get_gh_token():
130
156
  )
131
157
  token = result.stdout.strip()
132
158
  if result.returncode != 0 or not token:
133
- print("error: could not get gh auth token. run 'gh auth login' first.", file=sys.stderr)
159
+ print("\nghosttrap uses your GitHub identity for authentication.", file=sys.stderr)
160
+ print("run 'gh auth login' to sign in, then try again.\n", file=sys.stderr)
134
161
  sys.exit(1)
135
162
  return token
136
163
  except FileNotFoundError:
137
- print("error: gh cli not found. install it from https://cli.github.com", file=sys.stderr)
164
+ print("\nghosttrap requires the GitHub CLI for authentication.", file=sys.stderr)
165
+ print("install it from https://cli.github.com then try again.\n", file=sys.stderr)
138
166
  sys.exit(1)
139
167
 
140
168
 
@@ -173,6 +201,14 @@ async def _connect_and_handle(server_url, token, config, once=False):
173
201
  if target:
174
202
  _print_setup_snippet(target)
175
203
 
204
+ sdk_latest = event.get("sdk_latest")
205
+ if sdk_latest:
206
+ cwd_repo = _detect_repo_from_cwd()
207
+ if cwd_repo and cwd_repo in config.get("repos", {}):
208
+ installed = config["repos"][cwd_repo].get("sdk_version")
209
+ if installed and installed != sdk_latest:
210
+ print(f"ghosttrap-sdk {sdk_latest} available (you have {installed})", file=sys.stderr)
211
+
176
212
  if not once:
177
213
  print(f"waiting for errors...", file=sys.stderr)
178
214
  continue
@@ -266,6 +302,7 @@ async def watch(server_url, token):
266
302
 
267
303
  async def peek(server_url, token):
268
304
  config = _load_config()
305
+ _check_cli_version(config)
269
306
  await _connect_and_handle(server_url, token, config, once=True)
270
307
 
271
308
 
@@ -0,0 +1,68 @@
1
+ Metadata-Version: 2.4
2
+ Name: ghosttrap-cli
3
+ Version: 0.3.1
4
+ Summary: Watch for errors streaming from ghosttrap.io
5
+ Project-URL: Homepage, https://github.com/alex-rowley/ghosttrap-cli
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: websockets>=12.0
9
+
10
+ # ghosttrap-cli
11
+
12
+ The developer-side listener for [ghosttrap](https://ghosttrap.io). Connects errors from remote servers to Claude Code in real time.
13
+
14
+ Works with any Python app. Django and Celery get deep integration (middleware, app config, task failure hooks). Flask and other frameworks work via Python's logging and excepthook.
15
+
16
+ ## Setup
17
+
18
+ Requires the [GitHub CLI](https://cli.github.com) (`gh`) and [Claude Code](https://claude.ai/code).
19
+
20
+ ```
21
+ pip install ghosttrap-cli
22
+ cd ~/your-project
23
+ ghosttrap setup
24
+ ```
25
+
26
+ Then in Claude Code:
27
+
28
+ ```
29
+ /ghosttrap
30
+ ```
31
+
32
+ That's it. `setup` authenticates via `gh`, claims the repo, and installs a Claude Code skill. The `/ghosttrap` skill handles everything else — it installs the SDK into your app, wires in the error hooks, and starts monitoring.
33
+
34
+ ## What happens next
35
+
36
+ The skill file tells Claude Code to run `ghosttrap peek` in the background. Peek opens a WebSocket to ghosttrap.io and waits. When a production error arrives, Claude sees the full traceback — exception type, message, file, line, function — and starts fixing.
37
+
38
+ After fixing, Claude restarts peek and waits for the next one. Errors become a real-time stream that your AI agent dispatches automatically.
39
+
40
+ ## The SDK
41
+
42
+ Your app needs [ghosttrap-sdk](https://github.com/alex-rowley/ghosttrap-sdk) to report errors. The Claude Code skill handles the integration automatically — it installs the SDK, wires it into your app, and adds Django/Celery hooks if applicable. You shouldn't need to touch the SDK manually.
43
+
44
+ ## Commands
45
+
46
+ | Command | What it does |
47
+ |---------|-------------|
48
+ | `ghosttrap setup` | Claim a repo, install the Claude Code skill |
49
+ | `ghosttrap peek` | Wait for the next error, print it, exit |
50
+ | `ghosttrap watch` | Stream all errors continuously |
51
+
52
+ ## How it works
53
+
54
+ - **Setup** authenticates with GitHub to prove you own the repo, then saves a token locally
55
+ - **Peek** and **watch** connect to ghosttrap.io using that token — no GitHub auth needed after setup
56
+ - Errors that arrive while you're offline are replayed on next connect (cursor-based, no duplicates)
57
+ - Local state is stored in `~/.ghosttrap/config.json`
58
+
59
+ ## Requirements
60
+
61
+ - Python 3.10+
62
+ - [GitHub CLI](https://cli.github.com) (`gh`) — used for authentication during setup
63
+ - [Claude Code](https://claude.ai/code) — the AI agent that fixes your errors
64
+ - macOS or Linux (Windows is untested)
65
+
66
+ ## Privacy
67
+
68
+ 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.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ghosttrap-cli"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "Watch for errors streaming from ghosttrap.io"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -16,7 +16,7 @@ dependencies = [
16
16
  ghosttrap = "ghosttrap_cli.cli:main"
17
17
 
18
18
  [project.urls]
19
- Homepage = "https://github.com/arowley-predictive-power/ghosttrap-cli"
19
+ Homepage = "https://github.com/alex-rowley/ghosttrap-cli"
20
20
 
21
21
  [tool.setuptools.packages.find]
22
22
  include = ["ghosttrap_cli*"]
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ghosttrap-cli
3
- Version: 0.3.0
4
- Summary: Watch for errors streaming from ghosttrap.io
5
- Project-URL: Homepage, https://github.com/arowley-predictive-power/ghosttrap-cli
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- Requires-Dist: websockets>=12.0
9
-
10
- # ghosttrap-cli
11
-
12
- Watch for errors streaming from ghosttrap.io in real time.
13
-
14
- ## Install
15
-
16
- ```
17
- pip install ghosttrap-cli
18
- ```
19
-
20
- Requires the [GitHub CLI](https://cli.github.com) (`gh`) for authentication.
21
-
22
- ## Use
23
-
24
- ```
25
- ghosttrap watch
26
- ```
27
-
28
- Authenticates via your local `gh` session, subscribes to error streams
29
- for all repos you have access to, and prints events as they arrive.
30
-
31
- Human-readable summaries go to stderr. Machine-readable JSON goes to
32
- stdout, for piping into other tools.
@@ -1,23 +0,0 @@
1
- # ghosttrap-cli
2
-
3
- Watch for errors streaming from ghosttrap.io in real time.
4
-
5
- ## Install
6
-
7
- ```
8
- pip install ghosttrap-cli
9
- ```
10
-
11
- Requires the [GitHub CLI](https://cli.github.com) (`gh`) for authentication.
12
-
13
- ## Use
14
-
15
- ```
16
- ghosttrap watch
17
- ```
18
-
19
- Authenticates via your local `gh` session, subscribes to error streams
20
- for all repos you have access to, and prints events as they arrive.
21
-
22
- Human-readable summaries go to stderr. Machine-readable JSON goes to
23
- stdout, for piping into other tools.
@@ -1,32 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: ghosttrap-cli
3
- Version: 0.3.0
4
- Summary: Watch for errors streaming from ghosttrap.io
5
- Project-URL: Homepage, https://github.com/arowley-predictive-power/ghosttrap-cli
6
- Requires-Python: >=3.10
7
- Description-Content-Type: text/markdown
8
- Requires-Dist: websockets>=12.0
9
-
10
- # ghosttrap-cli
11
-
12
- Watch for errors streaming from ghosttrap.io in real time.
13
-
14
- ## Install
15
-
16
- ```
17
- pip install ghosttrap-cli
18
- ```
19
-
20
- Requires the [GitHub CLI](https://cli.github.com) (`gh`) for authentication.
21
-
22
- ## Use
23
-
24
- ```
25
- ghosttrap watch
26
- ```
27
-
28
- Authenticates via your local `gh` session, subscribes to error streams
29
- for all repos you have access to, and prints events as they arrive.
30
-
31
- Human-readable summaries go to stderr. Machine-readable JSON goes to
32
- stdout, for piping into other tools.
File without changes