Skip to content

Commit 4e1ebfd

Browse files
author
OpenClaw
committed
feat: Add repo-local skill support + structure tests
- Add .agents/skills/cli-anything/ for OpenClaw agents - Add tests/test_skill_layout.py for dual-entrypoint validation - Update README.md with repo-local skill documentation - Update .gitignore to include new directories Implements issue HKUDS#30
1 parent 02acd54 commit 4e1ebfd

4 files changed

Lines changed: 191 additions & 0 deletions

File tree

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# cli-anything Skill
2+
3+
Build powerful, stateful CLI interfaces for any GUI application using the cli-anything harness methodology.
4+
5+
## Overview
6+
7+
This skill enables AI agents to transform any software application into an agent-controllable CLI. It follows the proven cli-anything methodology that has successfully generated CLIs for GIMP, Blender, Inkscape, Audacity, LibreOffice, OBS Studio, and Kdenlive.
8+
9+
## Usage
10+
11+
```bash
12+
# Build CLI for local source
13+
cli-anything /path/to/software
14+
15+
# Build CLI from GitHub
16+
cli-anything https://github.com/org/repo
17+
```
18+
19+
## Prerequisites
20+
21+
- Python 3.10+
22+
- click >= 8.0
23+
- pytest
24+
25+
Install dependencies:
26+
```bash
27+
pip install click pytest pyyaml
28+
```
29+
30+
## Methodology
31+
32+
This skill follows the 7-phase cli-anything methodology:
33+
34+
### Phase 0: Source Acquisition
35+
- Clone GitHub repos or validate local paths
36+
- Verify source code structure
37+
38+
### Phase 1: Codebase Analysis
39+
- Analyze application architecture
40+
- Map GUI actions to API calls
41+
- Identify existing CLI tools
42+
43+
### Phase 2: CLI Architecture Design
44+
- Design command groups matching app domains
45+
- Plan state model and output formats
46+
- Create software-specific SOP documents
47+
48+
### Phase 3: Implementation
49+
- Create directory structure: `agent-harness/cli_anything/<software>/`
50+
- Implement core modules with Click
51+
- Add REPL support with JSON output mode
52+
53+
### Phase 4: Test Planning
54+
- Design unit and E2E test coverage
55+
- Plan validation scenarios
56+
57+
### Phase 5: Test Implementation
58+
- Write comprehensive tests
59+
- Ensure 100% pass rate
60+
61+
### Phase 6: Documentation & Publishing
62+
- Document commands and usage
63+
- Prepare for PyPI publishing
64+
65+
## Key Files
66+
67+
| File | Purpose |
68+
|------|---------|
69+
| `HARNESS.md` | Complete methodology specification |
70+
| `commands/cli-anything.md` | Main build command |
71+
| `commands/validate.md` | Validation command |
72+
| `commands/test.md` | Testing command |
73+
| `commands/refine.md` | Refinement command |
74+
75+
## Output
76+
77+
- Stateful CLI with REPL mode
78+
- JSON output for agent consumption
79+
- Undo/redo support
80+
- Full test coverage
81+
82+
## Related
83+
84+
- Plugin workflow: See `../cli-anything-plugin/` for Claude Code plugin
85+
- Examples: See `../blender/`, `../gimp/`, `../audacity/` for implemented CLIs

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
# Step 3: Allow cli-anything-plugin entirely
1919
!/cli-anything-plugin/
2020

21+
# Step 3.5: Allow .agents for repo-local skills
22+
!/.agents/
23+
24+
# Step 3.6: Allow tests directory
25+
!/tests/
26+
2127
# Step 4: Allow each software dir (top level only)
2228
!/gimp/
2329
!/blender/

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,19 @@ The playbook distills key insights from successfully building all 8 diverse, pro
514514
/cli-anything <software-name>
515515
```
516516

517+
### For Repo-Local Usage (OpenClaw Agents)
518+
519+
This project supports dual-entrypoint design:
520+
521+
1. **Plugin workflow** (see above): Use `cli-anything-plugin/` as a Claude Code plugin
522+
2. **Repo-local skill**: Use `.agents/skills/cli-anything/` for OpenClaw agents
523+
524+
```bash
525+
# The repo-local skill at .agents/skills/cli-anything/
526+
# reuses HARNESS.md and command specs from cli-anything-plugin/
527+
# No additional installation needed for OpenClaw agents
528+
```
529+
517530
### For Generated CLIs
518531

519532
```bash

tests/test_skill_layout.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
"""
2+
Test suite for CLI-Anything repo structure validation.
3+
4+
This test ensures the dual-entrypoint design (plugin + repo-local skill)
5+
is properly documented and aligned with README claims.
6+
"""
7+
8+
import os
9+
import re
10+
from pathlib import Path
11+
12+
REPO_ROOT = Path(__file__).parent.parent
13+
14+
15+
def test_readme_mentions_plugin_and_skill():
16+
"""README should mention both plugin and repo-local skill paths."""
17+
readme = REPO_ROOT / "README.md"
18+
content = readme.read_text()
19+
20+
# Check plugin path is documented
21+
assert "cli-anything-plugin" in content, "README should mention cli-anything-plugin"
22+
23+
# Check skill path is documented (dual-entrypoint)
24+
assert ".agents/skills" in content or "repo-local" in content.lower(), \
25+
"README should mention repo-local skill path"
26+
27+
28+
def test_skill_directory_exists():
29+
"""Repo-local skill directory should exist."""
30+
skill_dir = REPO_ROOT / ".agents" / "skills" / "cli-anything"
31+
assert skill_dir.exists(), f"Skill directory should exist at {skill_dir}"
32+
assert (skill_dir / "SKILL.md").exists(), "Skill should have SKILL.md"
33+
34+
35+
def test_skill_reuses_harness():
36+
"""Skill should reference the existing HARNESS.md."""
37+
skill_md = REPO_ROOT / ".agents" / "skills" / "cli-anything" / "SKILL.md"
38+
content = skill_md.read_text()
39+
40+
assert "HARNESS.md" in content, "Skill should reference HARNESS.md"
41+
assert "cli-anything-plugin" in content, "Skill should mention plugin for shared specs"
42+
43+
44+
def test_plugin_directory_exists():
45+
"""Plugin directory should exist for dual-entrypoint design."""
46+
plugin_dir = REPO_ROOT / "cli-anything-plugin"
47+
assert plugin_dir.exists(), "cli-anything-plugin directory should exist"
48+
assert (plugin_dir / "HARNESS.md").exists(), "Plugin should have HARNESS.md"
49+
assert (plugin_dir / "commands").exists(), "Plugin should have commands directory"
50+
51+
52+
def test_example_appsocumented():
53+
"""README should list example applications."""
54+
readme = REPO_ROOT / "README.md"
55+
content = readme.read_text()
56+
57+
examples = ["GIMP", "Blender", "Inkscape", "Audacity"]
58+
for example in examples:
59+
assert example in content, f"README should mention {example} as example"
60+
61+
62+
if __name__ == "__main__":
63+
import sys
64+
65+
tests = [
66+
test_readme_mentions_plugin_and_skill,
67+
test_skill_directory_exists,
68+
test_skill_reuses_harness,
69+
test_plugin_directory_exists,
70+
test_example_appsocumented,
71+
]
72+
73+
failed = []
74+
for test in tests:
75+
try:
76+
test()
77+
print(f"✓ {test.__name__}")
78+
except AssertionError as e:
79+
print(f"✗ {test.__name__}: {e}")
80+
failed.append(test.__name__)
81+
82+
if failed:
83+
print(f"\n{len(failed)} test(s) failed")
84+
sys.exit(1)
85+
else:
86+
print(f"\nAll {len(tests)} tests passed!")
87+
sys.exit(0)

0 commit comments

Comments
 (0)