cli-creator-skill 0.1.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.
- cli_creator_skill/__init__.py +3 -0
- cli_creator_skill/__main__.py +5 -0
- cli_creator_skill/installer.py +69 -0
- cli_creator_skill/skills/cli-creator/SKILL.md +288 -0
- cli_creator_skill/skills/cli-creator/references/creation-playbook.md +267 -0
- cli_creator_skill/skills/cli-creator/references/pitfalls-and-solutions.md +319 -0
- cli_creator_skill/skills/cli-creator/references/review-rubric.md +217 -0
- cli_creator_skill-0.1.0.dist-info/METADATA +129 -0
- cli_creator_skill-0.1.0.dist-info/RECORD +13 -0
- cli_creator_skill-0.1.0.dist-info/WHEEL +4 -0
- cli_creator_skill-0.1.0.dist-info/entry_points.txt +2 -0
- cli_creator_skill-0.1.0.dist-info/licenses/LICENSE +21 -0
- cli_creator_skill-0.1.0.dist-info/licenses/NOTICE.md +5 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import shutil
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
SKILL_NAME = "cli-creator"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def default_target() -> Path:
|
|
13
|
+
return Path.home() / ".codex" / "skills"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def skill_source() -> Path:
|
|
17
|
+
return Path(__file__).resolve().parent / "skills" / SKILL_NAME
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def install(target: Path, force: bool = False) -> Path:
|
|
21
|
+
src = skill_source()
|
|
22
|
+
if not src.exists():
|
|
23
|
+
raise FileNotFoundError(f"Skill files were not found in the package: {src}")
|
|
24
|
+
|
|
25
|
+
dest = target.expanduser().resolve() / SKILL_NAME
|
|
26
|
+
if dest.exists():
|
|
27
|
+
if not force:
|
|
28
|
+
raise FileExistsError(
|
|
29
|
+
f"{dest} already exists. Re-run with --force to overwrite it."
|
|
30
|
+
)
|
|
31
|
+
shutil.rmtree(dest)
|
|
32
|
+
|
|
33
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
34
|
+
shutil.copytree(src, dest)
|
|
35
|
+
return dest
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def main(argv: list[str] | None = None) -> int:
|
|
39
|
+
parser = argparse.ArgumentParser(
|
|
40
|
+
prog="cli-creator-skill",
|
|
41
|
+
description="Install the cli-creator agent skill.",
|
|
42
|
+
)
|
|
43
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
44
|
+
|
|
45
|
+
install_parser = subparsers.add_parser("install", help="Install the skill locally.")
|
|
46
|
+
install_parser.add_argument(
|
|
47
|
+
"--target",
|
|
48
|
+
type=Path,
|
|
49
|
+
default=default_target(),
|
|
50
|
+
help="Directory that contains skill folders. Default: ~/.codex/skills",
|
|
51
|
+
)
|
|
52
|
+
install_parser.add_argument(
|
|
53
|
+
"--force",
|
|
54
|
+
action="store_true",
|
|
55
|
+
help="Overwrite an existing cli-creator skill directory.",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
args = parser.parse_args(argv)
|
|
59
|
+
if args.command in (None, "install"):
|
|
60
|
+
try:
|
|
61
|
+
dest = install(args.target, force=args.force)
|
|
62
|
+
except Exception as exc:
|
|
63
|
+
print(f"Install failed: {exc}", file=sys.stderr)
|
|
64
|
+
return 1
|
|
65
|
+
print(f"Installed {SKILL_NAME} to {dest}")
|
|
66
|
+
return 0
|
|
67
|
+
|
|
68
|
+
parser.print_help()
|
|
69
|
+
return 0
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cli-creator
|
|
3
|
+
description: Use when designing, scaffolding, refactoring, or auditing a Python CLI tool, especially Typer + Rich + questionary CLIs with interactive flows, data fetching, caching, LLM integration, structured output, local memory, and multi-channel delivery.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# CLI Creator
|
|
7
|
+
|
|
8
|
+
Use this skill to create a high-quality CLI from zero, or to review an existing CLI and produce actionable fixes. Prefer it for interactive, data-driven, LLM-assisted, multi-turn command line products.
|
|
9
|
+
|
|
10
|
+
## Trigger Conditions
|
|
11
|
+
|
|
12
|
+
Use this skill when the user asks to:
|
|
13
|
+
|
|
14
|
+
- Create a Python CLI, command line app, interactive assistant, research assistant, data tool, or automation CLI.
|
|
15
|
+
- Improve a CLI's UX, command surface, onboarding, config flow, model setup, caching, or release process.
|
|
16
|
+
- Audit an existing CLI for maintainability, reliability, packaging, PyPI installability, or user experience.
|
|
17
|
+
- Add Typer, Rich, questionary, litellm, instructor, Pydantic, SQLite, config, profile memory, or provider setup to a CLI.
|
|
18
|
+
- Diagnose symptoms such as "command not found", "model returns empty", "refresh shows same results", "users do not know how to configure", "interactive flow feels rigid", or "report quality is shallow".
|
|
19
|
+
|
|
20
|
+
## Core Philosophy
|
|
21
|
+
|
|
22
|
+
Build the CLI as a product, not as a thin script.
|
|
23
|
+
|
|
24
|
+
1. Start from the user's job, not the command list. The first screen must help users decide what to do next.
|
|
25
|
+
2. Separate command routing, conversation flow, data access, LLM reasoning, persistence, and delivery channels.
|
|
26
|
+
3. Make every external dependency visible and diagnosable: model provider, base URL, model name, auth state, cache age, and output path.
|
|
27
|
+
4. Prefer progressive interaction. Ask one natural question at a time, summarize what you learned, and allow correction.
|
|
28
|
+
5. Ground data-driven recommendations in evidence. Show source, time window, freshness, and confidence.
|
|
29
|
+
6. Treat local memory as a user-controlled feature. Provide inspect, update, export, and clear commands.
|
|
30
|
+
7. Optimize for recovery. Every error should explain what happened, why it likely happened, and what command fixes it.
|
|
31
|
+
|
|
32
|
+
Balance UX and functionality by making the default path friendly and the expert path scriptable. Interactive commands should guide; non-interactive flags should reproduce the same workflow for automation.
|
|
33
|
+
|
|
34
|
+
## First Response Pattern
|
|
35
|
+
|
|
36
|
+
When starting a CLI creation task:
|
|
37
|
+
|
|
38
|
+
1. Restate the target user, core workflow, and delivery format in one short paragraph.
|
|
39
|
+
2. Identify whether this is a new CLI, a refactor, or an audit.
|
|
40
|
+
3. Inspect the repository before proposing architecture when code already exists.
|
|
41
|
+
4. Create or update files directly unless the user explicitly asks for a plan only.
|
|
42
|
+
5. Verify the installed command, the help output, and at least one end-to-end smoke path.
|
|
43
|
+
|
|
44
|
+
When starting a CLI review task:
|
|
45
|
+
|
|
46
|
+
1. Run a quick structure scan: `rg --files`, `pyproject.toml`, entry points, package layout, tests, README.
|
|
47
|
+
2. Run the CLI help and one representative command when safe.
|
|
48
|
+
3. Report findings by severity first, with file and line references.
|
|
49
|
+
4. Suggest fixes that preserve the existing architecture unless the structure itself is the problem.
|
|
50
|
+
|
|
51
|
+
## Creation Workflow
|
|
52
|
+
|
|
53
|
+
Follow this workflow for a new CLI.
|
|
54
|
+
|
|
55
|
+
### 1. Define The Product Surface
|
|
56
|
+
|
|
57
|
+
Clarify:
|
|
58
|
+
|
|
59
|
+
- Primary job: what valuable outcome should the user get in one session?
|
|
60
|
+
- First-run path: what does a brand-new user see before any config exists?
|
|
61
|
+
- Expert path: what command can be scripted in CI, cron, or automations?
|
|
62
|
+
- State model: what is ephemeral, cached, remembered, or user-owned?
|
|
63
|
+
- External integrations: models, APIs, browser tools, Feishu/Lark, GitHub, file outputs.
|
|
64
|
+
|
|
65
|
+
Design no more than 5 top-level commands for v1. Prefer:
|
|
66
|
+
|
|
67
|
+
- `run` for the main interactive flow.
|
|
68
|
+
- `setup` for guided first-run configuration.
|
|
69
|
+
- `config` for inspect/update/reset.
|
|
70
|
+
- `doctor` for diagnostics and auto-fixes.
|
|
71
|
+
- `history` or `profile` only when persistent memory is a core feature.
|
|
72
|
+
|
|
73
|
+
### 2. Choose The Stack
|
|
74
|
+
|
|
75
|
+
Use this default stack unless the repo has a strong existing convention:
|
|
76
|
+
|
|
77
|
+
- Typer for command routing, type hints, and shell completion.
|
|
78
|
+
- Rich for panels, tables, markdown rendering, progress, and friendly errors.
|
|
79
|
+
- questionary for interactive prompts, with non-TTY fallbacks.
|
|
80
|
+
- Pydantic v2 for domain models and validation.
|
|
81
|
+
- pydantic-settings plus `.env` for config.
|
|
82
|
+
- SQLite for cache, history, and user profile memory.
|
|
83
|
+
- httpx for HTTP clients with timeouts, retries, and clear user-agent.
|
|
84
|
+
- litellm for multi-provider model calls.
|
|
85
|
+
- instructor for structured LLM output when compatible; provide a JSON-schema fallback.
|
|
86
|
+
|
|
87
|
+
### 3. Design Modules Before Files
|
|
88
|
+
|
|
89
|
+
Keep these boundaries:
|
|
90
|
+
|
|
91
|
+
- `cli`: parse commands and flags only.
|
|
92
|
+
- `app` or `flows`: orchestrate user journeys.
|
|
93
|
+
- `models`: define Pydantic request, result, profile, and report schemas.
|
|
94
|
+
- `settings`: load env/config and validate provider setup.
|
|
95
|
+
- `store`: own SQLite schema, cache, history, and profile memory.
|
|
96
|
+
- `services`: fetch data from external sources.
|
|
97
|
+
- `llm`: call models and normalize structured output.
|
|
98
|
+
- `renderers`: terminal, markdown, JSON, or file rendering.
|
|
99
|
+
- `integrations`: Feishu/Lark, DingTalk, WeChat, GitHub, email, etc.
|
|
100
|
+
|
|
101
|
+
Do not let prompt strings, HTTP calls, database SQL, and Rich tables live in the same module.
|
|
102
|
+
|
|
103
|
+
### 4. Build The Interaction Loop
|
|
104
|
+
|
|
105
|
+
For conversational CLIs, model the flow as stages:
|
|
106
|
+
|
|
107
|
+
1. Explore intent with one open question.
|
|
108
|
+
2. Build a lightweight user profile through natural conversation.
|
|
109
|
+
3. Run data-driven opportunity scanning.
|
|
110
|
+
4. Rank and refine options with the user.
|
|
111
|
+
5. Generate a durable output artifact.
|
|
112
|
+
6. Offer one useful next action.
|
|
113
|
+
|
|
114
|
+
Use state objects, not scattered booleans. Track:
|
|
115
|
+
|
|
116
|
+
- Current stage.
|
|
117
|
+
- User goal and constraints.
|
|
118
|
+
- Known profile fields and confidence.
|
|
119
|
+
- Evidence queries already used.
|
|
120
|
+
- Candidate items already shown.
|
|
121
|
+
- User rejections and "do not ask again" preferences.
|
|
122
|
+
|
|
123
|
+
### 5. Make Data And LLMs Observable
|
|
124
|
+
|
|
125
|
+
For every model-backed or web-backed recommendation, preserve:
|
|
126
|
+
|
|
127
|
+
- Query text.
|
|
128
|
+
- Time window.
|
|
129
|
+
- Source name and URL.
|
|
130
|
+
- Fetch timestamp.
|
|
131
|
+
- Cache key and cache age.
|
|
132
|
+
- Model provider, base URL, model name, and response mode.
|
|
133
|
+
- Structured validation errors.
|
|
134
|
+
|
|
135
|
+
Show concise evidence to the user, and save full evidence beside generated artifacts.
|
|
136
|
+
|
|
137
|
+
### 6. Ship The CLI As An Installable Product
|
|
138
|
+
|
|
139
|
+
Ensure:
|
|
140
|
+
|
|
141
|
+
- `pyproject.toml` defines a `console_scripts` entry point.
|
|
142
|
+
- The command name users type is the command that gets installed.
|
|
143
|
+
- `--help` works before config exists.
|
|
144
|
+
- `setup` guides users through provider, base URL, model name, API key, and verification.
|
|
145
|
+
- `doctor` detects stale entry points, Python version mismatch, missing optional tools, auth state, and config mistakes.
|
|
146
|
+
- README includes install, first run, config, examples, troubleshooting, and extension points.
|
|
147
|
+
|
|
148
|
+
## Review Workflow
|
|
149
|
+
|
|
150
|
+
Audit an existing CLI with this order:
|
|
151
|
+
|
|
152
|
+
1. Inspect package metadata, command entry points, Python version, dependencies, and README.
|
|
153
|
+
2. Run `--help`, `setup --help`, `config --help`, and the main command help.
|
|
154
|
+
3. Trace the main flow from CLI command to app orchestration, services, LLM, persistence, rendering, and output.
|
|
155
|
+
4. Check first-run behavior with no config.
|
|
156
|
+
5. Check invalid config behavior, especially model provider/base URL/model name/API key combinations.
|
|
157
|
+
6. Check cache refresh semantics and whether "refresh" can repeat stale results.
|
|
158
|
+
7. Check non-TTY behavior and scriptability.
|
|
159
|
+
8. Check tests for entry point, config, cache, LLM fallback, and smoke flows.
|
|
160
|
+
9. Score with `references/review-rubric.md`.
|
|
161
|
+
10. Return findings first, then a prioritized repair plan.
|
|
162
|
+
|
|
163
|
+
## Pitfalls To Watch
|
|
164
|
+
|
|
165
|
+
Before implementing or reviewing, read `references/pitfalls-and-solutions.md` when the task involves:
|
|
166
|
+
|
|
167
|
+
- Interactive flows.
|
|
168
|
+
- LLM provider setup.
|
|
169
|
+
- Data caching or refresh.
|
|
170
|
+
- Profile memory.
|
|
171
|
+
- Packaging and PyPI entry points.
|
|
172
|
+
- Feishu/Lark or other delivery channels.
|
|
173
|
+
|
|
174
|
+
High-frequency pitfalls include:
|
|
175
|
+
|
|
176
|
+
- Asking form-like questions instead of having a natural conversation.
|
|
177
|
+
- Hiding required model settings behind a single API key prompt.
|
|
178
|
+
- Treating OpenAI-compatible endpoints as interchangeable without checking path, model name, and response schema.
|
|
179
|
+
- Returning empty lists when the real problem is model/config failure.
|
|
180
|
+
- Letting refresh reuse identical cache keys.
|
|
181
|
+
- Saving user profile memory without inspect and clear commands.
|
|
182
|
+
- Publishing a package whose installed command differs from README examples.
|
|
183
|
+
|
|
184
|
+
## Project Structure Template
|
|
185
|
+
|
|
186
|
+
Use or adapt this structure:
|
|
187
|
+
|
|
188
|
+
```text
|
|
189
|
+
my-cli/
|
|
190
|
+
pyproject.toml
|
|
191
|
+
README.md
|
|
192
|
+
.env.example
|
|
193
|
+
src/my_cli/
|
|
194
|
+
__init__.py
|
|
195
|
+
__main__.py
|
|
196
|
+
cli.py
|
|
197
|
+
app.py
|
|
198
|
+
console.py
|
|
199
|
+
errors.py
|
|
200
|
+
models.py
|
|
201
|
+
settings.py
|
|
202
|
+
store.py
|
|
203
|
+
prompts.py
|
|
204
|
+
renderers/
|
|
205
|
+
__init__.py
|
|
206
|
+
terminal.py
|
|
207
|
+
markdown.py
|
|
208
|
+
json.py
|
|
209
|
+
services/
|
|
210
|
+
__init__.py
|
|
211
|
+
evidence.py
|
|
212
|
+
search.py
|
|
213
|
+
llm/
|
|
214
|
+
__init__.py
|
|
215
|
+
client.py
|
|
216
|
+
schemas.py
|
|
217
|
+
integrations/
|
|
218
|
+
__init__.py
|
|
219
|
+
base.py
|
|
220
|
+
lark.py
|
|
221
|
+
dingtalk.py
|
|
222
|
+
wechat.py
|
|
223
|
+
tests/
|
|
224
|
+
test_cli_help.py
|
|
225
|
+
test_config.py
|
|
226
|
+
test_store.py
|
|
227
|
+
test_flow_smoke.py
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Read `references/creation-playbook.md` for a fuller scaffold and implementation sequence.
|
|
231
|
+
|
|
232
|
+
## Interactive Design Rules
|
|
233
|
+
|
|
234
|
+
Use these rules for conversational or assistant-like CLIs:
|
|
235
|
+
|
|
236
|
+
- Ask one question at a time.
|
|
237
|
+
- Make each question sound like a helpful collaborator, not an application form.
|
|
238
|
+
- Stop asking when enough signal exists; use defaults and say they can be changed later.
|
|
239
|
+
- Never repeat a question whose semantic field was already answered.
|
|
240
|
+
- Summarize the profile before using it for recommendations.
|
|
241
|
+
- Accept natural language commands such as "换一个方向", "再细一点", "这个太难", "保守一点", "直接生成".
|
|
242
|
+
- Treat refresh as a new search intent with exclusions from previously shown candidates.
|
|
243
|
+
- Always let the user inspect and clear remembered profile data.
|
|
244
|
+
|
|
245
|
+
For profile-building flows, internally collect background, goal, resources, constraints, risk preference, and output preference, but phrase questions naturally:
|
|
246
|
+
|
|
247
|
+
- "先聊聊你的背景吧,你之前主要在哪些方向做过研究、写作或项目?"
|
|
248
|
+
- "这次你更想得到什么结果?发论文、写长文、系统学习、职业准备,还是单纯好奇?"
|
|
249
|
+
- "你有没有别人不太容易有的视角、经历或资源?"
|
|
250
|
+
- "有没有什么方向你明确不想碰,或者现在比较顾虑?"
|
|
251
|
+
|
|
252
|
+
## LLM Integration Rules
|
|
253
|
+
|
|
254
|
+
When adding model support:
|
|
255
|
+
|
|
256
|
+
1. Require provider, base URL, model name, and API key as separate visible fields when using OpenAI-compatible third-party providers.
|
|
257
|
+
2. Provide presets for common providers, but let users override every field.
|
|
258
|
+
3. Verify configuration with a small structured-output call.
|
|
259
|
+
4. Detect and explain common failures: wrong endpoint path, unsupported JSON schema, invalid model name, expired key, proxy issue, timeout, and content filter.
|
|
260
|
+
5. Fall back from instructor tool/function mode to JSON mode or plain JSON parsing when provider compatibility is partial.
|
|
261
|
+
6. Cache only successful data fetches and validated LLM outputs. Do not cache empty results from failed calls as if they were valid.
|
|
262
|
+
|
|
263
|
+
## Output Standards
|
|
264
|
+
|
|
265
|
+
For a new CLI task, deliver:
|
|
266
|
+
|
|
267
|
+
- Project structure.
|
|
268
|
+
- Core Pydantic models.
|
|
269
|
+
- Main commands and help text.
|
|
270
|
+
- First-run setup flow.
|
|
271
|
+
- End-to-end smoke command.
|
|
272
|
+
- README updates.
|
|
273
|
+
- Known limitations and next steps.
|
|
274
|
+
|
|
275
|
+
For a review task, deliver:
|
|
276
|
+
|
|
277
|
+
- Findings ordered by severity.
|
|
278
|
+
- File and line references.
|
|
279
|
+
- Reproduction steps.
|
|
280
|
+
- Recommended fixes.
|
|
281
|
+
- Test gaps.
|
|
282
|
+
- A short implementation plan if changes are requested.
|
|
283
|
+
|
|
284
|
+
## References
|
|
285
|
+
|
|
286
|
+
- Read `references/pitfalls-and-solutions.md` for common failure modes and repairs.
|
|
287
|
+
- Read `references/creation-playbook.md` for the full build sequence.
|
|
288
|
+
- Read `references/review-rubric.md` for scoring and audit format.
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# CLI Creation Playbook
|
|
2
|
+
|
|
3
|
+
Use this playbook to build a modern Python CLI that is friendly for first-time users, scriptable for power users, and maintainable for future contributors.
|
|
4
|
+
|
|
5
|
+
## Phase 0: Product Framing
|
|
6
|
+
|
|
7
|
+
Define:
|
|
8
|
+
|
|
9
|
+
- Target user: who uses this CLI and in what context?
|
|
10
|
+
- Job to be done: what useful artifact or decision should the CLI produce?
|
|
11
|
+
- First-run success: what can a user achieve within five minutes?
|
|
12
|
+
- Repeat-run success: what should the CLI remember or automate?
|
|
13
|
+
- Failure model: what can fail, and how should the CLI recover?
|
|
14
|
+
|
|
15
|
+
Write a one-paragraph product promise before writing code.
|
|
16
|
+
|
|
17
|
+
## Phase 1: Command Surface
|
|
18
|
+
|
|
19
|
+
Keep v1 small:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
my-cli run # main interactive flow
|
|
23
|
+
my-cli setup # guided first-run setup
|
|
24
|
+
my-cli config show # inspect config safely
|
|
25
|
+
my-cli config set # update config
|
|
26
|
+
my-cli config reset # reset config
|
|
27
|
+
my-cli doctor # diagnose environment
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Add optional commands only when they expose real user value:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
my-cli profile show
|
|
34
|
+
my-cli profile clear
|
|
35
|
+
my-cli cache clear
|
|
36
|
+
my-cli history list
|
|
37
|
+
my-cli export
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Rules:
|
|
41
|
+
|
|
42
|
+
- Prefer verbs users understand.
|
|
43
|
+
- Keep aliases only when they reduce friction.
|
|
44
|
+
- Ensure every interactive prompt has an equivalent flag for automation.
|
|
45
|
+
|
|
46
|
+
## Phase 2: Project Bootstrap
|
|
47
|
+
|
|
48
|
+
Recommended tooling:
|
|
49
|
+
|
|
50
|
+
- `uv` for project and lock management when available.
|
|
51
|
+
- `src/` layout to prevent import confusion.
|
|
52
|
+
- `pytest` for tests.
|
|
53
|
+
- `ruff` for linting and formatting.
|
|
54
|
+
- `typer`, `rich`, `questionary`, `pydantic`, `pydantic-settings`, `python-dotenv`, `httpx`, `litellm`, `instructor`.
|
|
55
|
+
|
|
56
|
+
Minimal `pyproject.toml` shape:
|
|
57
|
+
|
|
58
|
+
```toml
|
|
59
|
+
[project]
|
|
60
|
+
name = "my-cli"
|
|
61
|
+
version = "0.1.0"
|
|
62
|
+
requires-python = ">=3.10"
|
|
63
|
+
dependencies = [
|
|
64
|
+
"typer>=0.12",
|
|
65
|
+
"rich>=13",
|
|
66
|
+
"questionary>=2",
|
|
67
|
+
"pydantic>=2",
|
|
68
|
+
"pydantic-settings>=2",
|
|
69
|
+
"python-dotenv>=1",
|
|
70
|
+
"httpx>=0.27",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[project.scripts]
|
|
74
|
+
my-cli = "my_cli.cli:main"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Phase 3: Domain Models
|
|
78
|
+
|
|
79
|
+
Define Pydantic models before implementing long flows.
|
|
80
|
+
|
|
81
|
+
Common models:
|
|
82
|
+
|
|
83
|
+
- `UserProfile`: background, goals, resources, constraints, risk preference, output preference, updated_at, confidence.
|
|
84
|
+
- `ConversationState`: current stage, known facts, pending question, rejected items, shown candidates.
|
|
85
|
+
- `EvidenceItem`: source, title, url, published_at, metric, snippet, reliability.
|
|
86
|
+
- `Candidate`: title, summary, evidence, scores, novelty, user_fit.
|
|
87
|
+
- `Brief`: final structured artifact.
|
|
88
|
+
- `ModelConfig`: provider, base_url, model, api_key_ref, mode, timeout.
|
|
89
|
+
- `CacheEntry`: key, status, payload, created_at, expires_at, error_summary.
|
|
90
|
+
|
|
91
|
+
Keep fields explicit enough that invalid LLM output fails early.
|
|
92
|
+
|
|
93
|
+
## Phase 4: Interaction Design
|
|
94
|
+
|
|
95
|
+
For multi-turn assistant CLIs:
|
|
96
|
+
|
|
97
|
+
1. Ask one open question.
|
|
98
|
+
2. Interpret intent.
|
|
99
|
+
3. Ask the next most useful missing question.
|
|
100
|
+
4. Summarize the profile.
|
|
101
|
+
5. Confirm or let the user correct.
|
|
102
|
+
6. Fetch evidence.
|
|
103
|
+
7. Show a ranked table.
|
|
104
|
+
8. Allow selection, refresh, refinement, or free-text challenge.
|
|
105
|
+
9. Generate an output file.
|
|
106
|
+
10. Offer delivery or next analysis.
|
|
107
|
+
|
|
108
|
+
State machine fields:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
class Stage(str, Enum):
|
|
112
|
+
EXPLORE = "explore"
|
|
113
|
+
PROFILE = "profile"
|
|
114
|
+
SCAN = "scan"
|
|
115
|
+
REFINE = "refine"
|
|
116
|
+
OUTPUT = "output"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Do not hard-code long question chains. Decide the next prompt from missing fields and the user's latest answer.
|
|
120
|
+
|
|
121
|
+
## Phase 5: Persistence And Cache
|
|
122
|
+
|
|
123
|
+
Use SQLite for:
|
|
124
|
+
|
|
125
|
+
- Query cache.
|
|
126
|
+
- Evidence cache.
|
|
127
|
+
- LLM structured output cache.
|
|
128
|
+
- User profile memory.
|
|
129
|
+
- Run history.
|
|
130
|
+
|
|
131
|
+
Cache key should include:
|
|
132
|
+
|
|
133
|
+
- Normalized query.
|
|
134
|
+
- Time window.
|
|
135
|
+
- Source or provider.
|
|
136
|
+
- Filters.
|
|
137
|
+
- Schema version.
|
|
138
|
+
|
|
139
|
+
Cache entry should include:
|
|
140
|
+
|
|
141
|
+
- Status.
|
|
142
|
+
- Created time.
|
|
143
|
+
- Expiry time.
|
|
144
|
+
- Payload hash.
|
|
145
|
+
- Error summary for failed calls.
|
|
146
|
+
|
|
147
|
+
Commands:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
my-cli cache stats
|
|
151
|
+
my-cli cache clear
|
|
152
|
+
my-cli profile show
|
|
153
|
+
my-cli profile clear
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Do not cache failed empty results as valid recommendations.
|
|
157
|
+
|
|
158
|
+
## Phase 6: LLM Integration
|
|
159
|
+
|
|
160
|
+
Support model providers through a normalized client:
|
|
161
|
+
|
|
162
|
+
- OpenAI.
|
|
163
|
+
- Anthropic.
|
|
164
|
+
- OpenAI-compatible providers.
|
|
165
|
+
- Ark or other provider-specific endpoints.
|
|
166
|
+
- Local Ollama when useful.
|
|
167
|
+
|
|
168
|
+
Configuration rules:
|
|
169
|
+
|
|
170
|
+
- Provider, base URL, model name, and API key must be separate.
|
|
171
|
+
- Presets should help, not hide fields.
|
|
172
|
+
- Verification must call the configured model.
|
|
173
|
+
- Store capability probes: plain chat, JSON mode, instructor/tool mode.
|
|
174
|
+
|
|
175
|
+
Structured output strategy:
|
|
176
|
+
|
|
177
|
+
1. Try instructor with provider-compatible mode.
|
|
178
|
+
2. Fall back to JSON mode.
|
|
179
|
+
3. Fall back to plain text with strict JSON extraction.
|
|
180
|
+
4. Validate with Pydantic.
|
|
181
|
+
5. Retry once with validation errors summarized.
|
|
182
|
+
6. Fail clearly with a diagnostic command.
|
|
183
|
+
|
|
184
|
+
## Phase 7: External Integrations
|
|
185
|
+
|
|
186
|
+
Use adapter interfaces:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
class DeliveryChannel(Protocol):
|
|
190
|
+
name: str
|
|
191
|
+
def is_configured(self) -> bool: ...
|
|
192
|
+
def verify(self) -> VerificationResult: ...
|
|
193
|
+
def send_file(self, file_path: Path, message: str) -> DeliveryResult: ...
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Keep integration-specific auth, CLI calls, and error mapping inside adapters.
|
|
197
|
+
|
|
198
|
+
For Feishu/Lark:
|
|
199
|
+
|
|
200
|
+
- Detect whether `lark-cli` exists.
|
|
201
|
+
- Check `auth status` for user or bot.
|
|
202
|
+
- Check configured chat ID.
|
|
203
|
+
- Guide users to install/auth only when missing.
|
|
204
|
+
- Do not block report generation if delivery is not configured.
|
|
205
|
+
|
|
206
|
+
## Phase 8: Error Handling
|
|
207
|
+
|
|
208
|
+
Define user-facing exceptions:
|
|
209
|
+
|
|
210
|
+
- `ConfigError`
|
|
211
|
+
- `ModelVerificationError`
|
|
212
|
+
- `DataFetchError`
|
|
213
|
+
- `CacheError`
|
|
214
|
+
- `DeliveryError`
|
|
215
|
+
- `UserCancelled`
|
|
216
|
+
|
|
217
|
+
Each error should include:
|
|
218
|
+
|
|
219
|
+
- Message.
|
|
220
|
+
- Likely cause.
|
|
221
|
+
- Suggested command.
|
|
222
|
+
- Whether retry is safe.
|
|
223
|
+
|
|
224
|
+
Show tracebacks only with `--debug`.
|
|
225
|
+
|
|
226
|
+
## Phase 9: Testing
|
|
227
|
+
|
|
228
|
+
Minimum tests:
|
|
229
|
+
|
|
230
|
+
- Import package.
|
|
231
|
+
- Run `--help`.
|
|
232
|
+
- Run every command's `--help`.
|
|
233
|
+
- Load default settings with temp home.
|
|
234
|
+
- Save, show, and clear profile.
|
|
235
|
+
- Cache hit, miss, refresh, and expired behavior.
|
|
236
|
+
- Model config validation without real network.
|
|
237
|
+
- One offline smoke flow using fixture evidence.
|
|
238
|
+
|
|
239
|
+
Useful commands:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
python -m pytest
|
|
243
|
+
python -m my_cli --help
|
|
244
|
+
my-cli doctor --json
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Phase 10: Documentation And Release
|
|
248
|
+
|
|
249
|
+
README must include:
|
|
250
|
+
|
|
251
|
+
- What the CLI is for.
|
|
252
|
+
- Install command.
|
|
253
|
+
- First-run setup.
|
|
254
|
+
- Main workflow with screenshots or terminal examples.
|
|
255
|
+
- Model provider configuration examples.
|
|
256
|
+
- Config paths.
|
|
257
|
+
- Troubleshooting.
|
|
258
|
+
- Extension guide.
|
|
259
|
+
|
|
260
|
+
Release checklist:
|
|
261
|
+
|
|
262
|
+
- Clean venv install works.
|
|
263
|
+
- Console script name matches README.
|
|
264
|
+
- `--help` works without config.
|
|
265
|
+
- Package metadata includes Python version.
|
|
266
|
+
- No secrets in repo.
|
|
267
|
+
- PyPI page renders README.
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# CLI Pitfalls And Solutions
|
|
2
|
+
|
|
3
|
+
Use this reference when creating or auditing a Python CLI, especially an interactive Typer + Rich + questionary application with data fetching, LLM integration, and local persistence.
|
|
4
|
+
|
|
5
|
+
## 1. Menu-First Design
|
|
6
|
+
|
|
7
|
+
Problem: The CLI opens with a rigid menu instead of helping the user express intent.
|
|
8
|
+
|
|
9
|
+
Typical signs:
|
|
10
|
+
|
|
11
|
+
- The first prompt asks users to choose between internal implementation modes.
|
|
12
|
+
- Users who do not know the domain cannot proceed confidently.
|
|
13
|
+
- Every branch produces similar results, so choices feel fake.
|
|
14
|
+
|
|
15
|
+
Solution:
|
|
16
|
+
|
|
17
|
+
- Start with a plain-language question about the user's goal.
|
|
18
|
+
- Offer 2-4 examples, but always allow free text.
|
|
19
|
+
- Route free text through intent detection, not a generic default branch.
|
|
20
|
+
|
|
21
|
+
Anti-pattern:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
? Choose mode: [Domain mode, Autonomous mode, Config mode]
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Better:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
? 你最近想研究什么?可以说一个领域,也可以说“我没思路,帮我找机会”。
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 2. Questionnaire-Like Profile Collection
|
|
34
|
+
|
|
35
|
+
Problem: The CLI asks a stack of formal questions and makes the user feel they are filling out a grant application.
|
|
36
|
+
|
|
37
|
+
Typical signs:
|
|
38
|
+
|
|
39
|
+
- Five or more questions are shown at once.
|
|
40
|
+
- Questions use abstract labels such as "风险偏好" or "输出形式偏好".
|
|
41
|
+
- The CLI repeats similar questions after the user already answered.
|
|
42
|
+
|
|
43
|
+
Solution:
|
|
44
|
+
|
|
45
|
+
- Ask one natural question at a time.
|
|
46
|
+
- Maintain a profile state with field confidence.
|
|
47
|
+
- Infer missing fields when confidence is good enough.
|
|
48
|
+
- Allow "没有", "不知道", "跳过", and continue with defaults.
|
|
49
|
+
|
|
50
|
+
Better:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
先聊聊你的背景吧,你之前主要在哪些方向做过研究、写作或项目?
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. No Persistent Profile Memory
|
|
57
|
+
|
|
58
|
+
Problem: The CLI asks the same background questions every run.
|
|
59
|
+
|
|
60
|
+
Typical signs:
|
|
61
|
+
|
|
62
|
+
- Returning users must re-enter goals and constraints.
|
|
63
|
+
- There is no command to inspect or clear memory.
|
|
64
|
+
- Profile data is mixed with cache data.
|
|
65
|
+
|
|
66
|
+
Solution:
|
|
67
|
+
|
|
68
|
+
- Store profile memory in SQLite or a dedicated config file.
|
|
69
|
+
- Provide `profile show`, `profile edit`, and `profile clear`.
|
|
70
|
+
- Store timestamps and confidence per field.
|
|
71
|
+
- Ask only for missing or stale information.
|
|
72
|
+
|
|
73
|
+
## 4. Hidden Model Configuration
|
|
74
|
+
|
|
75
|
+
Problem: The CLI asks only for an API key, but the provider also requires provider name, base URL, and model name.
|
|
76
|
+
|
|
77
|
+
Typical signs:
|
|
78
|
+
|
|
79
|
+
- OpenAI-compatible providers fail silently.
|
|
80
|
+
- Users paste a base URL such as an Ark endpoint but the CLI still calls the OpenAI default.
|
|
81
|
+
- Empty recommendations appear when the real cause is model failure.
|
|
82
|
+
|
|
83
|
+
Solution:
|
|
84
|
+
|
|
85
|
+
- Treat provider, base URL, model, API key, timeout, and structured-output mode as explicit settings.
|
|
86
|
+
- Provide presets, then verify with a small call.
|
|
87
|
+
- Display the active provider summary before expensive workflows.
|
|
88
|
+
|
|
89
|
+
Better commands:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
my-cli setup model
|
|
93
|
+
my-cli config model show
|
|
94
|
+
my-cli config model verify
|
|
95
|
+
my-cli config model presets
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 5. Provider Compatibility Assumptions
|
|
99
|
+
|
|
100
|
+
Problem: The CLI assumes all OpenAI-compatible endpoints support the same schema, tool calls, streaming, and JSON mode.
|
|
101
|
+
|
|
102
|
+
Typical signs:
|
|
103
|
+
|
|
104
|
+
- Instructor fails on one provider but works on another.
|
|
105
|
+
- `base_url` path is wrong, for example using a coding endpoint for chat completions.
|
|
106
|
+
- Model names require provider-specific IDs.
|
|
107
|
+
|
|
108
|
+
Solution:
|
|
109
|
+
|
|
110
|
+
- Implement provider presets with known base URL shape and model examples.
|
|
111
|
+
- Run a capability probe: plain chat, JSON mode, instructor/tool mode.
|
|
112
|
+
- Store capability flags and choose the safest response mode.
|
|
113
|
+
- Provide a manual override.
|
|
114
|
+
|
|
115
|
+
## 6. Caching Failed Or Empty Results
|
|
116
|
+
|
|
117
|
+
Problem: A failed fetch or bad LLM response is cached as a valid empty result.
|
|
118
|
+
|
|
119
|
+
Typical signs:
|
|
120
|
+
|
|
121
|
+
- Refresh still returns no results.
|
|
122
|
+
- The CLI says "no reliable topics" even after config is fixed.
|
|
123
|
+
- Cache has no status field.
|
|
124
|
+
|
|
125
|
+
Solution:
|
|
126
|
+
|
|
127
|
+
- Store cache entries with status: `ok`, `empty-valid`, `error`, `partial`.
|
|
128
|
+
- Do not reuse `error` cache entries unless explicitly requested.
|
|
129
|
+
- Include cache age and source in debug output.
|
|
130
|
+
- Provide `cache clear` and `run --refresh`.
|
|
131
|
+
|
|
132
|
+
## 7. Refresh Shows The Same Items
|
|
133
|
+
|
|
134
|
+
Problem: Refresh reuses the same query, same cache key, and same ranking without exclusions.
|
|
135
|
+
|
|
136
|
+
Typical signs:
|
|
137
|
+
|
|
138
|
+
- Users see identical suggestions across refreshes.
|
|
139
|
+
- The code only bypasses cache but does not alter the search strategy.
|
|
140
|
+
|
|
141
|
+
Solution:
|
|
142
|
+
|
|
143
|
+
- Track shown item IDs, titles, URLs, and embeddings or normalized titles.
|
|
144
|
+
- Add exclusions to ranking.
|
|
145
|
+
- Vary query expansions and time windows.
|
|
146
|
+
- Display "new since last batch" and "hidden duplicates" counts.
|
|
147
|
+
|
|
148
|
+
## 8. Evidence-Free Recommendations
|
|
149
|
+
|
|
150
|
+
Problem: The CLI generates attractive topic names without verifiable sources.
|
|
151
|
+
|
|
152
|
+
Typical signs:
|
|
153
|
+
|
|
154
|
+
- Tables have no source URLs.
|
|
155
|
+
- "Hot" means the model thinks it is hot.
|
|
156
|
+
- Social chatter is treated as equal to papers, policy, market data, or code activity.
|
|
157
|
+
|
|
158
|
+
Solution:
|
|
159
|
+
|
|
160
|
+
- Require evidence objects with source, URL, date, metric, and snippet.
|
|
161
|
+
- Rank topics using transparent dimensions.
|
|
162
|
+
- Mark unsupported claims as hypotheses.
|
|
163
|
+
- Refuse or ask to broaden search when evidence is insufficient.
|
|
164
|
+
|
|
165
|
+
## 9. Monolithic CLI Modules
|
|
166
|
+
|
|
167
|
+
Problem: `cli.py` contains command definitions, prompts, HTTP calls, SQL, prompt templates, and rendering.
|
|
168
|
+
|
|
169
|
+
Typical signs:
|
|
170
|
+
|
|
171
|
+
- Adding a new command risks breaking the main flow.
|
|
172
|
+
- Tests must mock too much.
|
|
173
|
+
- LLM prompts are hard to reuse.
|
|
174
|
+
|
|
175
|
+
Solution:
|
|
176
|
+
|
|
177
|
+
- Keep `cli.py` thin.
|
|
178
|
+
- Move orchestration to `app.py` or `flows/`.
|
|
179
|
+
- Move integrations to `services/` or `integrations/`.
|
|
180
|
+
- Move terminal output to `renderers/terminal.py`.
|
|
181
|
+
|
|
182
|
+
## 10. Poor Non-TTY Behavior
|
|
183
|
+
|
|
184
|
+
Problem: The CLI only works interactively and crashes in automation.
|
|
185
|
+
|
|
186
|
+
Typical signs:
|
|
187
|
+
|
|
188
|
+
- questionary prompts appear in cron, CI, or piped usage.
|
|
189
|
+
- No flags exist for required inputs.
|
|
190
|
+
- The command cannot run with `--yes`, `--json`, or config values.
|
|
191
|
+
|
|
192
|
+
Solution:
|
|
193
|
+
|
|
194
|
+
- Detect `sys.stdin.isatty()`.
|
|
195
|
+
- Provide flags for every required prompt.
|
|
196
|
+
- In non-TTY mode, fail with a clear missing-argument message or use defaults.
|
|
197
|
+
- Keep JSON output free of Rich styling.
|
|
198
|
+
|
|
199
|
+
## 11. Friendly UI But Weak Errors
|
|
200
|
+
|
|
201
|
+
Problem: The CLI looks polished but gives vague failure messages.
|
|
202
|
+
|
|
203
|
+
Typical signs:
|
|
204
|
+
|
|
205
|
+
- "执行失败" without cause.
|
|
206
|
+
- Stack traces shown to normal users.
|
|
207
|
+
- No suggested command fixes the issue.
|
|
208
|
+
|
|
209
|
+
Solution:
|
|
210
|
+
|
|
211
|
+
- Define domain errors with human messages and repair hints.
|
|
212
|
+
- Add `--debug` for tracebacks.
|
|
213
|
+
- Include next commands, for example `my-cli config model verify`.
|
|
214
|
+
|
|
215
|
+
Error format:
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
模型验证失败:Ark 返回 404,通常是 base_url 路径或模型名不匹配。
|
|
219
|
+
建议:运行 my-cli setup model --provider ark,然后选择一个可用模型。
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 12. Packaging Entry Point Drift
|
|
223
|
+
|
|
224
|
+
Problem: README says `hotspot-research`, package installs `hotspot-research-cli`, or stale scripts remain on PATH.
|
|
225
|
+
|
|
226
|
+
Typical signs:
|
|
227
|
+
|
|
228
|
+
- `command not found` after successful install.
|
|
229
|
+
- Help text shows old command names.
|
|
230
|
+
- User must manually create symlinks.
|
|
231
|
+
|
|
232
|
+
Solution:
|
|
233
|
+
|
|
234
|
+
- Define the final command in `[project.scripts]`.
|
|
235
|
+
- Add a `doctor --fix-entrypoint` command only for legacy installs.
|
|
236
|
+
- Test install into a clean venv.
|
|
237
|
+
- Keep README examples generated or verified from real commands.
|
|
238
|
+
|
|
239
|
+
## 13. Secrets In Logs And Config
|
|
240
|
+
|
|
241
|
+
Problem: API keys, tokens, or bot credentials appear in logs, snapshots, or Git history.
|
|
242
|
+
|
|
243
|
+
Typical signs:
|
|
244
|
+
|
|
245
|
+
- Config show prints full API keys.
|
|
246
|
+
- Debug logs include headers.
|
|
247
|
+
- `.env` is committed.
|
|
248
|
+
|
|
249
|
+
Solution:
|
|
250
|
+
|
|
251
|
+
- Mask secrets by default.
|
|
252
|
+
- Store keys in OS keychain when available, or protected config files.
|
|
253
|
+
- Keep `.env.example`, never `.env`.
|
|
254
|
+
- Add pre-commit or CI secret scanning when feasible.
|
|
255
|
+
|
|
256
|
+
## 14. Slow Startup
|
|
257
|
+
|
|
258
|
+
Problem: Heavy imports, network probes, or model discovery happen before help output.
|
|
259
|
+
|
|
260
|
+
Typical signs:
|
|
261
|
+
|
|
262
|
+
- `my-cli --help` is slow.
|
|
263
|
+
- Importing the package triggers HTTP calls.
|
|
264
|
+
- Rich progress starts before command validation.
|
|
265
|
+
|
|
266
|
+
Solution:
|
|
267
|
+
|
|
268
|
+
- Keep top-level imports lightweight.
|
|
269
|
+
- Lazy-load LLM, browser, data, and rendering-heavy modules inside commands.
|
|
270
|
+
- Never probe network during import.
|
|
271
|
+
|
|
272
|
+
## 15. Missing Smoke Tests
|
|
273
|
+
|
|
274
|
+
Problem: Unit tests pass but the installed CLI is broken.
|
|
275
|
+
|
|
276
|
+
Typical signs:
|
|
277
|
+
|
|
278
|
+
- No test runs `python -m package --help`.
|
|
279
|
+
- No test checks `console_scripts`.
|
|
280
|
+
- No test covers first run with empty config.
|
|
281
|
+
|
|
282
|
+
Solution:
|
|
283
|
+
|
|
284
|
+
- Test `--help` for all top-level commands.
|
|
285
|
+
- Test config load with temp directories.
|
|
286
|
+
- Test one dry-run or offline smoke flow.
|
|
287
|
+
- Test package build metadata.
|
|
288
|
+
|
|
289
|
+
## 16. Integration Hard-Coding
|
|
290
|
+
|
|
291
|
+
Problem: The CLI directly calls one delivery channel or one model provider throughout the app.
|
|
292
|
+
|
|
293
|
+
Typical signs:
|
|
294
|
+
|
|
295
|
+
- Feishu logic is embedded in report generation.
|
|
296
|
+
- Adding DingTalk requires editing core flow code.
|
|
297
|
+
- Provider-specific exceptions leak into UI.
|
|
298
|
+
|
|
299
|
+
Solution:
|
|
300
|
+
|
|
301
|
+
- Define integration interfaces.
|
|
302
|
+
- Keep provider adapters small.
|
|
303
|
+
- Return normalized result objects.
|
|
304
|
+
- Let the main app depend on abstractions, not concrete CLIs.
|
|
305
|
+
|
|
306
|
+
## 17. No Diagnostics Command
|
|
307
|
+
|
|
308
|
+
Problem: Users cannot tell whether the failure is config, network, dependency, auth, or code.
|
|
309
|
+
|
|
310
|
+
Typical signs:
|
|
311
|
+
|
|
312
|
+
- Support requests include screenshots instead of diagnostic output.
|
|
313
|
+
- The README has long manual troubleshooting sections.
|
|
314
|
+
|
|
315
|
+
Solution:
|
|
316
|
+
|
|
317
|
+
- Implement `doctor`.
|
|
318
|
+
- Check Python version, package version, command path, config path, model provider, cache DB, optional CLIs, auth state, network reachability, and write permissions.
|
|
319
|
+
- Provide `doctor --json` for bug reports.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# CLI Review Rubric
|
|
2
|
+
|
|
3
|
+
Use this rubric to audit an existing CLI. Score each category from 0 to 3 and mark urgent issues as P0/P1/P2.
|
|
4
|
+
|
|
5
|
+
## Scoring
|
|
6
|
+
|
|
7
|
+
- 0: Missing or actively harmful.
|
|
8
|
+
- 1: Present but fragile or confusing.
|
|
9
|
+
- 2: Mostly solid with clear improvement areas.
|
|
10
|
+
- 3: Strong, tested, and user-friendly.
|
|
11
|
+
|
|
12
|
+
## Severity
|
|
13
|
+
|
|
14
|
+
- P0: Prevents normal use, risks data loss, leaks secrets, or breaks installation.
|
|
15
|
+
- P1: Major UX, correctness, reliability, or maintainability issue.
|
|
16
|
+
- P2: Improvement that reduces friction or future risk.
|
|
17
|
+
|
|
18
|
+
## 1. Command Surface And First Run
|
|
19
|
+
|
|
20
|
+
Check:
|
|
21
|
+
|
|
22
|
+
- Does the installed command match the README?
|
|
23
|
+
- Does `--help` work before config exists?
|
|
24
|
+
- Is there a guided `setup`?
|
|
25
|
+
- Is the main command obvious?
|
|
26
|
+
- Are expert flags available for automation?
|
|
27
|
+
|
|
28
|
+
Red flags:
|
|
29
|
+
|
|
30
|
+
- Command not found after successful install.
|
|
31
|
+
- First run immediately fails on missing config.
|
|
32
|
+
- Users must read source code to configure providers.
|
|
33
|
+
|
|
34
|
+
## 2. Interactive UX
|
|
35
|
+
|
|
36
|
+
Check:
|
|
37
|
+
|
|
38
|
+
- Does the CLI ask one natural question at a time?
|
|
39
|
+
- Does it support free text, correction, refresh, and cancel?
|
|
40
|
+
- Does refresh produce genuinely new options?
|
|
41
|
+
- Does it avoid repeating questions?
|
|
42
|
+
- Does it summarize before committing to a recommendation?
|
|
43
|
+
|
|
44
|
+
Red flags:
|
|
45
|
+
|
|
46
|
+
- Menus expose internal architecture.
|
|
47
|
+
- All choices lead to the same output.
|
|
48
|
+
- Profile collection feels like a form.
|
|
49
|
+
|
|
50
|
+
## 3. Architecture And Modularity
|
|
51
|
+
|
|
52
|
+
Check:
|
|
53
|
+
|
|
54
|
+
- Is `cli.py` thin?
|
|
55
|
+
- Are flows, services, LLM, persistence, rendering, and integrations separated?
|
|
56
|
+
- Are Pydantic models used for structured data?
|
|
57
|
+
- Can integrations be added without editing core flows?
|
|
58
|
+
|
|
59
|
+
Red flags:
|
|
60
|
+
|
|
61
|
+
- One large file owns everything.
|
|
62
|
+
- Prompt strings, SQL, Rich rendering, and HTTP calls are mixed.
|
|
63
|
+
|
|
64
|
+
## 4. Configuration And Secrets
|
|
65
|
+
|
|
66
|
+
Check:
|
|
67
|
+
|
|
68
|
+
- Are provider, base URL, model, and API key represented separately?
|
|
69
|
+
- Are secrets masked in `config show`?
|
|
70
|
+
- Are config paths documented?
|
|
71
|
+
- Can users reset config safely?
|
|
72
|
+
|
|
73
|
+
Red flags:
|
|
74
|
+
|
|
75
|
+
- Full API keys printed to terminal.
|
|
76
|
+
- Provider setup silently falls back to a wrong default.
|
|
77
|
+
|
|
78
|
+
## 5. LLM Integration
|
|
79
|
+
|
|
80
|
+
Check:
|
|
81
|
+
|
|
82
|
+
- Is configuration verified with the actual model?
|
|
83
|
+
- Are provider compatibility differences handled?
|
|
84
|
+
- Is structured output validated?
|
|
85
|
+
- Is there a fallback when instructor/tool mode is unsupported?
|
|
86
|
+
- Are validation errors retried or explained?
|
|
87
|
+
|
|
88
|
+
Red flags:
|
|
89
|
+
|
|
90
|
+
- Empty user-facing results hide model failures.
|
|
91
|
+
- All OpenAI-compatible providers are treated as identical.
|
|
92
|
+
|
|
93
|
+
## 6. Data Fetching And Evidence
|
|
94
|
+
|
|
95
|
+
Check:
|
|
96
|
+
|
|
97
|
+
- Are recommendations grounded in source objects?
|
|
98
|
+
- Are source URLs, dates, and metrics preserved?
|
|
99
|
+
- Are fetch failures distinguishable from no results?
|
|
100
|
+
- Are rate limits and timeouts handled?
|
|
101
|
+
|
|
102
|
+
Red flags:
|
|
103
|
+
|
|
104
|
+
- "Hot" topics have no evidence.
|
|
105
|
+
- Social buzz is treated as fact without corroboration.
|
|
106
|
+
|
|
107
|
+
## 7. Cache And Persistence
|
|
108
|
+
|
|
109
|
+
Check:
|
|
110
|
+
|
|
111
|
+
- Is cache keyed by query, window, source, filters, and schema version?
|
|
112
|
+
- Are failed calls excluded from normal cache hits?
|
|
113
|
+
- Can users clear cache?
|
|
114
|
+
- Is profile memory separate from fetch cache?
|
|
115
|
+
|
|
116
|
+
Red flags:
|
|
117
|
+
|
|
118
|
+
- Refresh returns identical cached results.
|
|
119
|
+
- Empty failures are cached as valid.
|
|
120
|
+
- No clear profile command.
|
|
121
|
+
|
|
122
|
+
## 8. Error Handling
|
|
123
|
+
|
|
124
|
+
Check:
|
|
125
|
+
|
|
126
|
+
- Are errors actionable?
|
|
127
|
+
- Is `--debug` available?
|
|
128
|
+
- Are likely causes and suggested commands shown?
|
|
129
|
+
- Are cancellations graceful?
|
|
130
|
+
|
|
131
|
+
Red flags:
|
|
132
|
+
|
|
133
|
+
- Raw tracebacks in normal mode.
|
|
134
|
+
- Generic "failed" messages.
|
|
135
|
+
|
|
136
|
+
## 9. Performance
|
|
137
|
+
|
|
138
|
+
Check:
|
|
139
|
+
|
|
140
|
+
- Is startup fast?
|
|
141
|
+
- Are heavy imports lazy?
|
|
142
|
+
- Are network calls bounded by timeouts?
|
|
143
|
+
- Are progress indicators used for slow operations?
|
|
144
|
+
|
|
145
|
+
Red flags:
|
|
146
|
+
|
|
147
|
+
- `--help` imports LLM/browser modules or probes network.
|
|
148
|
+
- No timeout on HTTP calls.
|
|
149
|
+
|
|
150
|
+
## 10. Testing
|
|
151
|
+
|
|
152
|
+
Check:
|
|
153
|
+
|
|
154
|
+
- Are help commands tested?
|
|
155
|
+
- Is first-run empty config tested?
|
|
156
|
+
- Are cache and profile operations tested?
|
|
157
|
+
- Is there an offline smoke flow?
|
|
158
|
+
- Is package metadata/entry point tested?
|
|
159
|
+
|
|
160
|
+
Red flags:
|
|
161
|
+
|
|
162
|
+
- Only utility functions are tested.
|
|
163
|
+
- No installed-command test.
|
|
164
|
+
|
|
165
|
+
## 11. Documentation
|
|
166
|
+
|
|
167
|
+
Check:
|
|
168
|
+
|
|
169
|
+
- Does README explain the product promise?
|
|
170
|
+
- Are install, setup, run, config, doctor, and troubleshooting documented?
|
|
171
|
+
- Are model provider examples included?
|
|
172
|
+
- Are extension points documented?
|
|
173
|
+
|
|
174
|
+
Red flags:
|
|
175
|
+
|
|
176
|
+
- README examples do not match real commands.
|
|
177
|
+
- No explanation of required model fields.
|
|
178
|
+
|
|
179
|
+
## 12. Release And Maintenance
|
|
180
|
+
|
|
181
|
+
Check:
|
|
182
|
+
|
|
183
|
+
- Is Python version realistic for target users?
|
|
184
|
+
- Are optional integrations optional dependencies?
|
|
185
|
+
- Is release automation documented?
|
|
186
|
+
- Are migrations handled for SQLite/config schema?
|
|
187
|
+
|
|
188
|
+
Red flags:
|
|
189
|
+
|
|
190
|
+
- Package requires a Python version unavailable on target machines without guidance.
|
|
191
|
+
- Breaking config changes lack migrations.
|
|
192
|
+
|
|
193
|
+
## Audit Output Format
|
|
194
|
+
|
|
195
|
+
Use this format:
|
|
196
|
+
|
|
197
|
+
```markdown
|
|
198
|
+
**Findings**
|
|
199
|
+
|
|
200
|
+
- [P0] Installed command does not match README
|
|
201
|
+
- Evidence: `pyproject.toml` defines `x`, README says `y`.
|
|
202
|
+
- Impact: users cannot start the CLI after install.
|
|
203
|
+
- Fix: change `[project.scripts]` or README and test clean install.
|
|
204
|
+
|
|
205
|
+
**Scores**
|
|
206
|
+
|
|
207
|
+
| Area | Score | Notes |
|
|
208
|
+
|---|---:|---|
|
|
209
|
+
| First run | 1/3 | Missing setup |
|
|
210
|
+
| LLM config | 0/3 | Provider/base_url/model collapsed |
|
|
211
|
+
|
|
212
|
+
**Recommended Repair Order**
|
|
213
|
+
|
|
214
|
+
1. Fix entry point and first-run help.
|
|
215
|
+
2. Add model setup verification.
|
|
216
|
+
3. Separate cache failures from empty results.
|
|
217
|
+
```
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cli-creator-skill
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Installable cli-creator agent skill for designing and auditing Python CLI tools.
|
|
5
|
+
Project-URL: Homepage, https://github.com/AdvancingTitans/cli-creator-skill
|
|
6
|
+
Project-URL: Repository, https://github.com/AdvancingTitans/cli-creator-skill
|
|
7
|
+
Project-URL: Issues, https://github.com/AdvancingTitans/cli-creator-skill/issues
|
|
8
|
+
Author: yjw
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: NOTICE.md
|
|
12
|
+
Keywords: agent-skill,cli,codex,llm,questionary,rich,typer
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# cli-creator
|
|
27
|
+
|
|
28
|
+
`cli-creator` is a reusable agent skill for designing, building, and auditing high-quality Python CLI tools.
|
|
29
|
+
|
|
30
|
+
It is especially useful for Typer + Rich + questionary projects with interactive flows, data fetching, caching, LLM provider setup, structured output, local profile memory, and multi-channel delivery.
|
|
31
|
+
|
|
32
|
+
## Install As A Codex Skill
|
|
33
|
+
|
|
34
|
+
Clone this repository and copy the skill directory into your Codex skills folder:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git clone https://github.com/AdvancingTitans/cli-creator-skill.git
|
|
38
|
+
mkdir -p ~/.codex/skills
|
|
39
|
+
cp -R cli-creator-skill/skills/cli-creator ~/.codex/skills/cli-creator
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Then ask your agent to use `cli-creator` when creating or reviewing CLI tools.
|
|
43
|
+
|
|
44
|
+
## Install From PyPI
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install cli-creator-skill
|
|
48
|
+
cli-creator-skill install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
By default this installs the skill to `~/.codex/skills/cli-creator`.
|
|
52
|
+
|
|
53
|
+
Install to a custom directory:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cli-creator-skill install --target ~/.agents/skills
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## PyPI Trusted Publisher
|
|
60
|
+
|
|
61
|
+
This repository is ready for tag-driven PyPI publishing through GitHub Actions.
|
|
62
|
+
|
|
63
|
+
Configure a pending publisher on PyPI with these exact values:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
PyPI project name: cli-creator-skill
|
|
67
|
+
Owner: AdvancingTitans
|
|
68
|
+
Repository name: cli-creator-skill
|
|
69
|
+
Workflow name: publish.yml
|
|
70
|
+
Environment name: pypi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After the pending publisher is configured, publishing is:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
git tag v0.1.0
|
|
77
|
+
git push origin v0.1.0
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## What This Skill Helps With
|
|
81
|
+
|
|
82
|
+
- Design a new Python CLI from scratch.
|
|
83
|
+
- Review an existing CLI for UX, packaging, errors, model setup, caching, and maintainability.
|
|
84
|
+
- Structure Typer + Rich + questionary applications.
|
|
85
|
+
- Build natural multi-turn CLI flows without making users feel like they are filling out a form.
|
|
86
|
+
- Add robust model provider configuration for OpenAI, Anthropic, Ark/OpenAI-compatible endpoints, and local models.
|
|
87
|
+
- Add cache, profile memory, diagnostics, and first-run setup flows.
|
|
88
|
+
|
|
89
|
+
## Repository Structure
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
cli-creator-skill/
|
|
93
|
+
skills/cli-creator/
|
|
94
|
+
SKILL.md
|
|
95
|
+
references/
|
|
96
|
+
creation-playbook.md
|
|
97
|
+
pitfalls-and-solutions.md
|
|
98
|
+
review-rubric.md
|
|
99
|
+
src/cli_creator_skill/
|
|
100
|
+
installer.py
|
|
101
|
+
__main__.py
|
|
102
|
+
pyproject.toml
|
|
103
|
+
README.md
|
|
104
|
+
LICENSE
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Usage
|
|
108
|
+
|
|
109
|
+
Use this skill when you ask:
|
|
110
|
+
|
|
111
|
+
- "帮我从零设计一个 Python CLI"
|
|
112
|
+
- "帮我审查这个 Typer CLI"
|
|
113
|
+
- "这个 CLI 的交互很别扭,帮我重构"
|
|
114
|
+
- "帮我设计模型配置、缓存、doctor、profile memory"
|
|
115
|
+
- "帮我发布一个可 pip install 的 CLI"
|
|
116
|
+
|
|
117
|
+
## Sources And Design Influences
|
|
118
|
+
|
|
119
|
+
This skill distills practical lessons from building interactive Python CLIs and from studying mature CLI projects and documentation patterns, including:
|
|
120
|
+
|
|
121
|
+
- [larksuite/cli](https://github.com/larksuite/cli)
|
|
122
|
+
- [soongenwong/claudecode](https://github.com/soongenwong/claudecode)
|
|
123
|
+
- [Astral uv](https://github.com/astral-sh/uv)
|
|
124
|
+
- [Astral ruff](https://github.com/astral-sh/ruff)
|
|
125
|
+
- Typer, Rich, questionary, Pydantic, litellm, and instructor project practices
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
cli_creator_skill/__init__.py,sha256=7tSbeov-Nzm1Y499GNsAEqJUftdzMfNdOPET4esn_Cw,74
|
|
2
|
+
cli_creator_skill/__main__.py,sha256=Cnfu30AwCdIIm7aEj0BASh8PFoVyJsQcOewAbkmrtGU,68
|
|
3
|
+
cli_creator_skill/installer.py,sha256=QIInZSxgPBJ2Xz7cTF9psmrqSlfD7g38K9wGRxjUhew,1901
|
|
4
|
+
cli_creator_skill/skills/cli-creator/SKILL.md,sha256=5XAtMcFZAOXQtpDJFLLObKGITGw9DdWksfaEinEJc5o,11807
|
|
5
|
+
cli_creator_skill/skills/cli-creator/references/creation-playbook.md,sha256=IEwI_9zmmtc6REMuzcOlkINjXEGJfNduOXk0LF49Kjw,6444
|
|
6
|
+
cli_creator_skill/skills/cli-creator/references/pitfalls-and-solutions.md,sha256=Gg7FWHFbFKzzZw-W3J81qaNSz0sE2jDAhE-K5ICGUp4,9324
|
|
7
|
+
cli_creator_skill/skills/cli-creator/references/review-rubric.md,sha256=Hd5Tr-cehdD0GK2S4EZmDy8H1LB_j5M7VrDWfsEsYPQ,5204
|
|
8
|
+
cli_creator_skill-0.1.0.dist-info/METADATA,sha256=CCppR9bpaqWruLEXu3tWjxgtcS3PT4mJ-e7o14btaKU,4014
|
|
9
|
+
cli_creator_skill-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
10
|
+
cli_creator_skill-0.1.0.dist-info/entry_points.txt,sha256=bH_N0foJtwUyJQ2XYXhQQ5EqFy6dhnA7efWxQWacuHc,71
|
|
11
|
+
cli_creator_skill-0.1.0.dist-info/licenses/LICENSE,sha256=Tp84I2PKkZjKSunDQaJIH1fm6iLWSluvk-ejVBiYWq0,1060
|
|
12
|
+
cli_creator_skill-0.1.0.dist-info/licenses/NOTICE.md,sha256=SBDg7TQ9EpYtzo-bFUtJV0mmOwZRGb9Z7JteUd3IE1I,213
|
|
13
|
+
cli_creator_skill-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 yjw
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|