claude-dev-cli 0.7.0__tar.gz → 0.8.0__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.
- {claude_dev_cli-0.7.0/src/claude_dev_cli.egg-info → claude_dev_cli-0.8.0}/PKG-INFO +37 -5
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/README.md +36 -4
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/pyproject.toml +1 -1
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/__init__.py +1 -1
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/cli.py +90 -14
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/config.py +6 -0
- claude_dev_cli-0.8.0/src/claude_dev_cli/context.py +494 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0/src/claude_dev_cli.egg-info}/PKG-INFO +37 -5
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/SOURCES.txt +1 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/LICENSE +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/MANIFEST.in +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/setup.cfg +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/commands.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/core.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/history.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/__init__.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/base.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/__init__.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/plugin.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/viewer.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/secure_storage.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/template_manager.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/templates.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/toon_utils.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/usage.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/warp_integration.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/workflows.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/dependency_links.txt +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/entry_points.txt +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/requires.txt +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/top_level.txt +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_cli.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_commands.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_config.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_core.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_diff_editor.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_secure_storage.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_template_manager.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/tests/test_toon_utils.py +0 -0
- {claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/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
|
+
Version: 0.8.0
|
|
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
|
|
@@ -79,6 +79,13 @@ A powerful command-line tool for developers using Claude AI with multi-API routi
|
|
|
79
79
|
- **Variable Substitution**: Use {{variable}} placeholders for dynamic content
|
|
80
80
|
- **Categories**: Organize templates by category (review, testing, debugging, etc.)
|
|
81
81
|
|
|
82
|
+
### 🧠 Context Intelligence (NEW in v0.8.0)
|
|
83
|
+
- **Auto-Context**: `--auto-context` flag for intelligent context gathering
|
|
84
|
+
- **Git Integration**: Automatically include branch, commits, modified files
|
|
85
|
+
- **Dependency Analysis**: Parse imports and include related files
|
|
86
|
+
- **Error Parsing**: Structured Python traceback parsing
|
|
87
|
+
- **Project Memory**: Remember preferences per project
|
|
88
|
+
|
|
82
89
|
### 🎒 TOON Format Support (Optional)
|
|
83
90
|
- **Token Reduction**: 30-60% fewer tokens than JSON
|
|
84
91
|
- **Cost Savings**: Reduce API costs significantly
|
|
@@ -152,11 +159,14 @@ cdc generate tests mymodule.py --interactive
|
|
|
152
159
|
# Code review
|
|
153
160
|
cdc review mymodule.py
|
|
154
161
|
|
|
162
|
+
# Code review with auto-context (includes git, dependencies, tests)
|
|
163
|
+
cdc review mymodule.py --auto-context
|
|
164
|
+
|
|
155
165
|
# Code review with interactive follow-up questions
|
|
156
166
|
cdc review mymodule.py --interactive
|
|
157
167
|
|
|
158
|
-
# Debug errors
|
|
159
|
-
python script.py 2>&1 | cdc debug
|
|
168
|
+
# Debug errors with intelligent error parsing
|
|
169
|
+
python script.py 2>&1 | cdc debug --auto-context
|
|
160
170
|
|
|
161
171
|
# Generate documentation
|
|
162
172
|
cdc generate docs mymodule.py
|
|
@@ -164,8 +174,8 @@ cdc generate docs mymodule.py
|
|
|
164
174
|
# Generate docs with interactive refinement
|
|
165
175
|
cdc generate docs mymodule.py --interactive
|
|
166
176
|
|
|
167
|
-
# Refactor
|
|
168
|
-
cdc refactor legacy_code.py
|
|
177
|
+
# Refactor with context (includes related files)
|
|
178
|
+
cdc refactor legacy_code.py --auto-context
|
|
169
179
|
|
|
170
180
|
# Refactor with interactive refinement
|
|
171
181
|
cdc refactor legacy_code.py --interactive
|
|
@@ -175,6 +185,28 @@ git add .
|
|
|
175
185
|
cdc git commit
|
|
176
186
|
```
|
|
177
187
|
|
|
188
|
+
### 4. Context-Aware Operations (NEW in v0.8.0)
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Auto-context includes: git info, dependencies, related files
|
|
192
|
+
|
|
193
|
+
# Review with full project context
|
|
194
|
+
cdc review mymodule.py --auto-context
|
|
195
|
+
# ✓ Context gathered (git, dependencies, tests)
|
|
196
|
+
|
|
197
|
+
# Debug with parsed error details
|
|
198
|
+
python broken.py 2>&1 | cdc debug -f broken.py --auto-context
|
|
199
|
+
# ✓ Context gathered (error details, git context)
|
|
200
|
+
|
|
201
|
+
# Ask questions with file context
|
|
202
|
+
cdc ask -f mycode.py --auto-context "how can I improve this?"
|
|
203
|
+
# ✓ Context gathered
|
|
204
|
+
|
|
205
|
+
# Refactor with related files
|
|
206
|
+
cdc refactor app.py --auto-context
|
|
207
|
+
# Automatically includes imported modules and dependencies
|
|
208
|
+
```
|
|
209
|
+
|
|
178
210
|
### 5. Custom Templates
|
|
179
211
|
|
|
180
212
|
```bash
|
|
@@ -35,6 +35,13 @@ A powerful command-line tool for developers using Claude AI with multi-API routi
|
|
|
35
35
|
- **Variable Substitution**: Use {{variable}} placeholders for dynamic content
|
|
36
36
|
- **Categories**: Organize templates by category (review, testing, debugging, etc.)
|
|
37
37
|
|
|
38
|
+
### 🧠 Context Intelligence (NEW in v0.8.0)
|
|
39
|
+
- **Auto-Context**: `--auto-context` flag for intelligent context gathering
|
|
40
|
+
- **Git Integration**: Automatically include branch, commits, modified files
|
|
41
|
+
- **Dependency Analysis**: Parse imports and include related files
|
|
42
|
+
- **Error Parsing**: Structured Python traceback parsing
|
|
43
|
+
- **Project Memory**: Remember preferences per project
|
|
44
|
+
|
|
38
45
|
### 🎒 TOON Format Support (Optional)
|
|
39
46
|
- **Token Reduction**: 30-60% fewer tokens than JSON
|
|
40
47
|
- **Cost Savings**: Reduce API costs significantly
|
|
@@ -108,11 +115,14 @@ cdc generate tests mymodule.py --interactive
|
|
|
108
115
|
# Code review
|
|
109
116
|
cdc review mymodule.py
|
|
110
117
|
|
|
118
|
+
# Code review with auto-context (includes git, dependencies, tests)
|
|
119
|
+
cdc review mymodule.py --auto-context
|
|
120
|
+
|
|
111
121
|
# Code review with interactive follow-up questions
|
|
112
122
|
cdc review mymodule.py --interactive
|
|
113
123
|
|
|
114
|
-
# Debug errors
|
|
115
|
-
python script.py 2>&1 | cdc debug
|
|
124
|
+
# Debug errors with intelligent error parsing
|
|
125
|
+
python script.py 2>&1 | cdc debug --auto-context
|
|
116
126
|
|
|
117
127
|
# Generate documentation
|
|
118
128
|
cdc generate docs mymodule.py
|
|
@@ -120,8 +130,8 @@ cdc generate docs mymodule.py
|
|
|
120
130
|
# Generate docs with interactive refinement
|
|
121
131
|
cdc generate docs mymodule.py --interactive
|
|
122
132
|
|
|
123
|
-
# Refactor
|
|
124
|
-
cdc refactor legacy_code.py
|
|
133
|
+
# Refactor with context (includes related files)
|
|
134
|
+
cdc refactor legacy_code.py --auto-context
|
|
125
135
|
|
|
126
136
|
# Refactor with interactive refinement
|
|
127
137
|
cdc refactor legacy_code.py --interactive
|
|
@@ -131,6 +141,28 @@ git add .
|
|
|
131
141
|
cdc git commit
|
|
132
142
|
```
|
|
133
143
|
|
|
144
|
+
### 4. Context-Aware Operations (NEW in v0.8.0)
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Auto-context includes: git info, dependencies, related files
|
|
148
|
+
|
|
149
|
+
# Review with full project context
|
|
150
|
+
cdc review mymodule.py --auto-context
|
|
151
|
+
# ✓ Context gathered (git, dependencies, tests)
|
|
152
|
+
|
|
153
|
+
# Debug with parsed error details
|
|
154
|
+
python broken.py 2>&1 | cdc debug -f broken.py --auto-context
|
|
155
|
+
# ✓ Context gathered (error details, git context)
|
|
156
|
+
|
|
157
|
+
# Ask questions with file context
|
|
158
|
+
cdc ask -f mycode.py --auto-context "how can I improve this?"
|
|
159
|
+
# ✓ Context gathered
|
|
160
|
+
|
|
161
|
+
# Refactor with related files
|
|
162
|
+
cdc refactor app.py --auto-context
|
|
163
|
+
# Automatically includes imported modules and dependencies
|
|
164
|
+
```
|
|
165
|
+
|
|
134
166
|
### 5. Custom Templates
|
|
135
167
|
|
|
136
168
|
```bash
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "claude-dev-cli"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.8.0"
|
|
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"
|
|
@@ -57,6 +57,7 @@ except Exception:
|
|
|
57
57
|
@click.option('-a', '--api', help='API config to use')
|
|
58
58
|
@click.option('-m', '--model', help='Claude model to use')
|
|
59
59
|
@click.option('--stream/--no-stream', default=True, help='Stream response')
|
|
60
|
+
@click.option('--auto-context', is_flag=True, help='Automatically include git, dependencies, and related files')
|
|
60
61
|
@click.pass_context
|
|
61
62
|
def ask(
|
|
62
63
|
ctx: click.Context,
|
|
@@ -65,7 +66,8 @@ def ask(
|
|
|
65
66
|
system: Optional[str],
|
|
66
67
|
api: Optional[str],
|
|
67
68
|
model: Optional[str],
|
|
68
|
-
stream: bool
|
|
69
|
+
stream: bool,
|
|
70
|
+
auto_context: bool
|
|
69
71
|
) -> None:
|
|
70
72
|
"""Ask Claude a question (single-shot mode)."""
|
|
71
73
|
console = ctx.obj['console']
|
|
@@ -73,7 +75,18 @@ def ask(
|
|
|
73
75
|
# Build prompt
|
|
74
76
|
prompt_parts = []
|
|
75
77
|
|
|
76
|
-
if
|
|
78
|
+
# Gather context if requested
|
|
79
|
+
if auto_context and file:
|
|
80
|
+
from claude_dev_cli.context import ContextGatherer
|
|
81
|
+
|
|
82
|
+
with console.status("[bold blue]Gathering context..."):
|
|
83
|
+
gatherer = ContextGatherer()
|
|
84
|
+
context = gatherer.gather_for_file(Path(file))
|
|
85
|
+
context_info = context.format_for_prompt()
|
|
86
|
+
|
|
87
|
+
console.print("[dim]✓ Context gathered[/dim]")
|
|
88
|
+
prompt_parts.append(context_info)
|
|
89
|
+
elif file:
|
|
77
90
|
with open(file, 'r') as f:
|
|
78
91
|
file_content = f.read()
|
|
79
92
|
prompt_parts.append(f"File: {file}\n\n{file_content}\n\n")
|
|
@@ -584,19 +597,42 @@ def gen_docs(
|
|
|
584
597
|
@click.argument('file_path', type=click.Path(exists=True))
|
|
585
598
|
@click.option('-a', '--api', help='API config to use')
|
|
586
599
|
@click.option('-i', '--interactive', is_flag=True, help='Interactive follow-up questions')
|
|
600
|
+
@click.option('--auto-context', is_flag=True, help='Automatically include git, dependencies, and related files')
|
|
587
601
|
@click.pass_context
|
|
588
602
|
def review(
|
|
589
603
|
ctx: click.Context,
|
|
590
604
|
file_path: str,
|
|
591
605
|
api: Optional[str],
|
|
592
|
-
interactive: bool
|
|
606
|
+
interactive: bool,
|
|
607
|
+
auto_context: bool
|
|
593
608
|
) -> None:
|
|
594
609
|
"""Review code for bugs and improvements."""
|
|
595
610
|
console = ctx.obj['console']
|
|
596
611
|
|
|
597
612
|
try:
|
|
613
|
+
# Gather context if requested
|
|
614
|
+
context_info = ""
|
|
615
|
+
if auto_context:
|
|
616
|
+
from claude_dev_cli.context import ContextGatherer
|
|
617
|
+
|
|
618
|
+
with console.status("[bold blue]Gathering context..."):
|
|
619
|
+
gatherer = ContextGatherer()
|
|
620
|
+
context = gatherer.gather_for_review(Path(file_path))
|
|
621
|
+
context_info = context.format_for_prompt()
|
|
622
|
+
|
|
623
|
+
console.print("[dim]✓ Context gathered (git, dependencies, tests)[/dim]")
|
|
624
|
+
|
|
598
625
|
with console.status("[bold blue]Reviewing code..."):
|
|
599
|
-
|
|
626
|
+
# If we have context, prepend it to the file analysis
|
|
627
|
+
if context_info:
|
|
628
|
+
# Read file separately for context-aware review
|
|
629
|
+
result = code_review(file_path, api_config_name=api)
|
|
630
|
+
# The context module already includes the file, so we use it differently
|
|
631
|
+
client = ClaudeClient(api_config_name=api)
|
|
632
|
+
enhanced_prompt = f"{context_info}\n\nPlease review this code for bugs and improvements."
|
|
633
|
+
result = client.call(enhanced_prompt)
|
|
634
|
+
else:
|
|
635
|
+
result = code_review(file_path, api_config_name=api)
|
|
600
636
|
|
|
601
637
|
md = Markdown(result)
|
|
602
638
|
console.print(md)
|
|
@@ -633,12 +669,14 @@ def review(
|
|
|
633
669
|
@click.option('-f', '--file', type=click.Path(exists=True), help='File to debug')
|
|
634
670
|
@click.option('-e', '--error', help='Error message to analyze')
|
|
635
671
|
@click.option('-a', '--api', help='API config to use')
|
|
672
|
+
@click.option('--auto-context', is_flag=True, help='Automatically include git context and parse error details')
|
|
636
673
|
@click.pass_context
|
|
637
674
|
def debug(
|
|
638
675
|
ctx: click.Context,
|
|
639
676
|
file: Optional[str],
|
|
640
677
|
error: Optional[str],
|
|
641
|
-
api: Optional[str]
|
|
678
|
+
api: Optional[str],
|
|
679
|
+
auto_context: bool
|
|
642
680
|
) -> None:
|
|
643
681
|
"""Debug code and analyze errors."""
|
|
644
682
|
console = ctx.obj['console']
|
|
@@ -648,13 +686,33 @@ def debug(
|
|
|
648
686
|
if not sys.stdin.isatty():
|
|
649
687
|
stdin_content = sys.stdin.read().strip()
|
|
650
688
|
|
|
689
|
+
error_text = error or stdin_content
|
|
690
|
+
|
|
651
691
|
try:
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
692
|
+
# Gather context if requested
|
|
693
|
+
if auto_context and error_text:
|
|
694
|
+
from claude_dev_cli.context import ContextGatherer
|
|
695
|
+
|
|
696
|
+
with console.status("[bold blue]Gathering context..."):
|
|
697
|
+
gatherer = ContextGatherer()
|
|
698
|
+
file_path = Path(file) if file else None
|
|
699
|
+
context = gatherer.gather_for_error(error_text, file_path=file_path)
|
|
700
|
+
context_info = context.format_for_prompt()
|
|
701
|
+
|
|
702
|
+
console.print("[dim]✓ Context gathered (error details, git context)[/dim]")
|
|
703
|
+
|
|
704
|
+
# Use context-aware analysis
|
|
705
|
+
client = ClaudeClient(api_config_name=api)
|
|
706
|
+
enhanced_prompt = f"{context_info}\n\nPlease analyze this error and suggest fixes."
|
|
707
|
+
result = client.call(enhanced_prompt)
|
|
708
|
+
else:
|
|
709
|
+
# Original behavior
|
|
710
|
+
with console.status("[bold blue]Analyzing error..."):
|
|
711
|
+
result = debug_code(
|
|
712
|
+
file_path=file,
|
|
713
|
+
error_message=error_text,
|
|
714
|
+
api_config_name=api
|
|
715
|
+
)
|
|
658
716
|
|
|
659
717
|
md = Markdown(result)
|
|
660
718
|
console.print(md)
|
|
@@ -669,20 +727,38 @@ def debug(
|
|
|
669
727
|
@click.option('-o', '--output', type=click.Path(), help='Output file path')
|
|
670
728
|
@click.option('-a', '--api', help='API config to use')
|
|
671
729
|
@click.option('-i', '--interactive', is_flag=True, help='Interactive refinement mode')
|
|
730
|
+
@click.option('--auto-context', is_flag=True, help='Automatically include git, dependencies, and related files')
|
|
672
731
|
@click.pass_context
|
|
673
732
|
def refactor(
|
|
674
733
|
ctx: click.Context,
|
|
675
734
|
file_path: str,
|
|
676
735
|
output: Optional[str],
|
|
677
736
|
api: Optional[str],
|
|
678
|
-
interactive: bool
|
|
737
|
+
interactive: bool,
|
|
738
|
+
auto_context: bool
|
|
679
739
|
) -> None:
|
|
680
740
|
"""Suggest refactoring improvements."""
|
|
681
741
|
console = ctx.obj['console']
|
|
682
742
|
|
|
683
743
|
try:
|
|
684
|
-
|
|
685
|
-
|
|
744
|
+
# Gather context if requested
|
|
745
|
+
if auto_context:
|
|
746
|
+
from claude_dev_cli.context import ContextGatherer
|
|
747
|
+
|
|
748
|
+
with console.status("[bold blue]Gathering context..."):
|
|
749
|
+
gatherer = ContextGatherer()
|
|
750
|
+
context = gatherer.gather_for_file(Path(file_path))
|
|
751
|
+
context_info = context.format_for_prompt()
|
|
752
|
+
|
|
753
|
+
console.print("[dim]✓ Context gathered[/dim]")
|
|
754
|
+
|
|
755
|
+
# Use context-aware refactoring
|
|
756
|
+
client = ClaudeClient(api_config_name=api)
|
|
757
|
+
enhanced_prompt = f"{context_info}\n\nPlease suggest refactoring improvements for the main file."
|
|
758
|
+
result = client.call(enhanced_prompt)
|
|
759
|
+
else:
|
|
760
|
+
with console.status("[bold blue]Analyzing code..."):
|
|
761
|
+
result = refactor_code(file_path, api_config_name=api)
|
|
686
762
|
|
|
687
763
|
if interactive:
|
|
688
764
|
console.print("\n[bold]Initial Refactoring:[/bold]\n")
|
|
@@ -25,6 +25,12 @@ class ProjectProfile(BaseModel):
|
|
|
25
25
|
api_config: str # Name of the API config to use
|
|
26
26
|
system_prompt: Optional[str] = None
|
|
27
27
|
allowed_commands: List[str] = Field(default_factory=lambda: ["all"])
|
|
28
|
+
|
|
29
|
+
# Project memory - preferences and patterns
|
|
30
|
+
auto_context: bool = False # Default value for --auto-context flag
|
|
31
|
+
coding_style: Optional[str] = None # Preferred coding style
|
|
32
|
+
test_framework: Optional[str] = None # Preferred test framework
|
|
33
|
+
preferences: Dict[str, str] = Field(default_factory=dict) # Custom preferences
|
|
28
34
|
|
|
29
35
|
|
|
30
36
|
class Config:
|
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
"""Intelligent context gathering for AI operations."""
|
|
2
|
+
|
|
3
|
+
import ast
|
|
4
|
+
import json
|
|
5
|
+
import re
|
|
6
|
+
import subprocess
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Dict, List, Optional, Set
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ContextItem:
|
|
14
|
+
"""A single piece of context information."""
|
|
15
|
+
type: str # 'file', 'git', 'dependency', 'error'
|
|
16
|
+
content: str
|
|
17
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
18
|
+
|
|
19
|
+
def format_for_prompt(self) -> str:
|
|
20
|
+
"""Format this context item for inclusion in a prompt."""
|
|
21
|
+
if self.type == 'file':
|
|
22
|
+
path = self.metadata.get('path', 'unknown')
|
|
23
|
+
return f"# File: {path}\n\n{self.content}\n"
|
|
24
|
+
elif self.type == 'git':
|
|
25
|
+
return f"# Git Context\n\n{self.content}\n"
|
|
26
|
+
elif self.type == 'dependency':
|
|
27
|
+
return f"# Dependencies\n\n{self.content}\n"
|
|
28
|
+
elif self.type == 'error':
|
|
29
|
+
return f"# Error Context\n\n{self.content}\n"
|
|
30
|
+
else:
|
|
31
|
+
return self.content
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class Context:
|
|
36
|
+
"""Collection of context items."""
|
|
37
|
+
items: List[ContextItem] = field(default_factory=list)
|
|
38
|
+
|
|
39
|
+
def add(self, item: ContextItem) -> None:
|
|
40
|
+
"""Add a context item."""
|
|
41
|
+
self.items.append(item)
|
|
42
|
+
|
|
43
|
+
def format_for_prompt(self) -> str:
|
|
44
|
+
"""Format all context items for inclusion in a prompt."""
|
|
45
|
+
if not self.items:
|
|
46
|
+
return ""
|
|
47
|
+
|
|
48
|
+
parts = ["# Context Information\n"]
|
|
49
|
+
for item in self.items:
|
|
50
|
+
parts.append(item.format_for_prompt())
|
|
51
|
+
|
|
52
|
+
return "\n".join(parts)
|
|
53
|
+
|
|
54
|
+
def get_by_type(self, context_type: str) -> List[ContextItem]:
|
|
55
|
+
"""Get all context items of a specific type."""
|
|
56
|
+
return [item for item in self.items if item.type == context_type]
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class GitContext:
|
|
60
|
+
"""Gather Git-related context."""
|
|
61
|
+
|
|
62
|
+
def __init__(self, cwd: Optional[Path] = None):
|
|
63
|
+
self.cwd = cwd or Path.cwd()
|
|
64
|
+
|
|
65
|
+
def is_git_repo(self) -> bool:
|
|
66
|
+
"""Check if current directory is a git repository."""
|
|
67
|
+
try:
|
|
68
|
+
result = subprocess.run(
|
|
69
|
+
['git', 'rev-parse', '--git-dir'],
|
|
70
|
+
cwd=self.cwd,
|
|
71
|
+
capture_output=True,
|
|
72
|
+
text=True
|
|
73
|
+
)
|
|
74
|
+
return result.returncode == 0
|
|
75
|
+
except Exception:
|
|
76
|
+
return False
|
|
77
|
+
|
|
78
|
+
def get_current_branch(self) -> Optional[str]:
|
|
79
|
+
"""Get the current git branch."""
|
|
80
|
+
try:
|
|
81
|
+
result = subprocess.run(
|
|
82
|
+
['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
|
|
83
|
+
cwd=self.cwd,
|
|
84
|
+
capture_output=True,
|
|
85
|
+
text=True,
|
|
86
|
+
check=True
|
|
87
|
+
)
|
|
88
|
+
return result.stdout.strip()
|
|
89
|
+
except Exception:
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
def get_recent_commits(self, count: int = 5) -> List[Dict[str, str]]:
|
|
93
|
+
"""Get recent commit messages."""
|
|
94
|
+
try:
|
|
95
|
+
result = subprocess.run(
|
|
96
|
+
['git', '--no-pager', 'log', f'-{count}', '--pretty=format:%h|%s|%an|%ar'],
|
|
97
|
+
cwd=self.cwd,
|
|
98
|
+
capture_output=True,
|
|
99
|
+
text=True,
|
|
100
|
+
check=True
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
commits = []
|
|
104
|
+
for line in result.stdout.strip().split('\n'):
|
|
105
|
+
if line:
|
|
106
|
+
parts = line.split('|', 3)
|
|
107
|
+
if len(parts) == 4:
|
|
108
|
+
commits.append({
|
|
109
|
+
'hash': parts[0],
|
|
110
|
+
'message': parts[1],
|
|
111
|
+
'author': parts[2],
|
|
112
|
+
'date': parts[3]
|
|
113
|
+
})
|
|
114
|
+
return commits
|
|
115
|
+
except Exception:
|
|
116
|
+
return []
|
|
117
|
+
|
|
118
|
+
def get_staged_diff(self) -> Optional[str]:
|
|
119
|
+
"""Get diff of staged changes."""
|
|
120
|
+
try:
|
|
121
|
+
result = subprocess.run(
|
|
122
|
+
['git', '--no-pager', 'diff', '--cached'],
|
|
123
|
+
cwd=self.cwd,
|
|
124
|
+
capture_output=True,
|
|
125
|
+
text=True,
|
|
126
|
+
check=True
|
|
127
|
+
)
|
|
128
|
+
return result.stdout if result.stdout else None
|
|
129
|
+
except Exception:
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
def get_unstaged_diff(self) -> Optional[str]:
|
|
133
|
+
"""Get diff of unstaged changes."""
|
|
134
|
+
try:
|
|
135
|
+
result = subprocess.run(
|
|
136
|
+
['git', '--no-pager', 'diff'],
|
|
137
|
+
cwd=self.cwd,
|
|
138
|
+
capture_output=True,
|
|
139
|
+
text=True,
|
|
140
|
+
check=True
|
|
141
|
+
)
|
|
142
|
+
return result.stdout if result.stdout else None
|
|
143
|
+
except Exception:
|
|
144
|
+
return None
|
|
145
|
+
|
|
146
|
+
def get_modified_files(self) -> List[str]:
|
|
147
|
+
"""Get list of modified files."""
|
|
148
|
+
try:
|
|
149
|
+
result = subprocess.run(
|
|
150
|
+
['git', 'status', '--porcelain'],
|
|
151
|
+
cwd=self.cwd,
|
|
152
|
+
capture_output=True,
|
|
153
|
+
text=True,
|
|
154
|
+
check=True
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
files = []
|
|
158
|
+
for line in result.stdout.strip().split('\n'):
|
|
159
|
+
if line:
|
|
160
|
+
# Format: "XY filename"
|
|
161
|
+
parts = line.strip().split(maxsplit=1)
|
|
162
|
+
if len(parts) == 2:
|
|
163
|
+
files.append(parts[1])
|
|
164
|
+
return files
|
|
165
|
+
except Exception:
|
|
166
|
+
return []
|
|
167
|
+
|
|
168
|
+
def gather(self, include_diff: bool = False) -> ContextItem:
|
|
169
|
+
"""Gather all git context."""
|
|
170
|
+
parts = []
|
|
171
|
+
|
|
172
|
+
branch = self.get_current_branch()
|
|
173
|
+
if branch:
|
|
174
|
+
parts.append(f"Branch: {branch}")
|
|
175
|
+
|
|
176
|
+
commits = self.get_recent_commits(5)
|
|
177
|
+
if commits:
|
|
178
|
+
parts.append("\nRecent commits:")
|
|
179
|
+
for commit in commits:
|
|
180
|
+
parts.append(f" {commit['hash']} - {commit['message']} ({commit['date']})")
|
|
181
|
+
|
|
182
|
+
modified = self.get_modified_files()
|
|
183
|
+
if modified:
|
|
184
|
+
parts.append(f"\nModified files: {', '.join(modified[:10])}")
|
|
185
|
+
|
|
186
|
+
if include_diff:
|
|
187
|
+
staged = self.get_staged_diff()
|
|
188
|
+
if staged:
|
|
189
|
+
parts.append(f"\nStaged changes:\n{staged[:1000]}...") # Limit size
|
|
190
|
+
|
|
191
|
+
content = "\n".join(parts) if parts else "No git context available"
|
|
192
|
+
|
|
193
|
+
return ContextItem(
|
|
194
|
+
type='git',
|
|
195
|
+
content=content,
|
|
196
|
+
metadata={'branch': branch, 'modified_count': len(modified)}
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class DependencyAnalyzer:
|
|
201
|
+
"""Analyze project dependencies and imports."""
|
|
202
|
+
|
|
203
|
+
def __init__(self, project_root: Path):
|
|
204
|
+
self.project_root = project_root
|
|
205
|
+
|
|
206
|
+
def find_python_imports(self, file_path: Path) -> Set[str]:
|
|
207
|
+
"""Extract imports from a Python file."""
|
|
208
|
+
imports = set()
|
|
209
|
+
|
|
210
|
+
try:
|
|
211
|
+
with open(file_path, 'r') as f:
|
|
212
|
+
tree = ast.parse(f.read())
|
|
213
|
+
|
|
214
|
+
for node in ast.walk(tree):
|
|
215
|
+
if isinstance(node, ast.Import):
|
|
216
|
+
for name in node.names:
|
|
217
|
+
imports.add(name.name.split('.')[0])
|
|
218
|
+
elif isinstance(node, ast.ImportFrom):
|
|
219
|
+
if node.module:
|
|
220
|
+
imports.add(node.module.split('.')[0])
|
|
221
|
+
except Exception:
|
|
222
|
+
pass
|
|
223
|
+
|
|
224
|
+
return imports
|
|
225
|
+
|
|
226
|
+
def find_related_files(self, file_path: Path, max_depth: int = 2) -> List[Path]:
|
|
227
|
+
"""Find files related to the given file through imports."""
|
|
228
|
+
if not file_path.suffix == '.py':
|
|
229
|
+
return []
|
|
230
|
+
|
|
231
|
+
related = []
|
|
232
|
+
imports = self.find_python_imports(file_path)
|
|
233
|
+
|
|
234
|
+
# Look for local modules
|
|
235
|
+
for imp in imports:
|
|
236
|
+
# Try as module file
|
|
237
|
+
module_file = self.project_root / f"{imp}.py"
|
|
238
|
+
if module_file.exists() and module_file != file_path:
|
|
239
|
+
related.append(module_file)
|
|
240
|
+
|
|
241
|
+
# Try as package
|
|
242
|
+
package_init = self.project_root / imp / "__init__.py"
|
|
243
|
+
if package_init.exists():
|
|
244
|
+
related.append(package_init)
|
|
245
|
+
|
|
246
|
+
return related[:5] # Limit to avoid too many files
|
|
247
|
+
|
|
248
|
+
def get_dependency_files(self) -> List[Path]:
|
|
249
|
+
"""Find dependency configuration files."""
|
|
250
|
+
files = []
|
|
251
|
+
|
|
252
|
+
# Python
|
|
253
|
+
for name in ['requirements.txt', 'setup.py', 'pyproject.toml', 'Pipfile']:
|
|
254
|
+
file = self.project_root / name
|
|
255
|
+
if file.exists():
|
|
256
|
+
files.append(file)
|
|
257
|
+
|
|
258
|
+
# Node.js
|
|
259
|
+
for name in ['package.json', 'package-lock.json']:
|
|
260
|
+
file = self.project_root / name
|
|
261
|
+
if file.exists():
|
|
262
|
+
files.append(file)
|
|
263
|
+
|
|
264
|
+
# Other
|
|
265
|
+
for name in ['Gemfile', 'go.mod', 'Cargo.toml']:
|
|
266
|
+
file = self.project_root / name
|
|
267
|
+
if file.exists():
|
|
268
|
+
files.append(file)
|
|
269
|
+
|
|
270
|
+
return files
|
|
271
|
+
|
|
272
|
+
def gather(self, target_file: Optional[Path] = None) -> ContextItem:
|
|
273
|
+
"""Gather dependency context."""
|
|
274
|
+
parts = []
|
|
275
|
+
|
|
276
|
+
# Include dependency files
|
|
277
|
+
dep_files = self.get_dependency_files()
|
|
278
|
+
if dep_files:
|
|
279
|
+
parts.append("Dependency files:")
|
|
280
|
+
for file in dep_files[:3]: # Limit
|
|
281
|
+
parts.append(f" - {file.name}")
|
|
282
|
+
try:
|
|
283
|
+
content = file.read_text()
|
|
284
|
+
# Include only relevant parts
|
|
285
|
+
if file.suffix == '.json':
|
|
286
|
+
data = json.loads(content)
|
|
287
|
+
if 'dependencies' in data:
|
|
288
|
+
parts.append(f" Dependencies: {', '.join(list(data['dependencies'].keys())[:10])}")
|
|
289
|
+
elif file.suffix == '.txt':
|
|
290
|
+
lines = content.split('\n')[:20]
|
|
291
|
+
parts.append(f" Requirements: {', '.join([l.split('==')[0] for l in lines if l and not l.startswith('#')])}")
|
|
292
|
+
except Exception:
|
|
293
|
+
pass
|
|
294
|
+
|
|
295
|
+
# Related files if target specified
|
|
296
|
+
if target_file and target_file.exists():
|
|
297
|
+
related = self.find_related_files(target_file)
|
|
298
|
+
if related:
|
|
299
|
+
parts.append(f"\nRelated files for {target_file.name}:")
|
|
300
|
+
for file in related:
|
|
301
|
+
parts.append(f" - {file.relative_to(self.project_root)}")
|
|
302
|
+
|
|
303
|
+
content = "\n".join(parts) if parts else "No dependency context found"
|
|
304
|
+
|
|
305
|
+
return ContextItem(
|
|
306
|
+
type='dependency',
|
|
307
|
+
content=content,
|
|
308
|
+
metadata={'dependency_files': [str(f) for f in dep_files]}
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class ErrorContext:
|
|
313
|
+
"""Parse and format error context."""
|
|
314
|
+
|
|
315
|
+
@staticmethod
|
|
316
|
+
def parse_traceback(error_text: str) -> Dict[str, Any]:
|
|
317
|
+
"""Parse Python traceback into structured data."""
|
|
318
|
+
lines = error_text.split('\n')
|
|
319
|
+
|
|
320
|
+
# Find traceback start
|
|
321
|
+
traceback_start = -1
|
|
322
|
+
for i, line in enumerate(lines):
|
|
323
|
+
if 'Traceback' in line:
|
|
324
|
+
traceback_start = i
|
|
325
|
+
break
|
|
326
|
+
|
|
327
|
+
if traceback_start == -1:
|
|
328
|
+
return {'raw': error_text}
|
|
329
|
+
|
|
330
|
+
# Extract frames
|
|
331
|
+
frames = []
|
|
332
|
+
current_frame = {}
|
|
333
|
+
|
|
334
|
+
for line in lines[traceback_start + 1:]:
|
|
335
|
+
if line.startswith(' File '):
|
|
336
|
+
if current_frame:
|
|
337
|
+
frames.append(current_frame)
|
|
338
|
+
|
|
339
|
+
# Parse: File "path", line X, in function
|
|
340
|
+
match = re.match(r'\s*File "([^"]+)", line (\d+), in (.+)', line)
|
|
341
|
+
if match:
|
|
342
|
+
current_frame = {
|
|
343
|
+
'file': match.group(1),
|
|
344
|
+
'line': int(match.group(2)),
|
|
345
|
+
'function': match.group(3)
|
|
346
|
+
}
|
|
347
|
+
elif line.startswith(' ') and current_frame:
|
|
348
|
+
current_frame['code'] = line.strip()
|
|
349
|
+
elif line and not line.startswith(' '):
|
|
350
|
+
# Error message
|
|
351
|
+
if current_frame:
|
|
352
|
+
frames.append(current_frame)
|
|
353
|
+
current_frame = {}
|
|
354
|
+
|
|
355
|
+
error_type = line.split(':')[0] if ':' in line else line
|
|
356
|
+
error_message = line.split(':', 1)[1].strip() if ':' in line else ''
|
|
357
|
+
|
|
358
|
+
return {
|
|
359
|
+
'frames': frames,
|
|
360
|
+
'error_type': error_type,
|
|
361
|
+
'error_message': error_message,
|
|
362
|
+
'raw': error_text
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return {'frames': frames, 'raw': error_text}
|
|
366
|
+
|
|
367
|
+
@staticmethod
|
|
368
|
+
def format_for_ai(error_text: str) -> str:
|
|
369
|
+
"""Format error for AI consumption."""
|
|
370
|
+
parsed = ErrorContext.parse_traceback(error_text)
|
|
371
|
+
|
|
372
|
+
if 'error_type' not in parsed:
|
|
373
|
+
return error_text
|
|
374
|
+
|
|
375
|
+
parts = [
|
|
376
|
+
f"Error Type: {parsed['error_type']}",
|
|
377
|
+
f"Error Message: {parsed.get('error_message', 'N/A')}",
|
|
378
|
+
"\nStack Trace:"
|
|
379
|
+
]
|
|
380
|
+
|
|
381
|
+
for i, frame in enumerate(parsed.get('frames', []), 1):
|
|
382
|
+
parts.append(f" {i}. {frame.get('file', 'unknown')}:{frame.get('line', '?')} in {frame.get('function', 'unknown')}")
|
|
383
|
+
if 'code' in frame:
|
|
384
|
+
parts.append(f" > {frame['code']}")
|
|
385
|
+
|
|
386
|
+
return "\n".join(parts)
|
|
387
|
+
|
|
388
|
+
def gather(self, error_text: str) -> ContextItem:
|
|
389
|
+
"""Gather error context."""
|
|
390
|
+
formatted = self.format_for_ai(error_text)
|
|
391
|
+
parsed = self.parse_traceback(error_text)
|
|
392
|
+
|
|
393
|
+
return ContextItem(
|
|
394
|
+
type='error',
|
|
395
|
+
content=formatted,
|
|
396
|
+
metadata=parsed
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
class ContextGatherer:
|
|
401
|
+
"""Main context gathering coordinator."""
|
|
402
|
+
|
|
403
|
+
def __init__(self, project_root: Optional[Path] = None):
|
|
404
|
+
self.project_root = project_root or Path.cwd()
|
|
405
|
+
self.git = GitContext(self.project_root)
|
|
406
|
+
self.dependencies = DependencyAnalyzer(self.project_root)
|
|
407
|
+
self.error_parser = ErrorContext()
|
|
408
|
+
|
|
409
|
+
def gather_for_file(
|
|
410
|
+
self,
|
|
411
|
+
file_path: Path,
|
|
412
|
+
include_git: bool = True,
|
|
413
|
+
include_dependencies: bool = True,
|
|
414
|
+
include_related: bool = True
|
|
415
|
+
) -> Context:
|
|
416
|
+
"""Gather context for a specific file operation."""
|
|
417
|
+
context = Context()
|
|
418
|
+
|
|
419
|
+
# Add the file itself
|
|
420
|
+
if file_path.exists():
|
|
421
|
+
context.add(ContextItem(
|
|
422
|
+
type='file',
|
|
423
|
+
content=file_path.read_text(),
|
|
424
|
+
metadata={'path': str(file_path)}
|
|
425
|
+
))
|
|
426
|
+
|
|
427
|
+
# Add git context
|
|
428
|
+
if include_git and self.git.is_git_repo():
|
|
429
|
+
context.add(self.git.gather(include_diff=False))
|
|
430
|
+
|
|
431
|
+
# Add dependency context
|
|
432
|
+
if include_dependencies:
|
|
433
|
+
context.add(self.dependencies.gather(target_file=file_path if include_related else None))
|
|
434
|
+
|
|
435
|
+
return context
|
|
436
|
+
|
|
437
|
+
def gather_for_error(
|
|
438
|
+
self,
|
|
439
|
+
error_text: str,
|
|
440
|
+
file_path: Optional[Path] = None,
|
|
441
|
+
include_git: bool = True
|
|
442
|
+
) -> Context:
|
|
443
|
+
"""Gather context for error debugging."""
|
|
444
|
+
context = Context()
|
|
445
|
+
|
|
446
|
+
# Add error context
|
|
447
|
+
context.add(self.error_parser.gather(error_text))
|
|
448
|
+
|
|
449
|
+
# Add file if provided
|
|
450
|
+
if file_path and file_path.exists():
|
|
451
|
+
context.add(ContextItem(
|
|
452
|
+
type='file',
|
|
453
|
+
content=file_path.read_text(),
|
|
454
|
+
metadata={'path': str(file_path)}
|
|
455
|
+
))
|
|
456
|
+
|
|
457
|
+
# Add git context
|
|
458
|
+
if include_git and self.git.is_git_repo():
|
|
459
|
+
context.add(self.git.gather(include_diff=False))
|
|
460
|
+
|
|
461
|
+
return context
|
|
462
|
+
|
|
463
|
+
def gather_for_review(
|
|
464
|
+
self,
|
|
465
|
+
file_path: Path,
|
|
466
|
+
include_git: bool = True,
|
|
467
|
+
include_tests: bool = True
|
|
468
|
+
) -> Context:
|
|
469
|
+
"""Gather context for code review."""
|
|
470
|
+
context = self.gather_for_file(
|
|
471
|
+
file_path,
|
|
472
|
+
include_git=include_git,
|
|
473
|
+
include_dependencies=True,
|
|
474
|
+
include_related=True
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
# Try to find test file
|
|
478
|
+
if include_tests:
|
|
479
|
+
test_patterns = [
|
|
480
|
+
self.project_root / "tests" / f"test_{file_path.name}",
|
|
481
|
+
self.project_root / f"test_{file_path.name}",
|
|
482
|
+
file_path.parent / f"test_{file_path.name}"
|
|
483
|
+
]
|
|
484
|
+
|
|
485
|
+
for test_file in test_patterns:
|
|
486
|
+
if test_file.exists():
|
|
487
|
+
context.add(ContextItem(
|
|
488
|
+
type='file',
|
|
489
|
+
content=test_file.read_text(),
|
|
490
|
+
metadata={'path': str(test_file), 'is_test': True}
|
|
491
|
+
))
|
|
492
|
+
break
|
|
493
|
+
|
|
494
|
+
return context
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-dev-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
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
|
|
@@ -79,6 +79,13 @@ A powerful command-line tool for developers using Claude AI with multi-API routi
|
|
|
79
79
|
- **Variable Substitution**: Use {{variable}} placeholders for dynamic content
|
|
80
80
|
- **Categories**: Organize templates by category (review, testing, debugging, etc.)
|
|
81
81
|
|
|
82
|
+
### 🧠 Context Intelligence (NEW in v0.8.0)
|
|
83
|
+
- **Auto-Context**: `--auto-context` flag for intelligent context gathering
|
|
84
|
+
- **Git Integration**: Automatically include branch, commits, modified files
|
|
85
|
+
- **Dependency Analysis**: Parse imports and include related files
|
|
86
|
+
- **Error Parsing**: Structured Python traceback parsing
|
|
87
|
+
- **Project Memory**: Remember preferences per project
|
|
88
|
+
|
|
82
89
|
### 🎒 TOON Format Support (Optional)
|
|
83
90
|
- **Token Reduction**: 30-60% fewer tokens than JSON
|
|
84
91
|
- **Cost Savings**: Reduce API costs significantly
|
|
@@ -152,11 +159,14 @@ cdc generate tests mymodule.py --interactive
|
|
|
152
159
|
# Code review
|
|
153
160
|
cdc review mymodule.py
|
|
154
161
|
|
|
162
|
+
# Code review with auto-context (includes git, dependencies, tests)
|
|
163
|
+
cdc review mymodule.py --auto-context
|
|
164
|
+
|
|
155
165
|
# Code review with interactive follow-up questions
|
|
156
166
|
cdc review mymodule.py --interactive
|
|
157
167
|
|
|
158
|
-
# Debug errors
|
|
159
|
-
python script.py 2>&1 | cdc debug
|
|
168
|
+
# Debug errors with intelligent error parsing
|
|
169
|
+
python script.py 2>&1 | cdc debug --auto-context
|
|
160
170
|
|
|
161
171
|
# Generate documentation
|
|
162
172
|
cdc generate docs mymodule.py
|
|
@@ -164,8 +174,8 @@ cdc generate docs mymodule.py
|
|
|
164
174
|
# Generate docs with interactive refinement
|
|
165
175
|
cdc generate docs mymodule.py --interactive
|
|
166
176
|
|
|
167
|
-
# Refactor
|
|
168
|
-
cdc refactor legacy_code.py
|
|
177
|
+
# Refactor with context (includes related files)
|
|
178
|
+
cdc refactor legacy_code.py --auto-context
|
|
169
179
|
|
|
170
180
|
# Refactor with interactive refinement
|
|
171
181
|
cdc refactor legacy_code.py --interactive
|
|
@@ -175,6 +185,28 @@ git add .
|
|
|
175
185
|
cdc git commit
|
|
176
186
|
```
|
|
177
187
|
|
|
188
|
+
### 4. Context-Aware Operations (NEW in v0.8.0)
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Auto-context includes: git info, dependencies, related files
|
|
192
|
+
|
|
193
|
+
# Review with full project context
|
|
194
|
+
cdc review mymodule.py --auto-context
|
|
195
|
+
# ✓ Context gathered (git, dependencies, tests)
|
|
196
|
+
|
|
197
|
+
# Debug with parsed error details
|
|
198
|
+
python broken.py 2>&1 | cdc debug -f broken.py --auto-context
|
|
199
|
+
# ✓ Context gathered (error details, git context)
|
|
200
|
+
|
|
201
|
+
# Ask questions with file context
|
|
202
|
+
cdc ask -f mycode.py --auto-context "how can I improve this?"
|
|
203
|
+
# ✓ Context gathered
|
|
204
|
+
|
|
205
|
+
# Refactor with related files
|
|
206
|
+
cdc refactor app.py --auto-context
|
|
207
|
+
# Automatically includes imported modules and dependencies
|
|
208
|
+
```
|
|
209
|
+
|
|
178
210
|
### 5. Custom Templates
|
|
179
211
|
|
|
180
212
|
```bash
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/__init__.py
RENAMED
|
File without changes
|
{claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/plugin.py
RENAMED
|
File without changes
|
{claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli/plugins/diff_editor/viewer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_dev_cli-0.7.0 → claude_dev_cli-0.8.0}/src/claude_dev_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|