claude-dev-cli 0.3.0__py3-none-any.whl → 0.3.1__py3-none-any.whl
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.
- claude_dev_cli/config.py +7 -7
- claude_dev_cli/core.py +13 -5
- claude_dev_cli/plugins/diff_editor/viewer.py +57 -4
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/METADATA +4 -1
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/RECORD +9 -9
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/WHEEL +0 -0
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/entry_points.txt +0 -0
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/licenses/LICENSE +0 -0
- {claude_dev_cli-0.3.0.dist-info → claude_dev_cli-0.3.1.dist-info}/top_level.txt +0 -0
claude_dev_cli/config.py
CHANGED
|
@@ -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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
|
claude_dev_cli/core.py
CHANGED
|
@@ -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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
203
|
-
|
|
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
|
-
|
|
209
|
-
|
|
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.
|
|
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
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
claude_dev_cli/__init__.py,sha256=2ulyIQ3E-s6wBTKyeXAlqHMVA73zUGdaaNUsFiJ-nqs,469
|
|
2
2
|
claude_dev_cli/cli.py,sha256=ekJpBU3d0k9DrE5VoJdKGNgPBsmdB4415up_Yhx_fw0,16174
|
|
3
3
|
claude_dev_cli/commands.py,sha256=RKGx2rv56PM6eErvA2uoQ20hY8babuI5jav8nCUyUOk,3964
|
|
4
|
-
claude_dev_cli/config.py,sha256
|
|
5
|
-
claude_dev_cli/core.py,sha256=
|
|
4
|
+
claude_dev_cli/config.py,sha256=-AESk_3Oxq7AoMxvnBIbgplAU9AXQGtlpihEwgtww2s,5826
|
|
5
|
+
claude_dev_cli/core.py,sha256=yaLjEixDvPzvUy4fJ2UB7nMpPPLyKACjR-RuM-1OQBY,4780
|
|
6
6
|
claude_dev_cli/templates.py,sha256=lKxH943ySfUKgyHaWa4W3LVv91SgznKgajRtSRp_4UY,2260
|
|
7
7
|
claude_dev_cli/toon_utils.py,sha256=S3px2UvmNEaltmTa5K-h21n2c0CPvYjZc9mc7kHGqNQ,2828
|
|
8
8
|
claude_dev_cli/usage.py,sha256=32rs0_dUn6ihha3vCfT3rwnvel_-sED7jvLpO7gu-KQ,7446
|
|
@@ -10,10 +10,10 @@ claude_dev_cli/plugins/__init__.py,sha256=BdiZlylBzEgnwK2tuEdn8cITxhAZRVbTnDbWhd
|
|
|
10
10
|
claude_dev_cli/plugins/base.py,sha256=H4HQet1I-a3WLCfE9F06Lp8NuFvVoIlou7sIgyJFK-c,1417
|
|
11
11
|
claude_dev_cli/plugins/diff_editor/__init__.py,sha256=gqR5S2TyIVuq-sK107fegsutQ7Z-sgAIEbtc71FhXIM,101
|
|
12
12
|
claude_dev_cli/plugins/diff_editor/plugin.py,sha256=M1bUoqpasD3ZNQo36Fu_8g92uySPZyG_ujMbj5UplsU,3073
|
|
13
|
-
claude_dev_cli/plugins/diff_editor/viewer.py,sha256=
|
|
14
|
-
claude_dev_cli-0.3.
|
|
15
|
-
claude_dev_cli-0.3.
|
|
16
|
-
claude_dev_cli-0.3.
|
|
17
|
-
claude_dev_cli-0.3.
|
|
18
|
-
claude_dev_cli-0.3.
|
|
19
|
-
claude_dev_cli-0.3.
|
|
13
|
+
claude_dev_cli/plugins/diff_editor/viewer.py,sha256=LoS6MD48AIQM_9aeBhIuGOYJN1-D6TTxozPV-hkvnTc,13951
|
|
14
|
+
claude_dev_cli-0.3.1.dist-info/licenses/LICENSE,sha256=DGueuJwMJtMwgLO5mWlS0TaeBrFwQuNpNZ22PU9J2bw,1062
|
|
15
|
+
claude_dev_cli-0.3.1.dist-info/METADATA,sha256=oYmNCiM1y__QsoXnp3Cbvw3R21-SpUrepCpQ461v6eg,10447
|
|
16
|
+
claude_dev_cli-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
claude_dev_cli-0.3.1.dist-info/entry_points.txt,sha256=zymgUIIVpFTARkFmxAuW2A4BQsNITh_L0uU-XunytHg,85
|
|
18
|
+
claude_dev_cli-0.3.1.dist-info/top_level.txt,sha256=m7MF6LOIuTe41IT5Fgt0lc-DK1EgM4gUU_IZwWxK0pg,15
|
|
19
|
+
claude_dev_cli-0.3.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|