claude-jacked 0.3.1__tar.gz → 0.3.3__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 (46) hide show
  1. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/PKG-INFO +19 -19
  2. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/README.md +18 -18
  3. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/__init__.py +1 -1
  4. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/cli.py +4 -4
  5. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/hooks/security_gatekeeper.py +25 -12
  6. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/pyproject.toml +1 -1
  7. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/.claude/settings.local.json +0 -0
  8. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/.github/workflows/publish.yml +0 -0
  9. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/.gitignore +0 -0
  10. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/LICENSE +0 -0
  11. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/design/session_indexing_improvements.md +0 -0
  12. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/docs/DESIGN.md +0 -0
  13. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/install.sh +0 -0
  14. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/client.py +0 -0
  15. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/config.py +0 -0
  16. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/code-simplicity-reviewer.md +0 -0
  17. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/defensive-error-handler.md +0 -0
  18. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/double-check-reviewer.md +0 -0
  19. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/git-pr-workflow-manager.md +0 -0
  20. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/issue-pr-coordinator.md +0 -0
  21. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/pr-workflow-checker.md +0 -0
  22. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/readme-maintainer.md +0 -0
  23. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/test-coverage-engineer.md +0 -0
  24. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/test-coverage-improver.md +0 -0
  25. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/agents/wiki-documentation-architect.md +0 -0
  26. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/audit-rules.md +0 -0
  27. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/dc.md +0 -0
  28. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/learn.md +0 -0
  29. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/pr.md +0 -0
  30. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/redo.md +0 -0
  31. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/commands/techdebt.md +0 -0
  32. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/rules/jacked_behaviors.md +0 -0
  33. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/data/skills/jacked/SKILL.md +0 -0
  34. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/index_write_tracker.py +0 -0
  35. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/indexer.py +0 -0
  36. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/retriever.py +0 -0
  37. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/searcher.py +0 -0
  38. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/jacked/transcript.py +0 -0
  39. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/__init__.py +0 -0
  40. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/conftest.py +0 -0
  41. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/debugging/test_gatekeeper.py +0 -0
  42. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/test_config.py +0 -0
  43. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/test_index_write_tracker.py +0 -0
  44. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/test_indexer_incremental.py +0 -0
  45. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/tests/test_transcript.py +0 -0
  46. {claude_jacked-0.3.1 → claude_jacked-0.3.3}/uninstall.sh +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-jacked
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: Smart reviewers, commands, and session search for Claude Code
5
5
  Project-URL: Homepage, https://github.com/jackneil/claude-jacked
6
6
  Project-URL: Repository, https://github.com/jackneil/claude-jacked
@@ -82,10 +82,10 @@ Install claude-jacked for me. Use AskUserQuestion to ask me which features I wan
82
82
  - SECURITY: Everything above + auto-approve safe bash commands (fewer permission prompts)
83
83
  - ALL: Everything
84
84
  3. Install based on my choice:
85
- - BASE: pipx install claude-jacked && jacked install
86
- - SEARCH: pipx install "claude-jacked[search]" && jacked install
87
- - SECURITY: pipx install "claude-jacked[security]" && jacked install --security
88
- - ALL: pipx install "claude-jacked[all]" && jacked install --security
85
+ - BASE: pipx install claude-jacked && jacked install --force
86
+ - SEARCH: pipx install "claude-jacked[search]" && jacked install --force
87
+ - SECURITY: pipx install "claude-jacked[security]" && jacked install --force --security
88
+ - ALL: pipx install "claude-jacked[all]" && jacked install --force --security
89
89
  4. If I chose SEARCH or ALL, help me set up Qdrant Cloud credentials
90
90
  5. Verify with: jacked --help
91
91
  ```
@@ -95,26 +95,26 @@ Install claude-jacked for me. Use AskUserQuestion to ask me which features I wan
95
95
  **Core (reviewers, commands, behavioral rules):**
96
96
  ```bash
97
97
  pipx install claude-jacked
98
- jacked install
98
+ jacked install --force
99
99
  ```
100
100
 
101
101
  **Add session search (optional):**
102
102
  ```bash
103
103
  pipx install "claude-jacked[search]"
104
- jacked install
104
+ jacked install --force
105
105
  # Then set up Qdrant Cloud credentials (see below)
106
106
  ```
107
107
 
108
108
  **Add security gatekeeper (optional):**
109
109
  ```bash
110
110
  pipx install "claude-jacked[security]"
111
- jacked install --security
111
+ jacked install --force --security
112
112
  ```
113
113
 
114
114
  **Everything:**
115
115
  ```bash
116
116
  pipx install "claude-jacked[all]"
117
- jacked install --security
117
+ jacked install --force --security
118
118
  ```
119
119
 
120
120
  ---
@@ -277,7 +277,7 @@ The security gatekeeper is opt-in. To enable it:
277
277
 
278
278
  ```bash
279
279
  pip install "claude-jacked[security]"
280
- jacked install --security
280
+ jacked install --force --security
281
281
  ```
282
282
 
283
283
  To remove just the security hook:
@@ -311,7 +311,7 @@ export ANTHROPIC_API_KEY="sk-..."
311
311
  Get audio alerts so you don't have to watch the terminal:
312
312
 
313
313
  ```bash
314
- jacked install --sounds
314
+ jacked install --force --sounds
315
315
  ```
316
316
 
317
317
  - **Notification sound** — Plays when Claude needs your input
@@ -444,10 +444,10 @@ jacked delete <session_id> # Remove from index
444
444
  jacked cleardb # Delete all your data
445
445
 
446
446
  # Setup
447
- jacked install # Install agents, commands, rules
448
- jacked install --search # Also add session indexing hook
449
- jacked install --security # Also add security gatekeeper hook
450
- jacked install --sounds # Also add sound notifications
447
+ jacked install --force # Install agents, commands, rules
448
+ jacked install --force --search # Also add session indexing hook
449
+ jacked install --force --security # Also add security gatekeeper hook
450
+ jacked install --force --sounds # Also add sound notifications
451
451
  jacked uninstall # Remove from Claude Code
452
452
  jacked uninstall --sounds # Remove only sounds
453
453
  jacked uninstall --security # Remove only security hook
@@ -603,10 +603,10 @@ Options:
603
603
 
604
604
  PHASE 3 - INSTALL:
605
605
  Based on user choice:
606
- - BASE: pipx install claude-jacked && jacked install
607
- - SEARCH: pipx install "claude-jacked[search]" && jacked install
608
- - SECURITY: pipx install "claude-jacked[security]" && jacked install --security
609
- - ALL: pipx install "claude-jacked[all]" && jacked install --security
606
+ - BASE: pipx install claude-jacked && jacked install --force
607
+ - SEARCH: pipx install "claude-jacked[search]" && jacked install --force
608
+ - SECURITY: pipx install "claude-jacked[security]" && jacked install --force --security
609
+ - ALL: pipx install "claude-jacked[all]" && jacked install --force --security
610
610
 
611
611
  PHASE 4 - POST-INSTALL (if SEARCH or ALL):
612
612
  Help user set up Qdrant Cloud:
@@ -46,10 +46,10 @@ Install claude-jacked for me. Use AskUserQuestion to ask me which features I wan
46
46
  - SECURITY: Everything above + auto-approve safe bash commands (fewer permission prompts)
47
47
  - ALL: Everything
48
48
  3. Install based on my choice:
49
- - BASE: pipx install claude-jacked && jacked install
50
- - SEARCH: pipx install "claude-jacked[search]" && jacked install
51
- - SECURITY: pipx install "claude-jacked[security]" && jacked install --security
52
- - ALL: pipx install "claude-jacked[all]" && jacked install --security
49
+ - BASE: pipx install claude-jacked && jacked install --force
50
+ - SEARCH: pipx install "claude-jacked[search]" && jacked install --force
51
+ - SECURITY: pipx install "claude-jacked[security]" && jacked install --force --security
52
+ - ALL: pipx install "claude-jacked[all]" && jacked install --force --security
53
53
  4. If I chose SEARCH or ALL, help me set up Qdrant Cloud credentials
54
54
  5. Verify with: jacked --help
55
55
  ```
@@ -59,26 +59,26 @@ Install claude-jacked for me. Use AskUserQuestion to ask me which features I wan
59
59
  **Core (reviewers, commands, behavioral rules):**
60
60
  ```bash
61
61
  pipx install claude-jacked
62
- jacked install
62
+ jacked install --force
63
63
  ```
64
64
 
65
65
  **Add session search (optional):**
66
66
  ```bash
67
67
  pipx install "claude-jacked[search]"
68
- jacked install
68
+ jacked install --force
69
69
  # Then set up Qdrant Cloud credentials (see below)
70
70
  ```
71
71
 
72
72
  **Add security gatekeeper (optional):**
73
73
  ```bash
74
74
  pipx install "claude-jacked[security]"
75
- jacked install --security
75
+ jacked install --force --security
76
76
  ```
77
77
 
78
78
  **Everything:**
79
79
  ```bash
80
80
  pipx install "claude-jacked[all]"
81
- jacked install --security
81
+ jacked install --force --security
82
82
  ```
83
83
 
84
84
  ---
@@ -241,7 +241,7 @@ The security gatekeeper is opt-in. To enable it:
241
241
 
242
242
  ```bash
243
243
  pip install "claude-jacked[security]"
244
- jacked install --security
244
+ jacked install --force --security
245
245
  ```
246
246
 
247
247
  To remove just the security hook:
@@ -275,7 +275,7 @@ export ANTHROPIC_API_KEY="sk-..."
275
275
  Get audio alerts so you don't have to watch the terminal:
276
276
 
277
277
  ```bash
278
- jacked install --sounds
278
+ jacked install --force --sounds
279
279
  ```
280
280
 
281
281
  - **Notification sound** — Plays when Claude needs your input
@@ -408,10 +408,10 @@ jacked delete <session_id> # Remove from index
408
408
  jacked cleardb # Delete all your data
409
409
 
410
410
  # Setup
411
- jacked install # Install agents, commands, rules
412
- jacked install --search # Also add session indexing hook
413
- jacked install --security # Also add security gatekeeper hook
414
- jacked install --sounds # Also add sound notifications
411
+ jacked install --force # Install agents, commands, rules
412
+ jacked install --force --search # Also add session indexing hook
413
+ jacked install --force --security # Also add security gatekeeper hook
414
+ jacked install --force --sounds # Also add sound notifications
415
415
  jacked uninstall # Remove from Claude Code
416
416
  jacked uninstall --sounds # Remove only sounds
417
417
  jacked uninstall --security # Remove only security hook
@@ -567,10 +567,10 @@ Options:
567
567
 
568
568
  PHASE 3 - INSTALL:
569
569
  Based on user choice:
570
- - BASE: pipx install claude-jacked && jacked install
571
- - SEARCH: pipx install "claude-jacked[search]" && jacked install
572
- - SECURITY: pipx install "claude-jacked[security]" && jacked install --security
573
- - ALL: pipx install "claude-jacked[all]" && jacked install --security
570
+ - BASE: pipx install claude-jacked && jacked install --force
571
+ - SEARCH: pipx install "claude-jacked[search]" && jacked install --force
572
+ - SECURITY: pipx install "claude-jacked[security]" && jacked install --force --security
573
+ - ALL: pipx install "claude-jacked[all]" && jacked install --force --security
574
574
 
575
575
  PHASE 4 - POST-INSTALL (if SEARCH or ALL):
576
576
  Help user set up Qdrant Cloud:
@@ -8,7 +8,7 @@ Install extras for additional features:
8
8
  pip install "claude-jacked[all]" — everything
9
9
  """
10
10
 
11
- __version__ = "0.3.1"
11
+ __version__ = "0.3.3"
12
12
 
13
13
 
14
14
  def _qdrant_available() -> bool:
@@ -807,7 +807,7 @@ def _install_behavioral_rules(claude_md_path: Path, force: bool = False):
807
807
  # Version upgrade needed
808
808
  console.print("\n[bold]Behavioral rules update available:[/bold]")
809
809
  console.print(f"[dim]{rules_text}[/dim]")
810
- if not force and not click.confirm("Update behavioral rules in CLAUDE.md?"):
810
+ if not force and sys.stdin.isatty() and not click.confirm("Update behavioral rules in CLAUDE.md?"):
811
811
  console.print("[yellow][-][/yellow] Skipped behavioral rules update")
812
812
  return
813
813
 
@@ -838,7 +838,7 @@ def _install_behavioral_rules(claude_md_path: Path, force: bool = False):
838
838
  # Fresh install - show and confirm
839
839
  console.print("\n[bold]Proposed behavioral rules for ~/.claude/CLAUDE.md:[/bold]")
840
840
  console.print(f"[dim]{rules_text}[/dim]")
841
- if not force and not click.confirm("Add these behavioral rules to your global CLAUDE.md?"):
841
+ if not force and sys.stdin.isatty() and not click.confirm("Add these behavioral rules to your global CLAUDE.md?"):
842
842
  console.print("[yellow][-][/yellow] Skipped behavioral rules")
843
843
  return
844
844
 
@@ -1142,7 +1142,7 @@ def install(sounds: bool, search: bool, security: bool, no_rules: bool, force: b
1142
1142
  skipped += 1
1143
1143
  continue # Same content, skip silently
1144
1144
  # Different content - ask before overwriting (unless --force)
1145
- if not force and not click.confirm(f"Agent '{agent_file.name}' exists with different content. Overwrite?"):
1145
+ if not force and sys.stdin.isatty() and not click.confirm(f"Agent '{agent_file.name}' exists with different content. Overwrite?"):
1146
1146
  console.print(f"[yellow][-][/yellow] Skipped {agent_file.name}")
1147
1147
  continue
1148
1148
  shutil.copy(agent_file, dst_file)
@@ -1170,7 +1170,7 @@ def install(sounds: bool, search: bool, security: bool, no_rules: bool, force: b
1170
1170
  skipped += 1
1171
1171
  continue # Same content, skip silently
1172
1172
  # Different content - ask before overwriting (unless --force)
1173
- if not force and not click.confirm(f"Command '{cmd_file.name}' exists with different content. Overwrite?"):
1173
+ if not force and sys.stdin.isatty() and not click.confirm(f"Command '{cmd_file.name}' exists with different content. Overwrite?"):
1174
1174
  console.print(f"[yellow][-][/yellow] Skipped {cmd_file.name}")
1175
1175
  continue
1176
1176
  shutil.copy(cmd_file, dst_file)
@@ -64,6 +64,9 @@ SAFE_EXACT = {
64
64
  # e.g., C:/Users/jack/.conda/envs/krac_llm/python.exe → python
65
65
  PATH_STRIP_RE = re.compile(r'^(?:.*[/\\])?([^/\\]+?)(?:\.exe)?(?:\s|$)', re.IGNORECASE)
66
66
 
67
+ # Strip leading env var assignments: HOME=/x PATH="/y:$PATH" cmd → cmd
68
+ ENV_ASSIGN_RE = re.compile(r"""^(?:\w+=(?:"[^"]*"|'[^']*'|\S+)\s+)+""")
69
+
67
70
  # Universal safe: any command that just asks for version or help
68
71
  VERSION_HELP_RE = re.compile(r'^\S+\s+(-[Vv]|--version|-h|--help)\s*$')
69
72
 
@@ -195,14 +198,18 @@ def check_permissions(command: str, cwd: str) -> bool:
195
198
  patterns.extend(_load_permissions(project_dir / ".claude" / "settings.json"))
196
199
  patterns.extend(_load_permissions(project_dir / ".claude" / "settings.local.json"))
197
200
 
201
+ cmd_core = _strip_env_prefix(command)
202
+ candidates = [command, cmd_core] if cmd_core != command else [command]
203
+
198
204
  for pat in patterns:
199
205
  prefix, is_wildcard = _parse_bash_pattern(pat)
200
- if is_wildcard:
201
- if command.startswith(prefix):
202
- return True
203
- else:
204
- if command == prefix:
205
- return True
206
+ for cmd in candidates:
207
+ if is_wildcard:
208
+ if cmd.startswith(prefix):
209
+ return True
210
+ else:
211
+ if cmd == prefix:
212
+ return True
206
213
 
207
214
  return False
208
215
 
@@ -223,9 +230,14 @@ def _get_base_command(command: str) -> str:
223
230
  return stripped
224
231
 
225
232
 
233
+ def _strip_env_prefix(cmd: str) -> str:
234
+ """Strip leading env var assignments: HOME=/x PATH="/y" cmd → cmd"""
235
+ return ENV_ASSIGN_RE.sub('', cmd).strip()
236
+
237
+
226
238
  def local_evaluate(command: str) -> str | None:
227
239
  """Evaluate command locally. Returns 'YES', 'NO', or None (ambiguous)."""
228
- cmd = command.strip()
240
+ cmd = _strip_env_prefix(command.strip())
229
241
  base = _get_base_command(cmd)
230
242
 
231
243
  # Check deny patterns first (on original command, not stripped)
@@ -353,11 +365,12 @@ def main():
353
365
 
354
366
  # Tier 0: Deny check FIRST — security always wins over permissions
355
367
  cmd_stripped = command.strip()
368
+ cmd_core = _strip_env_prefix(cmd_stripped)
356
369
  for pattern in DENY_PATTERNS:
357
- if pattern.search(cmd_stripped):
370
+ if pattern.search(cmd_stripped) or pattern.search(cmd_core):
358
371
  elapsed = time.time() - start
359
372
  log(f"DENY MATCH ({elapsed:.3f}s)")
360
- log(f"DECISION: PASS ({elapsed:.3f}s)")
373
+ log(f"DECISION: ASK USER ({elapsed:.3f}s)")
361
374
  sys.exit(0)
362
375
 
363
376
  # Tier 1: Check Claude's own permission rules
@@ -380,7 +393,7 @@ def main():
380
393
  # Shouldn't hit this since deny checked above, but just in case
381
394
  elapsed = time.time() - start
382
395
  log(f"LOCAL SAID: NO ({elapsed:.3f}s)")
383
- log(f"DECISION: PASS ({elapsed:.3f}s)")
396
+ log(f"DECISION: ASK USER ({elapsed:.3f}s)")
384
397
  sys.exit(0)
385
398
 
386
399
  # Tier 3+4: API then CLI for ambiguous commands
@@ -396,7 +409,7 @@ def main():
396
409
  elapsed = time.time() - start
397
410
 
398
411
  if response is None:
399
- log(f"DECISION: PASS (no response, {elapsed:.1f}s)")
412
+ log(f"DECISION: ASK USER (no response, {elapsed:.1f}s)")
400
413
  sys.exit(0)
401
414
 
402
415
  response_upper = response.upper()
@@ -406,7 +419,7 @@ def main():
406
419
  log(f"DECISION: ALLOW ({elapsed:.1f}s)")
407
420
  emit_allow()
408
421
  else:
409
- log(f"DECISION: PASS ({elapsed:.1f}s)")
422
+ log(f"DECISION: ASK USER ({elapsed:.1f}s)")
410
423
 
411
424
  sys.exit(0)
412
425
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "claude-jacked"
7
- version = "0.3.1"
7
+ version = "0.3.3"
8
8
  description = "Smart reviewers, commands, and session search for Claude Code"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes