claude-dev-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.

Potentially problematic release.


This version of claude-dev-cli might be problematic. Click here for more details.

Files changed (31) hide show
  1. {claude_dev_cli-0.3.0/src/claude_dev_cli.egg-info → claude_dev_cli-0.3.1}/PKG-INFO +4 -1
  2. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/pyproject.toml +5 -1
  3. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/config.py +7 -7
  4. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/core.py +13 -5
  5. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/plugins/diff_editor/viewer.py +57 -4
  6. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1/src/claude_dev_cli.egg-info}/PKG-INFO +4 -1
  7. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli.egg-info/requires.txt +4 -0
  8. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/LICENSE +0 -0
  9. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/MANIFEST.in +0 -0
  10. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/README.md +0 -0
  11. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/setup.cfg +0 -0
  12. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/__init__.py +0 -0
  13. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/cli.py +0 -0
  14. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/commands.py +0 -0
  15. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/plugins/__init__.py +0 -0
  16. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/plugins/base.py +0 -0
  17. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/plugins/diff_editor/__init__.py +0 -0
  18. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/plugins/diff_editor/plugin.py +0 -0
  19. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/templates.py +0 -0
  20. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/toon_utils.py +0 -0
  21. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli/usage.py +0 -0
  22. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli.egg-info/SOURCES.txt +0 -0
  23. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli.egg-info/dependency_links.txt +0 -0
  24. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli.egg-info/entry_points.txt +0 -0
  25. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/src/claude_dev_cli.egg-info/top_level.txt +0 -0
  26. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_cli.py +0 -0
  27. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_commands.py +0 -0
  28. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_config.py +0 -0
  29. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_core.py +0 -0
  30. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_toon_utils.py +0 -0
  31. {claude_dev_cli-0.3.0 → claude_dev_cli-0.3.1}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-dev-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: A powerful CLI tool for developers using Claude AI with multi-API routing, test generation, code review, and usage tracking
5
5
  Author-email: Julio <thinmanj@users.noreply.github.com>
6
6
  License: MIT
@@ -28,12 +28,15 @@ Requires-Dist: rich>=13.0.0
28
28
  Requires-Dist: pydantic>=2.0.0
29
29
  Provides-Extra: toon
30
30
  Requires-Dist: toon-format>=0.9.0; extra == "toon"
31
+ Provides-Extra: plugins
32
+ Requires-Dist: pygments>=2.0.0; extra == "plugins"
31
33
  Provides-Extra: dev
32
34
  Requires-Dist: pytest>=7.0.0; extra == "dev"
33
35
  Requires-Dist: black>=23.0.0; extra == "dev"
34
36
  Requires-Dist: ruff>=0.1.0; extra == "dev"
35
37
  Requires-Dist: mypy>=1.0.0; extra == "dev"
36
38
  Requires-Dist: toon-format>=0.9.0; extra == "dev"
39
+ Requires-Dist: pygments>=2.0.0; extra == "dev"
37
40
  Dynamic: license-file
38
41
 
39
42
  # Claude Dev CLI
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-dev-cli"
7
- version = "0.3.0"
7
+ version = "0.3.1"
8
8
  description = "A powerful CLI tool for developers using Claude AI with multi-API routing, test generation, code review, and usage tracking"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -38,12 +38,16 @@ dependencies = [
38
38
  toon = [
39
39
  "toon-format>=0.9.0",
40
40
  ]
41
+ plugins = [
42
+ "pygments>=2.0.0",
43
+ ]
41
44
  dev = [
42
45
  "pytest>=7.0.0",
43
46
  "black>=23.0.0",
44
47
  "ruff>=0.1.0",
45
48
  "mypy>=1.0.0",
46
49
  "toon-format>=0.9.0",
50
+ "pygments>=2.0.0",
47
51
  ]
48
52
 
49
53
  [project.urls]
@@ -28,15 +28,15 @@ class ProjectProfile(BaseModel):
28
28
  class Config:
29
29
  """Manages configuration for Claude Dev CLI."""
30
30
 
31
- CONFIG_DIR = Path.home() / ".claude-dev-cli"
32
- CONFIG_FILE = CONFIG_DIR / "config.json"
33
- USAGE_LOG = CONFIG_DIR / "usage.jsonl"
34
-
35
31
  def __init__(self) -> None:
36
32
  """Initialize configuration."""
37
- self.config_dir = self.CONFIG_DIR
38
- self.config_file = self.CONFIG_FILE
39
- self.usage_log = self.USAGE_LOG
33
+ # Determine home directory (respects HOME env var for testing)
34
+ home = Path(os.environ.get("HOME", str(Path.home())))
35
+
36
+ self.config_dir = home / ".claude-dev-cli"
37
+ self.config_file = self.config_dir / "config.json"
38
+ self.usage_log = self.config_dir / "usage.jsonl"
39
+
40
40
  self._ensure_config_dir()
41
41
  self._data: Dict = self._load_config()
42
42
 
@@ -13,13 +13,21 @@ class ClaudeClient:
13
13
  """Claude API client with multi-key routing and usage tracking."""
14
14
 
15
15
  def __init__(self, config: Optional[Config] = None, api_config_name: Optional[str] = None):
16
- """Initialize Claude client."""
16
+ """Initialize Claude client.
17
+
18
+ API routing hierarchy (highest to lowest priority):
19
+ 1. Explicit api_config_name parameter
20
+ 2. Project-specific .claude-dev-cli file
21
+ 3. Default API config
22
+ """
17
23
  self.config = config or Config()
18
24
 
19
- # Determine which API config to use
20
- project_profile = self.config.get_project_profile()
21
- if project_profile:
22
- api_config_name = project_profile.api_config
25
+ # Determine which API config to use based on hierarchy
26
+ if not api_config_name:
27
+ # Check for project profile if no explicit config provided
28
+ project_profile = self.config.get_project_profile()
29
+ if project_profile:
30
+ api_config_name = project_profile.api_config
23
31
 
24
32
  self.api_config = self.config.get_api_config(api_config_name)
25
33
  if not self.api_config:
@@ -11,6 +11,13 @@ from rich.syntax import Syntax
11
11
  from rich.table import Table
12
12
  from rich.text import Text
13
13
 
14
+ try:
15
+ from pygments import lexers
16
+ from pygments.util import ClassNotFound
17
+ PYGMENTS_AVAILABLE = True
18
+ except ImportError:
19
+ PYGMENTS_AVAILABLE = False
20
+
14
21
 
15
22
  class Hunk:
16
23
  """Represents a single diff hunk."""
@@ -69,6 +76,12 @@ class DiffViewer:
69
76
  self.hunks = self._generate_hunks()
70
77
  self.current_hunk_idx = 0
71
78
  self.filename = proposed_path.name
79
+
80
+ # Detect lexer for syntax highlighting
81
+ self.lexer_name = self._detect_lexer()
82
+
83
+ # History stack for undo support
84
+ self.history: List[Tuple[int, Optional[bool]]] = []
72
85
 
73
86
  def _detect_keybinding_mode(self) -> str:
74
87
  """Auto-detect keybinding preference from environment."""
@@ -80,6 +93,17 @@ class DiffViewer:
80
93
  return "nvim"
81
94
  return "fresh"
82
95
 
96
+ def _detect_lexer(self) -> Optional[str]:
97
+ """Detect appropriate lexer for syntax highlighting based on filename."""
98
+ if not PYGMENTS_AVAILABLE:
99
+ return None
100
+
101
+ try:
102
+ lexer = lexers.get_lexer_for_filename(str(self.proposed_path))
103
+ return lexer.name
104
+ except ClassNotFound:
105
+ return None
106
+
83
107
  def _generate_hunks(self) -> List[Hunk]:
84
108
  """Generate hunks from diff."""
85
109
  hunks = []
@@ -199,14 +223,28 @@ class DiffViewer:
199
223
  # Show original (if any deletions)
200
224
  if hunk.original_lines:
201
225
  self.console.print("\n[bold red]━━━ Original (-):[/bold red]")
202
- for line in hunk.original_lines:
203
- self.console.print(f"[red]- {line}[/red]", end="")
226
+ code = "".join(hunk.original_lines)
227
+ if self.lexer_name and code.strip():
228
+ syntax = Syntax(code, self.lexer_name, theme="monokai", line_numbers=False)
229
+ # Wrap in red for deletions
230
+ for line in code.splitlines():
231
+ self.console.print(f"[red]- {line}[/red]")
232
+ else:
233
+ for line in hunk.original_lines:
234
+ self.console.print(f"[red]- {line}[/red]", end="")
204
235
 
205
236
  # Show proposed (if any additions)
206
237
  if hunk.proposed_lines:
207
238
  self.console.print("\n[bold green]━━━ Proposed (+):[/bold green]")
208
- for line in hunk.proposed_lines:
209
- self.console.print(f"[green]+ {line}[/green]", end="")
239
+ code = "".join(hunk.proposed_lines)
240
+ if self.lexer_name and code.strip():
241
+ syntax = Syntax(code, self.lexer_name, theme="monokai", line_numbers=False)
242
+ # Wrap in green for additions
243
+ for line in code.splitlines():
244
+ self.console.print(f"[green]+ {line}[/green]")
245
+ else:
246
+ for line in hunk.proposed_lines:
247
+ self.console.print(f"[green]+ {line}[/green]", end="")
210
248
 
211
249
  # Context
212
250
  context = hunk.get_context()
@@ -258,9 +296,13 @@ class DiffViewer:
258
296
 
259
297
  # Process choice
260
298
  if choice in kb["accept"]:
299
+ # Save history before changing
300
+ self.history.append((self.current_hunk_idx, hunk.accepted))
261
301
  hunk.accepted = True
262
302
  self.current_hunk_idx += 1
263
303
  elif choice in kb["reject"]:
304
+ # Save history before changing
305
+ self.history.append((self.current_hunk_idx, hunk.accepted))
264
306
  hunk.accepted = False
265
307
  self.current_hunk_idx += 1
266
308
  elif choice in kb["edit"]:
@@ -283,6 +325,17 @@ class DiffViewer:
283
325
  for h in self.hunks[self.current_hunk_idx:]:
284
326
  h.accepted = False
285
327
  break
328
+ elif choice in kb["undo"]:
329
+ if self.history:
330
+ # Restore previous state
331
+ hunk_idx, prev_state = self.history.pop()
332
+ self.hunks[hunk_idx].accepted = prev_state
333
+ self.current_hunk_idx = hunk_idx
334
+ self.console.print("[yellow]↶ Undone last action[/yellow]")
335
+ self.console.input("Press Enter to continue...")
336
+ else:
337
+ self.console.print("[yellow]No actions to undo[/yellow]")
338
+ self.console.input("Press Enter to continue...")
286
339
  elif choice in kb["quit"]:
287
340
  self.console.print("[yellow]Quitting without applying changes[/yellow]")
288
341
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-dev-cli
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: A powerful CLI tool for developers using Claude AI with multi-API routing, test generation, code review, and usage tracking
5
5
  Author-email: Julio <thinmanj@users.noreply.github.com>
6
6
  License: MIT
@@ -28,12 +28,15 @@ Requires-Dist: rich>=13.0.0
28
28
  Requires-Dist: pydantic>=2.0.0
29
29
  Provides-Extra: toon
30
30
  Requires-Dist: toon-format>=0.9.0; extra == "toon"
31
+ Provides-Extra: plugins
32
+ Requires-Dist: pygments>=2.0.0; extra == "plugins"
31
33
  Provides-Extra: dev
32
34
  Requires-Dist: pytest>=7.0.0; extra == "dev"
33
35
  Requires-Dist: black>=23.0.0; extra == "dev"
34
36
  Requires-Dist: ruff>=0.1.0; extra == "dev"
35
37
  Requires-Dist: mypy>=1.0.0; extra == "dev"
36
38
  Requires-Dist: toon-format>=0.9.0; extra == "dev"
39
+ Requires-Dist: pygments>=2.0.0; extra == "dev"
37
40
  Dynamic: license-file
38
41
 
39
42
  # Claude Dev CLI
@@ -9,6 +9,10 @@ black>=23.0.0
9
9
  ruff>=0.1.0
10
10
  mypy>=1.0.0
11
11
  toon-format>=0.9.0
12
+ pygments>=2.0.0
13
+
14
+ [plugins]
15
+ pygments>=2.0.0
12
16
 
13
17
  [toon]
14
18
  toon-format>=0.9.0
File without changes
File without changes
File without changes