Skip to content

Commit 5950543

Browse files
committed
feat: update examples and documentation to use ls, jq, and curl, and fix root-only tool execution target logic
1 parent 81bfaf6 commit 5950543

7 files changed

Lines changed: 103 additions & 45 deletions

File tree

‎README.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Outside-In CLI-to-Agent Bridge — automatically wraps existing CLI tools into g
1111

1212
## What is apexe?
1313

14-
`apexe` scans any CLI tool on your system (e.g., `git`, `curl`, `grep`, `find`, `lsof`), deterministically extracts its command structure, flags, and arguments — then exposes them as governed MCP tools that AI agents can invoke safely.
14+
`apexe` scans any CLI tool on your system (e.g., `git`, `curl`, `ls`, `jq`), deterministically extracts its command structure, flags, and arguments — then exposes them as governed MCP tools that AI agents can invoke safely.
1515

1616
**No LLM required for scanning. No changes to the CLI tools. Zero-config governance.**
1717

@@ -87,7 +87,7 @@ apexe serve --show-config cursor
8787
Scan CLI tools and generate binding files + ACL rules.
8888

8989
```bash
90-
apexe scan git curl grep lsof # Scan multiple tools
90+
apexe scan ls jq curl # Scan multiple tools
9191
apexe scan git --depth 3 # 3 levels of subcommands (default: 2, max: 5)
9292
apexe scan git --no-cache # Force re-scan
9393
apexe scan git --format json # Output as JSON (also: yaml, table)

‎docs/quickstart.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Open `http://127.0.0.1:8000` in a browser to explore available tools.
5252
## Scan more tools
5353

5454
```bash
55-
apexe scan curl grep find lsof
55+
apexe scan ls curl jq
5656
```
5757

5858
## See what you have

‎docs/user-manual.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ apexe scan <TOOLS>... [OPTIONS]
9191

9292
```bash
9393
apexe scan git # basic scan
94-
apexe scan git curl grep lsof # multiple tools
94+
apexe scan ls jq curl # multiple tools
9595
apexe scan git --depth 3 # deeper subcommand discovery
9696
apexe scan git --no-cache # force re-scan
9797
apexe scan git --format json # JSON output

‎examples/README.md‎

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ server.serve()?; // blocking — starts the server
204204
### Scan multiple tools at once
205205

206206
```bash
207-
apexe scan git curl grep find lsof --depth 3
207+
apexe scan ls jq curl --no-cache
208208
apexe list
209209
# Shows all modules from all tools
210210
```
@@ -214,16 +214,56 @@ apexe list
214214
```bash
215215
apexe serve --transport http --port 8000 --explorer
216216
# Open http://127.0.0.1:8000/explorer in your browser
217-
# Browse tools, view schemas, test invocations
218217
```
219218

220-
### Try it: Call tools via MCP (curl examples)
219+
### Try it: Explorer UI step-by-step
220+
221+
1. **Scan ls, jq, and curl**:
222+
223+
```bash
224+
apexe scan ls jq curl --no-cache
225+
apexe serve --transport http --port 8000 --explorer
226+
```
227+
228+
2. **Open** http://127.0.0.1:8000/explorer in your browser
229+
230+
3. **Click `cli.ls`** → type `{}` → click **Call**. Instant file listing:
231+
232+
```json
233+
{}
234+
```
235+
236+
**Response:**
237+
```json
238+
{
239+
"content": [
240+
{
241+
"type": "text",
242+
"text": "{\"stdout\":\"Cargo.toml\\nREADME.md\\nsrc\\n...\",\"stderr\":\"\",\"exit_code\":0}"
243+
}
244+
]
245+
}
246+
```
247+
248+
4. **Click `cli.jq`** → 22 form fields! Try:
249+
250+
```json
251+
{"compact_output": true, "raw_output": true}
252+
```
253+
254+
5. **Click `cli.curl`** → 12 form fields. Try:
255+
256+
```json
257+
{"verbose": true, "silent": true}
258+
```
259+
260+
### Try it: Call tools via MCP API (full control)
221261

222262
Start the server in one terminal, then call tools from another:
223263

224264
```bash
225265
# Terminal 1: start server
226-
apexe scan ls curl grep find
266+
apexe scan ls jq curl --no-cache
227267
apexe serve --transport http --port 8000 --explorer
228268
```
229269

‎examples/basic/README.md‎

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
# Basic Example: Scan Git, Serve via MCP
1+
# Basic Example: Scan Tools, Explore via Browser
22

3-
This example scans `git`, generates binding files, and starts an MCP server that Claude Desktop or Cursor can use.
3+
Scans `ls` (instant result), `jq` (22 flags), and `curl` (12 flags), then starts an HTTP server with Explorer UI for browser-based testing.
44

55
## Prerequisites
66

77
- `apexe` installed (`cargo install --path ../..`)
8-
- `git` on your `$PATH`
8+
- `ls`, `jq`, and `curl` on your `$PATH`
99

1010
## Run
1111

@@ -15,26 +15,34 @@ This example scans `git`, generates binding files, and starts an MCP server that
1515

1616
## What it does
1717

18-
1. Scans `git` with depth 2 (discovers `git commit`, `git push`, `git status`, etc.)
18+
1. Scans `ls`, `jq`, and `curl` (extracts flags and generates JSON Schema)
1919
2. Writes binding files to `./output/modules/`
20-
3. Writes ACL rules to `./output/acl.yaml`
21-
4. Shows the scan results and generated modules
22-
5. Prints Claude Desktop and Cursor integration configs
23-
6. Starts the MCP server on stdio (Ctrl+C to stop)
20+
3. Prints Claude Desktop and Cursor integration configs
21+
4. Starts HTTP server with Explorer UI at http://127.0.0.1:8000/explorer
2422

25-
## Generated files
23+
## Using the Explorer UI
2624

25+
1. Open **http://127.0.0.1:8000/explorer** in your browser
26+
27+
2. Click **`cli.ls`** → type `{}` → click **Call**:
28+
```json
29+
{}
2730
```
28-
output/
29-
modules/
30-
*.binding.yaml # One file per scanned module
31-
acl.yaml # Access control rules (readonly=allow, destructive=deny)
31+
You'll see your current directory listing immediately. This is the quickest way to verify apexe works.
32+
33+
3. Click **`cli.curl`** → it has form fields for `data`, `verbose`, `silent`, etc. Try:
34+
```json
35+
{"verbose": true}
3236
```
3337

38+
4. The response includes `stdout`, `stderr`, `exit_code`, `trace_id`, and `duration_ms`
39+
3440
## Claude Desktop integration
3541

36-
Copy the output of step 5 into your Claude Desktop config:
37-
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
38-
- Linux: `~/.config/claude/claude_desktop_config.json`
42+
After testing with Explorer, switch to stdio for Claude Desktop:
43+
44+
```bash
45+
apexe serve --show-config claude-desktop
46+
```
3947

40-
Then restart Claude Desktop. Git commands will appear as MCP tools.
48+
Copy the JSON into `~/Library/Application Support/Claude/claude_desktop_config.json`, restart Claude Desktop.

‎examples/basic/run.sh‎

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,48 @@
11
#!/usr/bin/env bash
2-
# apexe basic example: scan git, inspect results, start MCP server.
2+
# apexe basic example: scan tools, inspect results, start MCP server.
33
set -euo pipefail
44

55
OUTPUT_DIR="./output"
66
MODULES_DIR="$OUTPUT_DIR/modules"
77

8-
echo "=== Step 1: Scan git ==="
9-
apexe scan git --output-dir "$MODULES_DIR" --depth 2 --format table
8+
echo "=== Step 1: Scan tools ==="
9+
echo " ls — simple tool, runs with {} immediately"
10+
echo " jq — 22 flags with full schema (best Explorer demo)"
11+
echo " curl — 12 flags (GNU format)"
12+
echo
13+
apexe scan ls jq curl --no-cache --output-dir "$MODULES_DIR" --format table
1014
echo
1115

1216
echo "=== Step 2: List generated modules ==="
1317
apexe list --modules-dir "$MODULES_DIR"
1418
echo
1519

16-
echo "=== Step 3: Inspect ACL ==="
17-
if [ -f "$HOME/.apexe/acl.yaml" ]; then
18-
echo "ACL rules at ~/.apexe/acl.yaml:"
19-
cat "$HOME/.apexe/acl.yaml"
20-
else
21-
echo "(ACL file not found — may have been written to default location)"
22-
fi
23-
echo
24-
25-
echo "=== Step 4: Inspect a binding file ==="
20+
echo "=== Step 3: Inspect binding file (check the schema properties) ==="
2621
FIRST_BINDING=$(ls "$MODULES_DIR"/*.binding.yaml 2>/dev/null | head -1)
2722
if [ -n "$FIRST_BINDING" ]; then
28-
echo "First binding file: $FIRST_BINDING"
29-
head -40 "$FIRST_BINDING"
23+
echo "Binding file: $FIRST_BINDING"
24+
head -50 "$FIRST_BINDING"
3025
echo "..."
3126
fi
3227
echo
3328

34-
echo "=== Step 5: Integration configs ==="
29+
echo "=== Step 4: Integration configs ==="
3530
echo "--- Claude Desktop ---"
3631
apexe serve --show-config claude-desktop --modules-dir "$MODULES_DIR"
3732
echo
3833
echo "--- Cursor ---"
3934
apexe serve --show-config cursor --modules-dir "$MODULES_DIR"
4035
echo
4136

42-
echo "=== Step 6: Start MCP server (stdio) ==="
37+
echo "=== Step 5: Start HTTP server with Explorer UI ==="
38+
echo "Open http://127.0.0.1:8000/explorer in your browser."
39+
echo "Click 'cli.curl' → fill in JSON input → click Call."
40+
echo ""
41+
echo "Try in Explorer:"
42+
echo ' cli.ls → input: {} → file listing (instant result!)'
43+
echo ' cli.jq → input: {"compact_output": true} → 22 flags with form fields'
44+
echo ' cli.curl → input: {"verbose": true} → 12 flags with form fields'
45+
echo ""
4346
echo "Press Ctrl+C to stop."
44-
echo "In production, this is launched by Claude Desktop / Cursor, not run manually."
4547
echo
46-
apexe serve --transport stdio --modules-dir "$MODULES_DIR"
48+
apexe serve --transport http --port 8000 --explorer --modules-dir "$MODULES_DIR"

‎src/adapter/converter.rs‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,13 @@ impl CliToolConverter {
7272
help_format_to_tag(command_opt.map_or(HelpFormat::Unknown, |c| c.help_format));
7373

7474
let tags = self.build_tags(tool, command_opt, help_format_name);
75-
let target = format!("exec://{} {}", tool.binary_path, full_command);
75+
// For root-only tools (no subcommands), target is just the binary path.
76+
// For subcommands, include the command path (e.g., "exec:///usr/bin/git commit").
77+
let target = if path.is_empty() {
78+
format!("exec://{}", tool.binary_path)
79+
} else {
80+
format!("exec://{} {}", tool.binary_path, full_command)
81+
};
7682
let version = tool
7783
.version
7884
.clone()
@@ -488,6 +494,8 @@ mod tests {
488494

489495
assert_eq!(modules.len(), 1);
490496
assert_eq!(modules[0].module_id, "cli.ffmpeg");
497+
// Root-only target should NOT repeat the tool name as an argument
498+
assert_eq!(modules[0].target, "exec:///usr/bin/ffmpeg");
491499
}
492500

493501
#[test]

0 commit comments

Comments
 (0)