axe-cli 1.7.6__py3-none-any.whl → 1.8.0__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.
- axe_cli/README.md +304 -0
- axe_cli/agents/README.md +160 -0
- axe_cli/agents/default/system.md +48 -4
- axe_cli/app.py +8 -3
- axe_cli/auth/__init__.py +3 -0
- axe_cli/config.py +12 -0
- axe_cli/llm.py +6 -3
- axe_cli/skills/README.md +242 -0
- axe_cli/soul/agent.py +11 -1
- axe_cli/soul/axesoul.py +10 -0
- axe_cli/tools/README.md +135 -0
- axe_cli/tools/axe/auto_init.py +27 -27
- axe_cli/tools/axe/context.py +1 -2
- axe_cli/tools/axe/impact.py +9 -1
- axe_cli/tools/axe/prewarm.py +1 -1
- axe_cli/tools/axe/search.py +11 -5
- axe_cli/ui/shell/__init__.py +2 -2
- axe_cli/ui/shell/slash.py +1 -1
- axe_cli-1.8.0.dist-info/METADATA +470 -0
- {axe_cli-1.7.6.dist-info → axe_cli-1.8.0.dist-info}/RECORD +22 -17
- axe_cli-1.7.6.dist-info/METADATA +0 -1399
- {axe_cli-1.7.6.dist-info → axe_cli-1.8.0.dist-info}/WHEEL +0 -0
- {axe_cli-1.7.6.dist-info → axe_cli-1.8.0.dist-info}/entry_points.txt +0 -0
axe_cli/skills/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Agent Skills
|
|
2
|
+
|
|
3
|
+
Agent Skills is an open format for adding specialized knowledge and workflows to AI agents. axe supports loading Agent Skills to extend AI capabilities.
|
|
4
|
+
|
|
5
|
+
## What are Agent Skills?
|
|
6
|
+
|
|
7
|
+
A skill is a directory containing a `SKILL.md` file. When axe starts, it discovers all skills and injects their names, paths, and descriptions into the system prompt. The AI will decide on its own whether to read the specific SKILL.md file to get detailed guidance based on the current task's needs.
|
|
8
|
+
|
|
9
|
+
For example, you can create a "code style" skill to tell the AI your project's naming conventions, comment styles, etc.; or create a "security audit" skill to have the AI focus on specific security issues when reviewing code.
|
|
10
|
+
|
|
11
|
+
## Skill discovery
|
|
12
|
+
|
|
13
|
+
axe uses a layered loading mechanism to discover skills, loading in the following priority order (later ones override skills with the same name):
|
|
14
|
+
|
|
15
|
+
**Built-in skills**
|
|
16
|
+
|
|
17
|
+
Skills shipped with the package, providing basic capabilities.
|
|
18
|
+
|
|
19
|
+
**User-level skills**
|
|
20
|
+
|
|
21
|
+
Stored in the user's home directory, effective across all projects. axe checks the following directories in priority order and uses the first one that exists:
|
|
22
|
+
|
|
23
|
+
- `~/.config/agents/skills/` (recommended)
|
|
24
|
+
- `~/.agents/skills/`
|
|
25
|
+
- `~/.axe/skills/`
|
|
26
|
+
- `~/.claude/skills/`
|
|
27
|
+
- `~/.codex/skills/`
|
|
28
|
+
|
|
29
|
+
**Project-level skills**
|
|
30
|
+
|
|
31
|
+
Stored in the project directory, only effective within that project's working directory. axe checks the following directories in priority order and uses the first one that exists:
|
|
32
|
+
|
|
33
|
+
- `.agents/skills/` (recommended)
|
|
34
|
+
- `.axe/skills/`
|
|
35
|
+
- `.claude/skills/`
|
|
36
|
+
- `.codex/skills/`
|
|
37
|
+
|
|
38
|
+
You can also specify other directories with the `--skills-dir` flag, which skips user-level and project-level skill discovery:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
axe --skills-dir /path/to/my-skills
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Built-in skills
|
|
45
|
+
|
|
46
|
+
axe includes the following built-in skills:
|
|
47
|
+
|
|
48
|
+
- **axe-cli-help**: axe CLI help. Answers questions about axe installation, configuration, slash commands, keyboard shortcuts, MCP integration, providers, environment variables, and more.
|
|
49
|
+
- **skill-creator**: Guide for creating skills. When you need to create a new skill (or update an existing skill) to extend axe's capabilities, you can use this skill to get detailed creation guidance and best practices.
|
|
50
|
+
|
|
51
|
+
## Creating a skill
|
|
52
|
+
|
|
53
|
+
Creating a skill only requires two steps:
|
|
54
|
+
|
|
55
|
+
1. Create a subdirectory in the skills directory
|
|
56
|
+
2. Create a SKILL.md file in the subdirectory
|
|
57
|
+
|
|
58
|
+
**Directory structure:**
|
|
59
|
+
|
|
60
|
+
A skill directory needs at least a SKILL.md file, and can also include auxiliary directories to organize more complex content:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
~/.config/agents/skills/
|
|
64
|
+
└── my-skill/
|
|
65
|
+
├── SKILL.md # Required: main file
|
|
66
|
+
├── scripts/ # Optional: script files
|
|
67
|
+
├── references/ # Optional: reference documents
|
|
68
|
+
└── assets/ # Optional: other resources
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**SKILL.md format:**
|
|
72
|
+
|
|
73
|
+
SKILL.md uses YAML frontmatter to define metadata, followed by prompt content in Markdown format:
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
---
|
|
77
|
+
name: code-style
|
|
78
|
+
description: My project's code style guidelines
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Code Style
|
|
82
|
+
|
|
83
|
+
In this project, please follow these conventions:
|
|
84
|
+
|
|
85
|
+
- Use 4-space indentation
|
|
86
|
+
- Variable names use camelCase
|
|
87
|
+
- Function names use snake_case
|
|
88
|
+
- Every function needs a docstring
|
|
89
|
+
- Lines should not exceed 100 characters
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Frontmatter fields:**
|
|
93
|
+
|
|
94
|
+
| Field | Description | Required |
|
|
95
|
+
|-------|-------------|----------|
|
|
96
|
+
| name | Skill name, 1-64 characters, only lowercase letters, numbers, and hyphens allowed; defaults to directory name if omitted | No |
|
|
97
|
+
| description | Skill description, 1-1024 characters, explaining the skill's purpose and use cases; shows "No description provided." if omitted | No |
|
|
98
|
+
| license | License name or file reference | No |
|
|
99
|
+
| compatibility | Environment requirements, up to 500 characters | No |
|
|
100
|
+
| metadata | Additional key-value attributes | No |
|
|
101
|
+
|
|
102
|
+
**Best practices:**
|
|
103
|
+
|
|
104
|
+
- Keep SKILL.md under 500 lines, move detailed content to scripts/, references/, or assets/ directories
|
|
105
|
+
- Use relative paths in SKILL.md to reference other files
|
|
106
|
+
- Provide clear step-by-step instructions, input/output examples, and edge case explanations
|
|
107
|
+
|
|
108
|
+
### Example skills
|
|
109
|
+
|
|
110
|
+
**PowerPoint creation:**
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
---
|
|
114
|
+
name: pptx
|
|
115
|
+
description: Create and edit PowerPoint presentations
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## PPT Creation Workflow
|
|
119
|
+
|
|
120
|
+
When creating presentations, follow these steps:
|
|
121
|
+
|
|
122
|
+
1. Analyze content structure, plan slide outline
|
|
123
|
+
2. Choose appropriate color scheme and fonts
|
|
124
|
+
3. Use python-pptx library to generate .pptx files
|
|
125
|
+
|
|
126
|
+
## Design Principles
|
|
127
|
+
|
|
128
|
+
- Each slide focuses on one topic
|
|
129
|
+
- Keep text concise, use bullet points instead of long paragraphs
|
|
130
|
+
- Maintain clear visual hierarchy with distinct titles, body, and notes
|
|
131
|
+
- Use consistent colors, avoid more than 3 main colors
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Python project standards:**
|
|
135
|
+
|
|
136
|
+
```yaml
|
|
137
|
+
---
|
|
138
|
+
name: python-project
|
|
139
|
+
description: Python project development standards, including code style, testing, and dependency management
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Python Development Standards
|
|
143
|
+
|
|
144
|
+
- Use Python 3.14+
|
|
145
|
+
- Use ruff for code formatting and linting
|
|
146
|
+
- Use pyright for type checking
|
|
147
|
+
- Use pytest for testing
|
|
148
|
+
- Use uv for dependency management
|
|
149
|
+
|
|
150
|
+
Code style:
|
|
151
|
+
- Line length limit 100 characters
|
|
152
|
+
- Use type annotations
|
|
153
|
+
- Public functions need docstrings
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Git commit conventions:**
|
|
157
|
+
|
|
158
|
+
```yaml
|
|
159
|
+
---
|
|
160
|
+
name: git-commits
|
|
161
|
+
description: Git commit message conventions using Conventional Commits format
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Git Commit Conventions
|
|
165
|
+
|
|
166
|
+
Use Conventional Commits format:
|
|
167
|
+
|
|
168
|
+
type(scope): description
|
|
169
|
+
|
|
170
|
+
Allowed types: feat, fix, docs, style, refactor, test, chore
|
|
171
|
+
|
|
172
|
+
Examples:
|
|
173
|
+
- feat(auth): add OAuth login support
|
|
174
|
+
- fix(api): fix user query returning null
|
|
175
|
+
- docs(readme): update installation instructions
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Using slash commands to load a skill
|
|
179
|
+
|
|
180
|
+
The `/skill:<name>` slash command lets you save commonly used prompt templates as skills and quickly invoke them when needed. When you enter the command, axe reads the corresponding SKILL.md file content and sends it to the Agent as a prompt.
|
|
181
|
+
|
|
182
|
+
For example:
|
|
183
|
+
|
|
184
|
+
- `/skill:code-style` - Load code style guidelines
|
|
185
|
+
- `/skill:pptx` - Load PPT creation workflow
|
|
186
|
+
- `/skill:git-commits fix user login issue` - Load Git commit conventions with an additional task description
|
|
187
|
+
|
|
188
|
+
You can append additional text after the slash command, which will be added to the skill prompt as the user's specific request.
|
|
189
|
+
|
|
190
|
+
**TIP:** For regular conversations, the Agent will automatically decide whether to read skill content based on context, so you don't need to invoke it manually.
|
|
191
|
+
|
|
192
|
+
Skills allow you to codify your team's best practices and project standards, ensuring the AI always follows consistent standards.
|
|
193
|
+
|
|
194
|
+
## Flow skills
|
|
195
|
+
|
|
196
|
+
Flow skills are a special skill type that embed an Agent Flow diagram in SKILL.md, used to define multi-step automated workflows. Unlike standard skills, flow skills are invoked via `/flow:<name>` commands and automatically execute multiple conversation turns following the flow diagram.
|
|
197
|
+
|
|
198
|
+
**Creating a flow skill:**
|
|
199
|
+
|
|
200
|
+
To create a flow skill, set `type: flow` in the frontmatter and include a Mermaid or D2 code block in the content:
|
|
201
|
+
|
|
202
|
+
```yaml
|
|
203
|
+
---
|
|
204
|
+
name: code-review
|
|
205
|
+
description: Code review workflow
|
|
206
|
+
type: flow
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
```mermaid
|
|
210
|
+
flowchart TD
|
|
211
|
+
A([BEGIN]) --> B[Analyze code changes, list all modified files and features]
|
|
212
|
+
B --> C{Is code quality acceptable?}
|
|
213
|
+
C -->|Yes| D[Generate code review report]
|
|
214
|
+
C -->|No| E[List issues and propose improvements]
|
|
215
|
+
E --> B
|
|
216
|
+
D --> F([END])
|
|
217
|
+
```
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Flow diagram format:**
|
|
221
|
+
|
|
222
|
+
Both Mermaid and D2 formats are supported:
|
|
223
|
+
|
|
224
|
+
- **Mermaid**: Use ` ```mermaid ` code block, [Mermaid Playground](https://mermaid.live) can be used for editing and preview
|
|
225
|
+
- **D2**: Use ` ```d2 ` code block, [D2 Playground](https://play.d2lang.com) can be used for editing and preview
|
|
226
|
+
|
|
227
|
+
Flow diagrams must contain one BEGIN node and one END node. Regular node text is sent to the Agent as a prompt; decision nodes require the Agent to output `<choice>branch name</choice>` in the output to select the next step.
|
|
228
|
+
|
|
229
|
+
**Executing a flow skill:**
|
|
230
|
+
|
|
231
|
+
Flow skills can be invoked in two ways:
|
|
232
|
+
|
|
233
|
+
- `/flow:<name>` - Execute the flow. The Agent will start from the BEGIN node and process each node according to the flow diagram definition until reaching the END node
|
|
234
|
+
- `/skill:<name>` - Like a standard skill, sends the SKILL.md content to the Agent as a prompt (does not automatically execute the flow)
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Execute the flow
|
|
238
|
+
/flow:code-review
|
|
239
|
+
|
|
240
|
+
# Load as a standard skill
|
|
241
|
+
/skill:code-review
|
|
242
|
+
```
|
axe_cli/soul/agent.py
CHANGED
|
@@ -64,6 +64,7 @@ class Runtime:
|
|
|
64
64
|
|
|
65
65
|
config: Config
|
|
66
66
|
llm: LLM | None # we do not freeze the `Runtime` dataclass because LLM can be changed
|
|
67
|
+
model_config_name: str | None # name of the model config from config.toml
|
|
67
68
|
session: Session
|
|
68
69
|
builtin_args: BuiltinSystemPromptArgs
|
|
69
70
|
denwa_renji: DenwaRenji
|
|
@@ -71,11 +72,12 @@ class Runtime:
|
|
|
71
72
|
labor_market: LaborMarket
|
|
72
73
|
environment: Environment
|
|
73
74
|
skills: dict[str, Skill]
|
|
75
|
+
oauth: OAuthManager
|
|
74
76
|
|
|
75
|
-
@staticmethod
|
|
76
77
|
async def create(
|
|
77
78
|
config: Config,
|
|
78
79
|
llm: LLM | None,
|
|
80
|
+
model_config_name: str | None,
|
|
79
81
|
session: Session,
|
|
80
82
|
yolo: bool,
|
|
81
83
|
skills_dir: KaosPath | None = None,
|
|
@@ -100,9 +102,12 @@ class Runtime:
|
|
|
100
102
|
for skill in skills
|
|
101
103
|
)
|
|
102
104
|
|
|
105
|
+
from axe_cli.auth.oauth import OAuthManager
|
|
106
|
+
|
|
103
107
|
return Runtime(
|
|
104
108
|
config=config,
|
|
105
109
|
llm=llm,
|
|
110
|
+
model_config_name=model_config_name,
|
|
106
111
|
session=session,
|
|
107
112
|
builtin_args=BuiltinSystemPromptArgs(
|
|
108
113
|
AXE_NOW=datetime.now().astimezone().isoformat(),
|
|
@@ -116,6 +121,7 @@ class Runtime:
|
|
|
116
121
|
labor_market=LaborMarket(),
|
|
117
122
|
environment=environment,
|
|
118
123
|
skills=skills_by_name,
|
|
124
|
+
oauth=OAuthManager(config),
|
|
119
125
|
)
|
|
120
126
|
|
|
121
127
|
def copy_for_fixed_subagent(self) -> Runtime:
|
|
@@ -123,6 +129,7 @@ class Runtime:
|
|
|
123
129
|
return Runtime(
|
|
124
130
|
config=self.config,
|
|
125
131
|
llm=self.llm,
|
|
132
|
+
model_config_name=self.model_config_name,
|
|
126
133
|
session=self.session,
|
|
127
134
|
builtin_args=self.builtin_args,
|
|
128
135
|
denwa_renji=DenwaRenji(), # subagent must have its own DenwaRenji
|
|
@@ -130,6 +137,7 @@ class Runtime:
|
|
|
130
137
|
labor_market=LaborMarket(), # fixed subagent has its own LaborMarket
|
|
131
138
|
environment=self.environment,
|
|
132
139
|
skills=self.skills,
|
|
140
|
+
oauth=self.oauth,
|
|
133
141
|
)
|
|
134
142
|
|
|
135
143
|
def copy_for_dynamic_subagent(self) -> Runtime:
|
|
@@ -137,6 +145,7 @@ class Runtime:
|
|
|
137
145
|
return Runtime(
|
|
138
146
|
config=self.config,
|
|
139
147
|
llm=self.llm,
|
|
148
|
+
model_config_name=self.model_config_name,
|
|
140
149
|
session=self.session,
|
|
141
150
|
builtin_args=self.builtin_args,
|
|
142
151
|
denwa_renji=DenwaRenji(), # subagent must have its own DenwaRenji
|
|
@@ -144,6 +153,7 @@ class Runtime:
|
|
|
144
153
|
labor_market=self.labor_market, # dynamic subagent shares LaborMarket with main agent
|
|
145
154
|
environment=self.environment,
|
|
146
155
|
skills=self.skills,
|
|
156
|
+
oauth=self.oauth,
|
|
147
157
|
)
|
|
148
158
|
|
|
149
159
|
|
axe_cli/soul/axesoul.py
CHANGED
|
@@ -133,6 +133,16 @@ class AxeSoul:
|
|
|
133
133
|
def model_name(self) -> str:
|
|
134
134
|
return self._runtime.llm.chat_provider.model_name if self._runtime.llm else ""
|
|
135
135
|
|
|
136
|
+
@property
|
|
137
|
+
def model_display_name(self) -> str:
|
|
138
|
+
"""Get the display name for the model (uses alias if available)."""
|
|
139
|
+
if self._runtime.llm is None:
|
|
140
|
+
return ""
|
|
141
|
+
if self._runtime.model_config_name and self._runtime.model_config_name in self._runtime.config.models:
|
|
142
|
+
model_cfg = self._runtime.config.models[self._runtime.model_config_name]
|
|
143
|
+
return model_cfg.alias or model_cfg.model
|
|
144
|
+
return self._runtime.llm.chat_provider.model_name
|
|
145
|
+
|
|
136
146
|
@property
|
|
137
147
|
def model_capabilities(self) -> set[ModelCapability] | None:
|
|
138
148
|
if self._runtime.llm is None:
|
axe_cli/tools/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# Built-in Tools
|
|
2
|
+
|
|
3
|
+
The following are all built-in tools in axe.
|
|
4
|
+
|
|
5
|
+
## Task
|
|
6
|
+
**Path:** `axe_cli.tools.multiagent:Task`
|
|
7
|
+
**Description:** Dispatch a subagent to execute a task. Subagents cannot access the main agent's context; all necessary information must be provided in the prompt.
|
|
8
|
+
|
|
9
|
+
| Parameter | Type | Description |
|
|
10
|
+
|-----------|------|-------------|
|
|
11
|
+
| description | string | Short task description (3-5 words) |
|
|
12
|
+
| subagent_name | string | Subagent name |
|
|
13
|
+
| prompt | string | Detailed task description |
|
|
14
|
+
|
|
15
|
+
## SetTodoList
|
|
16
|
+
**Path:** `axe_cli.tools.todo:SetTodoList`
|
|
17
|
+
**Description:** Manage todo list, track task progress
|
|
18
|
+
|
|
19
|
+
| Parameter | Type | Description |
|
|
20
|
+
|-----------|------|-------------|
|
|
21
|
+
| todos | array | Todo list items |
|
|
22
|
+
| todos[].title | string | Todo item title |
|
|
23
|
+
| todos[].status | string | Status: pending, in_progress, done |
|
|
24
|
+
|
|
25
|
+
## Shell
|
|
26
|
+
**Path:** `axe_cli.tools.shell:Shell`
|
|
27
|
+
**Description:** Execute shell commands. Requires user approval. Uses the appropriate shell for the OS (bash/zsh on Unix, PowerShell on Windows).
|
|
28
|
+
|
|
29
|
+
| Parameter | Type | Description |
|
|
30
|
+
|-----------|------|-------------|
|
|
31
|
+
| command | string | Command to execute |
|
|
32
|
+
| timeout | int | Timeout in seconds, default 60, max 300 |
|
|
33
|
+
|
|
34
|
+
## ReadFile
|
|
35
|
+
**Path:** `axe_cli.tools.file:ReadFile`
|
|
36
|
+
**Description:** Read text file content. Max 1000 lines per read, max 2000 characters per line. Files outside working directory require absolute paths.
|
|
37
|
+
|
|
38
|
+
| Parameter | Type | Description |
|
|
39
|
+
|-----------|------|-------------|
|
|
40
|
+
| path | string | File path |
|
|
41
|
+
| line_offset | int | Starting line number, default 1 |
|
|
42
|
+
| n_lines | int | Number of lines to read, default/max 1000 |
|
|
43
|
+
|
|
44
|
+
## ReadMediaFile
|
|
45
|
+
**Path:** `axe_cli.tools.file:ReadMediaFile`
|
|
46
|
+
**Description:** Read image or video files. Max file size 100MB. Only available when the model supports image/video input. Files outside working directory require absolute paths.
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Description |
|
|
49
|
+
|-----------|------|-------------|
|
|
50
|
+
| path | string | File path |
|
|
51
|
+
|
|
52
|
+
## Glob
|
|
53
|
+
**Path:** `axe_cli.tools.file:Glob`
|
|
54
|
+
**Description:** Match files and directories by pattern. Returns max 1000 matches, patterns starting with ** not allowed.
|
|
55
|
+
|
|
56
|
+
| Parameter | Type | Description |
|
|
57
|
+
|-----------|------|-------------|
|
|
58
|
+
| pattern | string | Glob pattern (e.g., *.py, src/**/*.ts) |
|
|
59
|
+
| directory | string | Search directory, defaults to working directory |
|
|
60
|
+
| include_dirs | bool | Include directories, default true |
|
|
61
|
+
|
|
62
|
+
## Grep
|
|
63
|
+
**Path:** `axe_cli.tools.file:Grep`
|
|
64
|
+
**Description:** Search file content with regular expressions, based on ripgrep
|
|
65
|
+
|
|
66
|
+
| Parameter | Type | Description |
|
|
67
|
+
|-----------|------|-------------|
|
|
68
|
+
| pattern | string | Regular expression pattern |
|
|
69
|
+
| path | string | Search path, defaults to current directory |
|
|
70
|
+
| glob | string | File filter (e.g., *.js) |
|
|
71
|
+
| type | string | File type (e.g., py, js, go) |
|
|
72
|
+
| output_mode | string | Output mode: files_with_matches (default), content, count_matches |
|
|
73
|
+
| -B | int | Show N lines before match |
|
|
74
|
+
| -A | int | Show N lines after match |
|
|
75
|
+
| -C | int | Show N lines before and after match |
|
|
76
|
+
| -n | bool | Show line numbers |
|
|
77
|
+
| -i | bool | Case insensitive |
|
|
78
|
+
| multiline | bool | Enable multiline matching |
|
|
79
|
+
| head_limit | int | Limit output lines |
|
|
80
|
+
|
|
81
|
+
## WriteFile
|
|
82
|
+
**Path:** `axe_cli.tools.file:WriteFile`
|
|
83
|
+
**Description:** Write files. Requires user approval. Absolute paths are required when writing files outside the working directory.
|
|
84
|
+
|
|
85
|
+
| Parameter | Type | Description |
|
|
86
|
+
|-----------|------|-------------|
|
|
87
|
+
| path | string | Absolute path |
|
|
88
|
+
| content | string | File content |
|
|
89
|
+
| mode | string | overwrite (default) or append |
|
|
90
|
+
|
|
91
|
+
## StrReplaceFile
|
|
92
|
+
**Path:** `axe_cli.tools.file:StrReplaceFile`
|
|
93
|
+
**Description:** Edit files using string replacement. Requires user approval. Absolute paths are required when editing files outside the working directory.
|
|
94
|
+
|
|
95
|
+
| Parameter | Type | Description |
|
|
96
|
+
|-----------|------|-------------|
|
|
97
|
+
| path | string | Absolute path |
|
|
98
|
+
| edit | object/array | Single edit or list of edits |
|
|
99
|
+
| edit.old | string | Original string to replace |
|
|
100
|
+
| edit.new | string | Replacement string |
|
|
101
|
+
| edit.replace_all | bool | Replace all matches, default false |
|
|
102
|
+
|
|
103
|
+
## CodeSearch
|
|
104
|
+
**Path:** `axe_cli.tools.axe:CodeSearch`
|
|
105
|
+
**Description:** Semantic code search powered by axe-dig. Finds code by behavior, not just text matches.
|
|
106
|
+
|
|
107
|
+
## CodeContext
|
|
108
|
+
**Path:** `axe_cli.tools.axe:CodeContext`
|
|
109
|
+
**Description:** Get LLM-ready function summaries with 95% token savings.
|
|
110
|
+
|
|
111
|
+
## CodeStructure
|
|
112
|
+
**Path:** `axe_cli.tools.axe:CodeStructure`
|
|
113
|
+
**Description:** Navigate functions and classes in files or directories.
|
|
114
|
+
|
|
115
|
+
## CodeImpact
|
|
116
|
+
**Path:** `axe_cli.tools.axe:CodeImpact`
|
|
117
|
+
**Description:** Reverse call graph analysis - see who calls a function before refactoring.
|
|
118
|
+
|
|
119
|
+
## Tool security boundaries
|
|
120
|
+
|
|
121
|
+
**Working directory restrictions:**
|
|
122
|
+
|
|
123
|
+
- File reading and writing are typically done within the working directory
|
|
124
|
+
- Absolute paths are required when reading files outside the working directory
|
|
125
|
+
- Write and edit operations require user approval; absolute paths are required when operating on files outside the working directory
|
|
126
|
+
|
|
127
|
+
**Approval mechanism:**
|
|
128
|
+
|
|
129
|
+
The following operations require user approval:
|
|
130
|
+
|
|
131
|
+
| Operation | Approval required |
|
|
132
|
+
|-----------|-------------------|
|
|
133
|
+
| Shell command execution | Each execution |
|
|
134
|
+
| File write/edit | Each operation |
|
|
135
|
+
| MCP tool calls | Each call |
|
axe_cli/tools/axe/auto_init.py
CHANGED
|
@@ -142,14 +142,14 @@ def prompt_user_for_init(work_dir: Path) -> tuple[bool, str]:
|
|
|
142
142
|
"""
|
|
143
143
|
console.print()
|
|
144
144
|
console.print(Panel.fit(
|
|
145
|
-
"[bold
|
|
145
|
+
"[bold]okay so, lets pre-warm your codebase![/bold]\n\n"
|
|
146
146
|
"this builds the analysis stack once.\n"
|
|
147
147
|
"after completion, queries are instant and the daemon handles everything.\n\n"
|
|
148
148
|
"[dim]parsing structure. building call graphs. computing dependencies. encoding semantics.[/dim]\n\n"
|
|
149
|
-
"axe-dig gives llms [bold]lethal precision.[/bold]\n"
|
|
149
|
+
"axe-dig gives llms [bold red]lethal precision.[/bold red]\n"
|
|
150
150
|
"natural language queries. [bold]exact context.[/bold] 95% fewer tokens.\n\n"
|
|
151
151
|
"takes two minutes for typical projects.",
|
|
152
|
-
border_style="
|
|
152
|
+
border_style="white"
|
|
153
153
|
))
|
|
154
154
|
console.print()
|
|
155
155
|
console.print(f"[dim]this is the directory we gonna work with: {work_dir}[/dim]")
|
|
@@ -165,14 +165,14 @@ def prompt_user_for_init(work_dir: Path) -> tuple[bool, str]:
|
|
|
165
165
|
|
|
166
166
|
console.print()
|
|
167
167
|
console.print("[bold]choose digging depth:[/bold]\n")
|
|
168
|
-
console.print("
|
|
168
|
+
console.print(" 1) [bold]light-digging[/bold] (recommended)")
|
|
169
169
|
console.print(" • 90mb download")
|
|
170
170
|
console.print(" • 2gb ram during indexing")
|
|
171
171
|
console.print(" • fast. ~1 min for medium projects")
|
|
172
172
|
console.print(" • good precision for most codebases")
|
|
173
173
|
console.print(" • finds: 'jwt validation' → verify_token()")
|
|
174
174
|
console.print()
|
|
175
|
-
console.print("
|
|
175
|
+
console.print(" 2) [bold]heavy-digging[/bold] (maximum precision)")
|
|
176
176
|
console.print(" • 1.3gb download")
|
|
177
177
|
console.print(" • 10gb+ ram during indexing")
|
|
178
178
|
console.print(" • slower. 5-15 min for medium projects")
|
|
@@ -189,7 +189,7 @@ def prompt_user_for_init(work_dir: Path) -> tuple[bool, str]:
|
|
|
189
189
|
model = "minilm" if choice == "1" else "bge-large"
|
|
190
190
|
model_display = "light-digging (sentence-transformers/all-MiniLM-L6-v2)" if model == "minilm" else "heavy-digging (BAAI/bge-large-en-v1.5)"
|
|
191
191
|
|
|
192
|
-
console.print(f"\n[dim]selected: {model_display}[/
|
|
192
|
+
console.print(f"\n[dim]selected:[/dim] [red]{model_display}[/red]")
|
|
193
193
|
return True, model
|
|
194
194
|
|
|
195
195
|
|
|
@@ -236,9 +236,9 @@ async def auto_initialize_codebase(work_dir: Path, model: str | None = None, int
|
|
|
236
236
|
|
|
237
237
|
console.print()
|
|
238
238
|
console.print(Panel.fit(
|
|
239
|
-
"[bold
|
|
239
|
+
"[bold]okay lets do this!, grab a coffee—- axe is now understanding your codebase![/bold]\n"
|
|
240
240
|
f"[dim]Model: {model_name}[/dim]",
|
|
241
|
-
border_style="
|
|
241
|
+
border_style="white"
|
|
242
242
|
))
|
|
243
243
|
console.print()
|
|
244
244
|
|
|
@@ -246,67 +246,67 @@ async def auto_initialize_codebase(work_dir: Path, model: str | None = None, int
|
|
|
246
246
|
create_dig_config(work_dir, model)
|
|
247
247
|
|
|
248
248
|
with Progress(
|
|
249
|
-
SpinnerColumn(),
|
|
249
|
+
SpinnerColumn(style="bold red"),
|
|
250
250
|
TextColumn("[progress.description]{task.description}"),
|
|
251
|
-
BarColumn(),
|
|
251
|
+
BarColumn(bar_width=None, style="dim white", complete_style="white", finished_style="white"),
|
|
252
252
|
TaskProgressColumn(),
|
|
253
253
|
console=console,
|
|
254
254
|
transient=False
|
|
255
255
|
) as progress:
|
|
256
256
|
|
|
257
257
|
# Step 1: Structural indexing
|
|
258
|
-
task1 = progress.add_task("
|
|
258
|
+
task1 = progress.add_task("building and understanding the structure..", total=100)
|
|
259
259
|
progress.update(task1, advance=10)
|
|
260
260
|
|
|
261
261
|
success, output = await run_chop_command(f"chop warm {work_dir}", work_dir)
|
|
262
262
|
|
|
263
263
|
if success:
|
|
264
|
-
progress.update(task1, advance=90, description="[
|
|
264
|
+
progress.update(task1, advance=90, description="[bold]✓ structure indexed[/bold]")
|
|
265
265
|
for line in output.split("\n"):
|
|
266
266
|
if "Indexed" in line and "files" in line:
|
|
267
267
|
console.print(f" [dim]{line}[/dim]")
|
|
268
268
|
else:
|
|
269
|
-
progress.update(task1, description="[red]✗structural indexing failed")
|
|
269
|
+
progress.update(task1, description="[red]✗structural indexing failed[/red]")
|
|
270
270
|
console.print(f" [red]{output[:200]}[/red]")
|
|
271
271
|
return
|
|
272
272
|
|
|
273
273
|
# Step 2: Semantic indexing
|
|
274
|
-
task2 = progress.add_task("
|
|
274
|
+
task2 = progress.add_task("building semantics...", total=100)
|
|
275
275
|
progress.update(task2, advance=10)
|
|
276
276
|
|
|
277
277
|
cmd = f"chop semantic index {work_dir} --model {model_name}"
|
|
278
278
|
success, output = await run_chop_command(cmd, work_dir, timeout=1800)
|
|
279
279
|
|
|
280
280
|
if success:
|
|
281
|
-
progress.update(task2, advance=90, description="[
|
|
281
|
+
progress.update(task2, advance=90, description="[bold]✓ ok, semantic index built[/bold]")
|
|
282
282
|
for line in output.split("\n"):
|
|
283
283
|
if "Indexed" in line and "code units" in line:
|
|
284
284
|
console.print(f" [dim]{line}[/dim]")
|
|
285
285
|
else:
|
|
286
|
-
progress.update(task2, description="[
|
|
287
|
-
console.print(f" [
|
|
286
|
+
progress.update(task2, description="[red]⚠ semantic indexing failed due to some reason, maybe try again?[/red]")
|
|
287
|
+
console.print(f" [red]{output[:200]}[/red]")
|
|
288
288
|
|
|
289
289
|
# Step 3: Start daemon
|
|
290
|
-
task3 = progress.add_task("
|
|
290
|
+
task3 = progress.add_task("starting daemon...", total=100)
|
|
291
291
|
progress.update(task3, advance=10)
|
|
292
292
|
|
|
293
293
|
success, output = await run_chop_command(f"chop daemon start --project {work_dir}", work_dir, timeout=30)
|
|
294
294
|
|
|
295
295
|
if success or "already running" in output.lower():
|
|
296
|
-
progress.update(task3, advance=90, description="[
|
|
296
|
+
progress.update(task3, advance=90, description="[bold]daemon active[/bold]")
|
|
297
297
|
else:
|
|
298
|
-
progress.update(task3, description="[
|
|
298
|
+
progress.update(task3, description="[red]⚠ umm, daemon skipped[/red]")
|
|
299
299
|
console.print(f" [dim]you can run 'chop daemon start --project {work_dir}' manually if needed[/dim]")
|
|
300
300
|
|
|
301
301
|
console.print()
|
|
302
302
|
console.print(Panel.fit(
|
|
303
|
-
"[bold
|
|
303
|
+
"[bold]axe ready[/bold]\n\n"
|
|
304
304
|
"[dim]tools available:[/dim]\n"
|
|
305
|
-
" •
|
|
306
|
-
" •
|
|
307
|
-
" •
|
|
308
|
-
" •
|
|
309
|
-
border_style="
|
|
305
|
+
" • codesearch - semantic search by behavior\n"
|
|
306
|
+
" • codecontext - precise function context\n"
|
|
307
|
+
" • codeimpact - reverse call graph\n"
|
|
308
|
+
" • codestructure - function and class maps",
|
|
309
|
+
border_style="white"
|
|
310
310
|
))
|
|
311
311
|
console.print()
|
|
312
312
|
|
|
@@ -331,4 +331,4 @@ async def ensure_codebase_initialized(work_dir: Path) -> None:
|
|
|
331
331
|
try:
|
|
332
332
|
await auto_initialize_codebase(work_dir, model=None, interactive=interactive)
|
|
333
333
|
except Exception as e:
|
|
334
|
-
console.print(f"[
|
|
334
|
+
console.print(f"[red]⚠ Axe-dig auto-init skipped: {e}[/red]")
|
axe_cli/tools/axe/context.py
CHANGED
|
@@ -56,11 +56,10 @@ Returns a compressed LLM-ready summary that includes:
|
|
|
56
56
|
→ calls: check_permissions, get_user_data, log_access
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
**Why use this
|
|
59
|
+
**Why use this?**
|
|
60
60
|
- 95% fewer tokens while preserving understanding
|
|
61
61
|
- Includes cross-file context (callers from other files, dependencies)
|
|
62
62
|
- Shows complexity metrics to assess refactoring difficulty
|
|
63
|
-
- Optimized for LLM comprehension
|
|
64
63
|
|
|
65
64
|
**When to use:**
|
|
66
65
|
- Understanding a function before editing it
|
axe_cli/tools/axe/impact.py
CHANGED
|
@@ -55,7 +55,15 @@ Shows all places that call or depend on a function/class, helping you understand
|
|
|
55
55
|
- Finding all consumers of an API or function
|
|
56
56
|
- Assessing change impact and blast radius
|
|
57
57
|
|
|
58
|
-
**
|
|
58
|
+
**examples:**
|
|
59
|
+
```bash
|
|
60
|
+
chop impact TokenCounter src/axe_cli/
|
|
61
|
+
# Result: Only called by get_global_counter() in same file
|
|
62
|
+
# Meaning: Safe to refactor - no external dependencies to break
|
|
63
|
+
# Output shows caller_count: 1, with full call chain
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Output:** JSON with all callers, their locations, and the full call tree.
|
|
59
67
|
|
|
60
68
|
**Note:** The codebase is automatically indexed on startup.
|
|
61
69
|
|
axe_cli/tools/axe/prewarm.py
CHANGED
|
@@ -28,7 +28,7 @@ class CodePrewarm(CallableTool2[CodePrewarmParams]):
|
|
|
28
28
|
"""
|
|
29
29
|
PRE-WARM the codebase using axe-dig.
|
|
30
30
|
|
|
31
|
-
Runs: `chop warm
|
|
31
|
+
Runs: `chop warm .` + `chop semantic index .`
|
|
32
32
|
|
|
33
33
|
This runs full structural analysis and builds semantic embeddings.
|
|
34
34
|
Run this on any new/existing project first before using other code analysis tools.
|
axe_cli/tools/axe/search.py
CHANGED
|
@@ -43,11 +43,17 @@ Runs: `chop semantic search "<query>" --path <path>`
|
|
|
43
43
|
Search by what code DOES, not just what it says. Uses vector embeddings
|
|
44
44
|
to find functions by their purpose, even without exact text matches.
|
|
45
45
|
|
|
46
|
-
**
|
|
47
|
-
- "
|
|
48
|
-
- "
|
|
49
|
-
- "
|
|
50
|
-
- "
|
|
46
|
+
** examples :**
|
|
47
|
+
- "retry failed operations with exponential backoff" → _is_retryable_error() (score: 0.71)
|
|
48
|
+
- "load configuration from toml file" → load_config_from_string() (score: 0.76)
|
|
49
|
+
- "execute shell commands and capture output" → run_sh() (score: 0.73)
|
|
50
|
+
- "write content to file and handle errors" → flush_content() (score: 0.69)
|
|
51
|
+
|
|
52
|
+
**How to write good queries:**
|
|
53
|
+
- Describe WHAT the code does, not HOW: "cache data with expiration" not "redis.setex"
|
|
54
|
+
- Be specific but natural: "retry with backoff" finds retry logic better than just "retry"
|
|
55
|
+
- Use behavioral terms: "validate input", "handle errors", "parse config"
|
|
56
|
+
- Scores 0.65+ are excellent, 0.55-0.65 are good, below 0.55 try different terms
|
|
51
57
|
|
|
52
58
|
**Result format:** Returns function names with relevance scores (0-1).
|
|
53
59
|
|