simplicio-cli 0.2.9__tar.gz → 0.2.12__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. {simplicio_cli-0.2.9/simplicio_cli.egg-info → simplicio_cli-0.2.12}/PKG-INFO +77 -1
  2. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/README.md +76 -0
  3. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/pyproject.toml +6 -2
  4. simplicio_cli-0.2.12/simplicio/cli.py +120 -0
  5. simplicio_cli-0.2.12/simplicio/detect.py +139 -0
  6. simplicio_cli-0.2.12/simplicio/init.py +168 -0
  7. simplicio_cli-0.2.12/simplicio/templates/SKILL.md +169 -0
  8. simplicio_cli-0.2.12/simplicio/templates/userpromptsubmit-hook.sh +22 -0
  9. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12/simplicio_cli.egg-info}/PKG-INFO +77 -1
  10. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio_cli.egg-info/SOURCES.txt +4 -0
  11. simplicio_cli-0.2.9/simplicio/cli.py +0 -43
  12. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/LICENSE +0 -0
  13. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/setup.cfg +0 -0
  14. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/__init__.py +0 -0
  15. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/bench.py +0 -0
  16. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/cache.py +0 -0
  17. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/pipeline.py +0 -0
  18. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/precedent.py +0 -0
  19. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/prompt.py +0 -0
  20. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/providers.py +0 -0
  21. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/skill_router.py +0 -0
  22. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio/templates/simplicio_prompt.md +0 -0
  23. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio_cli.egg-info/dependency_links.txt +0 -0
  24. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio_cli.egg-info/entry_points.txt +0 -0
  25. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio_cli.egg-info/requires.txt +0 -0
  26. {simplicio_cli-0.2.9 → simplicio_cli-0.2.12}/simplicio_cli.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simplicio-cli
3
- Version: 0.2.9
3
+ Version: 0.2.12
4
4
  Summary: Portable task-to-code pipeline that works with any LLM. Turn a one-line task into a verified code change — diff + test + verify loop. +55 pts on a 156-check benchmark, 21% faster, ~same tokens.
5
5
  Author-email: Wesley Simplicio <wesleybob4@gmail.com>
6
6
  License: MIT
@@ -163,6 +163,82 @@ pip install simplicio-cli # from PyPI
163
163
  pip install -e . # from this repo
164
164
  ```
165
165
 
166
+ ### Auto-activation in Claude Code (often zero-step)
167
+
168
+ `pip install` puts `simplicio` on your PATH. To make Claude Code
169
+ **automatically** route code-edit tasks through simplicio, a skill + hook
170
+ need to land in `~/.claude/`.
171
+
172
+ **Zero-step path (recommended).** The first time you run *any* `simplicio`
173
+ command after install, if Claude Code is present (`~/.claude/` exists) and
174
+ the hook is missing, simplicio installs both for you and prints one stderr
175
+ line. PEP 517 wheels can't execute code on `pip install`, so this is the
176
+ closest equivalent that works on every machine.
177
+
178
+ ```bash
179
+ pip install simplicio-cli
180
+ simplicio smoke # ← first call also installs skill + hook (idempotent)
181
+ # stderr: "simplicio: auto-activation installed in Claude Code …"
182
+ ```
183
+
184
+ Opt out before the first call:
185
+
186
+ ```bash
187
+ export SIMPLICIO_SKIP_AUTO_INIT=1
188
+ ```
189
+
190
+ **Explicit path.** Same effect, no auto-magic:
191
+
192
+ ```bash
193
+ simplicio init # idempotent
194
+ simplicio init --dry-run # preview only
195
+ simplicio init --claude-home <path> # override target dir
196
+ ```
197
+
198
+ Either way, two files land in `~/.claude/`:
199
+
200
+ | File | Purpose |
201
+ |---|---|
202
+ | `~/.claude/skills/simplicio-cli/SKILL.md` | Skill the agent matches by description when your prompt looks like a code edit |
203
+ | `~/.claude/hooks/simplicio-userpromptsubmit.sh` + entry in `~/.claude/settings.json` | UserPromptSubmit hook that runs `simplicio detect` on every prompt and injects a hint when the heuristic catches a code-edit task the skill could miss |
204
+
205
+ A backup of your previous `settings.json` is written to `settings.json.bak`
206
+ before any merge.
207
+
208
+ ### How it works at runtime
209
+
210
+ After install, every prompt you type in Claude Code flows through two layers:
211
+
212
+ 1. **Skill layer (semantic).** Claude reads the SKILL.md description. When
213
+ your prompt looks like a programming task ("add X to Y.tsx", "fix the auth
214
+ bug in middleware.py"), Claude considers using `simplicio task` instead of
215
+ writing code directly.
216
+ 2. **Hook layer (deterministic).** Every prompt fires `simplicio detect` via
217
+ the UserPromptSubmit hook. The classifier scores the prompt (verbs + file
218
+ extensions + code nouns − read-only cues). Score ≥ 3 → it emits a
219
+ `[SIMPLICIO_PROMPT_HINT]` block on stderr. Claude sees the hint alongside
220
+ your prompt — a hard nudge toward `simplicio task <prompt> <repo>`.
221
+
222
+ The layers are complementary. Skill = "Claude *might* pick simplicio". Hook
223
+ = "Claude *sees* the hint regardless".
224
+
225
+ ### Why UserPromptSubmit and not PreToolUse
226
+
227
+ UserPromptSubmit fires **once, before Claude decides which tool to call** —
228
+ exactly when we want to steer. PreToolUse fires *after* the decision is made,
229
+ and again for every tool call in the turn, with no access to the original
230
+ user prompt. UserPromptSubmit is the right pre-hook for routing decisions.
231
+
232
+ ### Disable / re-enable
233
+
234
+ | Goal | How |
235
+ |---|---|
236
+ | Block the auto-bootstrap | `export SIMPLICIO_SKIP_AUTO_INIT=1` before the first `simplicio` call |
237
+ | Disable hook permanently | Delete `~/.claude/hooks/simplicio-userpromptsubmit.sh` and its entry in `~/.claude/settings.json` |
238
+ | Re-install / repair | `simplicio init` (idempotent — won't double-write) |
239
+ | Preview without writing | `simplicio init --dry-run` |
240
+ | Skill-only (no hook) | Copy `.skills/simplicio-cli/SKILL.md` to `~/.claude/skills/simplicio-cli/SKILL.md` manually, skip `simplicio init` |
241
+
166
242
  ## Configure — any LLM, nothing hardcoded
167
243
 
168
244
  | Provider | SIMPLICIO_MODEL | SIMPLICIO_BASE_URL |
@@ -126,6 +126,82 @@ pip install simplicio-cli # from PyPI
126
126
  pip install -e . # from this repo
127
127
  ```
128
128
 
129
+ ### Auto-activation in Claude Code (often zero-step)
130
+
131
+ `pip install` puts `simplicio` on your PATH. To make Claude Code
132
+ **automatically** route code-edit tasks through simplicio, a skill + hook
133
+ need to land in `~/.claude/`.
134
+
135
+ **Zero-step path (recommended).** The first time you run *any* `simplicio`
136
+ command after install, if Claude Code is present (`~/.claude/` exists) and
137
+ the hook is missing, simplicio installs both for you and prints one stderr
138
+ line. PEP 517 wheels can't execute code on `pip install`, so this is the
139
+ closest equivalent that works on every machine.
140
+
141
+ ```bash
142
+ pip install simplicio-cli
143
+ simplicio smoke # ← first call also installs skill + hook (idempotent)
144
+ # stderr: "simplicio: auto-activation installed in Claude Code …"
145
+ ```
146
+
147
+ Opt out before the first call:
148
+
149
+ ```bash
150
+ export SIMPLICIO_SKIP_AUTO_INIT=1
151
+ ```
152
+
153
+ **Explicit path.** Same effect, no auto-magic:
154
+
155
+ ```bash
156
+ simplicio init # idempotent
157
+ simplicio init --dry-run # preview only
158
+ simplicio init --claude-home <path> # override target dir
159
+ ```
160
+
161
+ Either way, two files land in `~/.claude/`:
162
+
163
+ | File | Purpose |
164
+ |---|---|
165
+ | `~/.claude/skills/simplicio-cli/SKILL.md` | Skill the agent matches by description when your prompt looks like a code edit |
166
+ | `~/.claude/hooks/simplicio-userpromptsubmit.sh` + entry in `~/.claude/settings.json` | UserPromptSubmit hook that runs `simplicio detect` on every prompt and injects a hint when the heuristic catches a code-edit task the skill could miss |
167
+
168
+ A backup of your previous `settings.json` is written to `settings.json.bak`
169
+ before any merge.
170
+
171
+ ### How it works at runtime
172
+
173
+ After install, every prompt you type in Claude Code flows through two layers:
174
+
175
+ 1. **Skill layer (semantic).** Claude reads the SKILL.md description. When
176
+ your prompt looks like a programming task ("add X to Y.tsx", "fix the auth
177
+ bug in middleware.py"), Claude considers using `simplicio task` instead of
178
+ writing code directly.
179
+ 2. **Hook layer (deterministic).** Every prompt fires `simplicio detect` via
180
+ the UserPromptSubmit hook. The classifier scores the prompt (verbs + file
181
+ extensions + code nouns − read-only cues). Score ≥ 3 → it emits a
182
+ `[SIMPLICIO_PROMPT_HINT]` block on stderr. Claude sees the hint alongside
183
+ your prompt — a hard nudge toward `simplicio task <prompt> <repo>`.
184
+
185
+ The layers are complementary. Skill = "Claude *might* pick simplicio". Hook
186
+ = "Claude *sees* the hint regardless".
187
+
188
+ ### Why UserPromptSubmit and not PreToolUse
189
+
190
+ UserPromptSubmit fires **once, before Claude decides which tool to call** —
191
+ exactly when we want to steer. PreToolUse fires *after* the decision is made,
192
+ and again for every tool call in the turn, with no access to the original
193
+ user prompt. UserPromptSubmit is the right pre-hook for routing decisions.
194
+
195
+ ### Disable / re-enable
196
+
197
+ | Goal | How |
198
+ |---|---|
199
+ | Block the auto-bootstrap | `export SIMPLICIO_SKIP_AUTO_INIT=1` before the first `simplicio` call |
200
+ | Disable hook permanently | Delete `~/.claude/hooks/simplicio-userpromptsubmit.sh` and its entry in `~/.claude/settings.json` |
201
+ | Re-install / repair | `simplicio init` (idempotent — won't double-write) |
202
+ | Preview without writing | `simplicio init --dry-run` |
203
+ | Skill-only (no hook) | Copy `.skills/simplicio-cli/SKILL.md` to `~/.claude/skills/simplicio-cli/SKILL.md` manually, skip `simplicio init` |
204
+
129
205
  ## Configure — any LLM, nothing hardcoded
130
206
 
131
207
  | Provider | SIMPLICIO_MODEL | SIMPLICIO_BASE_URL |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "simplicio-cli"
3
- version = "0.2.9"
3
+ version = "0.2.12"
4
4
  description = "Portable task-to-code pipeline that works with any LLM. Turn a one-line task into a verified code change — diff + test + verify loop. +55 pts on a 156-check benchmark, 21% faster, ~same tokens."
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -68,4 +68,8 @@ where = ["."]
68
68
  include = ["simplicio*"]
69
69
 
70
70
  [tool.setuptools.package-data]
71
- simplicio = ["templates/*.md"]
71
+ simplicio = ["templates/*.md", "templates/*.sh"]
72
+
73
+ [tool.pytest.ini_options]
74
+ pythonpath = ["."]
75
+ testpaths = ["tests/python"]
@@ -0,0 +1,120 @@
1
+ """cli.py — commands: index, task, bench, smoke, init, detect.
2
+
3
+ Heavy imports (numpy, sentence-transformers, openai/anthropic SDKs) are lazy so
4
+ that lightweight commands (`init`, `detect`, `--help`) don't pay for them.
5
+
6
+ First-run auto-bootstrap: if Claude Code (`~/.claude/`) is present and the
7
+ UserPromptSubmit hook is missing, the first `simplicio` invocation installs
8
+ the skill + hook automatically. Opt-out via `SIMPLICIO_SKIP_AUTO_INIT=1`.
9
+ PEP 517 wheels can't run code on `pip install`, so the bootstrap happens on
10
+ first CLI use instead — the closest equivalent that works on every machine.
11
+ """
12
+ from __future__ import annotations
13
+
14
+ import argparse
15
+ import os
16
+ import sys
17
+ from pathlib import Path
18
+
19
+
20
+ def maybe_autoinstall(cmd: str | None) -> bool:
21
+ """Install skill + hook on first run when Claude Code is detected.
22
+
23
+ Returns True iff install actually wrote files. Silent no-op on every
24
+ short-circuit so the CLI never breaks because of auto-activation.
25
+ """
26
+ if os.environ.get("SIMPLICIO_SKIP_AUTO_INIT"):
27
+ return False
28
+ if cmd in ("init", "detect"):
29
+ return False
30
+ claude_home = Path.home() / ".claude"
31
+ if not claude_home.is_dir():
32
+ return False
33
+ hook_path = claude_home / "hooks" / "simplicio-userpromptsubmit.sh"
34
+ if hook_path.exists():
35
+ return False
36
+ try:
37
+ from .init import install
38
+ report = install(claude_home=claude_home, dry_run=False)
39
+ except Exception as e:
40
+ print(f"simplicio: auto-activation skipped ({e})", file=sys.stderr)
41
+ return False
42
+ if report.skill_installed or report.hook_script_installed or report.settings_updated:
43
+ print(
44
+ "simplicio: auto-activation installed in Claude Code "
45
+ "(skill + UserPromptSubmit hook). "
46
+ "Disable next time with SIMPLICIO_SKIP_AUTO_INIT=1.",
47
+ file=sys.stderr,
48
+ )
49
+ return True
50
+ return False
51
+
52
+
53
+ def main():
54
+ ap = argparse.ArgumentParser(prog="simplicio")
55
+ sub = ap.add_subparsers(dest="cmd", required=True)
56
+
57
+ pi = sub.add_parser("index", help="index/cache the repo (once, or after changes)")
58
+ pi.add_argument("--root", default="."); pi.add_argument("--stack", default="angular")
59
+
60
+ pt = sub.add_parser("task", help="run a task")
61
+ pt.add_argument("goal")
62
+ pt.add_argument("--root", default="."); pt.add_argument("--stack", default="angular")
63
+ pt.add_argument("--target", required=True)
64
+ pt.add_argument("--criteria", default="- true state\n- false state")
65
+ pt.add_argument("--constraints", default="- build passes")
66
+
67
+
68
+ pb = sub.add_parser("bench", help="compare with vs without (real numbers)")
69
+ pb.add_argument("--root", default="."); pb.add_argument("--stack", default="angular")
70
+ pb.add_argument("--cases", default="bench/cases.json")
71
+
72
+
73
+ sub.add_parser("smoke", help="one proof call: connect+generate (needs SIMPLICIO_MODEL+KEY)")
74
+
75
+ p_init = sub.add_parser("init", help="install skill + UserPromptSubmit hook into ~/.claude/")
76
+ p_init.add_argument("--claude-home", help="override ~/.claude (for tests)")
77
+ p_init.add_argument("--dry-run", action="store_true")
78
+
79
+ p_det = sub.add_parser("detect", help="heuristic: is a prompt a code-edit task? (used by hook)")
80
+ p_det.add_argument("--prompt", help="prompt text (default: read from stdin)")
81
+ p_det.add_argument("--quiet", action="store_true")
82
+ p_det.add_argument("--json", action="store_true")
83
+
84
+ a = ap.parse_args()
85
+ maybe_autoinstall(a.cmd)
86
+ if a.cmd == "index":
87
+ from .precedent import index_repo
88
+ index_repo(a.root, a.stack)
89
+ elif a.cmd == "smoke":
90
+ from .providers import generate, info
91
+ print("provider:", info())
92
+ out = generate("Reply exactly: OK simplicio connected.")
93
+ print("model reply:", out.strip()[:200])
94
+ elif a.cmd == "bench":
95
+ from .bench import run_bench
96
+ run_bench(a.root, a.stack, a.cases)
97
+ elif a.cmd == "init":
98
+ from .init import main as init_main
99
+ argv = []
100
+ if a.claude_home:
101
+ argv += ["--claude-home", a.claude_home]
102
+ if a.dry_run:
103
+ argv += ["--dry-run"]
104
+ return init_main(argv)
105
+ elif a.cmd == "detect":
106
+ from .detect import main as detect_main
107
+ argv = []
108
+ if a.prompt is not None:
109
+ argv += ["--prompt", a.prompt]
110
+ if a.quiet:
111
+ argv += ["--quiet"]
112
+ if a.json:
113
+ argv += ["--json"]
114
+ return detect_main(argv)
115
+ else:
116
+ from .pipeline import run
117
+ run(a.root, a.stack, a.goal, a.target, a.criteria, a.constraints)
118
+
119
+ if __name__ == "__main__":
120
+ main()
@@ -0,0 +1,139 @@
1
+ """detect.py — heuristic: is this prompt a small/medium code-edit task?
2
+
3
+ Used by the UserPromptSubmit hook (.claude/hooks/simplicio-userpromptsubmit.sh)
4
+ to print a PROMPT_HINT when the user asks for a code edit, nudging the agent to
5
+ invoke the simplicio-cli skill instead of editing by hand.
6
+
7
+ No LLM call. Pure regex/keyword. Cheap to run on every prompt.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ import re
12
+ import sys
13
+ from dataclasses import dataclass
14
+ from pathlib import Path
15
+
16
+ _EDIT_VERBS = (
17
+ # English
18
+ "add", "remove", "delete", "rename", "refactor", "fix", "patch", "update",
19
+ "change", "replace", "hide", "show", "validate", "implement", "wire", "inject",
20
+ "extract", "split", "rewrite", "tweak", "adjust", "introduce", "expose",
21
+ # Portuguese
22
+ "adicione", "adicionar", "remova", "remover", "renomeie", "renomear",
23
+ "corrija", "corrigir", "atualize", "atualizar", "altere", "alterar",
24
+ "esconda", "esconder", "mostre", "mostrar", "valide", "validar",
25
+ "implemente", "implementar", "troque", "trocar", "ajuste", "ajustar",
26
+ "ocultar", "exiba", "exibir", "criar", "crie",
27
+ )
28
+
29
+ _FILE_EXT_RE = re.compile(
30
+ r"\b[\w./-]+\.(?:py|ts|tsx|js|jsx|vue|svelte|go|rs|java|kt|cs|cpp|cc|h|hpp|"
31
+ r"rb|php|swift|dart|sql|md|yml|yaml|json|toml|sh|html|css|scss)\b",
32
+ re.IGNORECASE,
33
+ )
34
+
35
+ _CODE_NOUNS = (
36
+ "component", "endpoint", "route", "handler", "service", "controller",
37
+ "middleware", "guard", "model", "schema", "migration", "fixture", "test",
38
+ "spec", "validator", "selector", "store", "reducer", "action", "hook",
39
+ "directive", "pipe", "module", "function", "method", "class", "prop",
40
+ "field", "column", "button", "form", "input", "dropdown", "modal", "page",
41
+ "componente", "função", "funcao", "classe", "tela", "rota", "campo",
42
+ "botão", "botao", "formulário", "formulario",
43
+ )
44
+
45
+ _NEGATIVE_CUES = (
46
+ "what does", "explain", "how does", "why does", "what is",
47
+ "o que faz", "explique", "como funciona", "por que", "o que é",
48
+ "show me the", "list ", "list the",
49
+ )
50
+
51
+
52
+ @dataclass
53
+ class DetectResult:
54
+ is_code_task: bool
55
+ score: int
56
+ signals: list
57
+ hint: str
58
+
59
+
60
+ def detect(prompt: str) -> DetectResult:
61
+ if not prompt or not prompt.strip():
62
+ return DetectResult(False, 0, [], "")
63
+
64
+ lower = prompt.lower()
65
+ signals: list = []
66
+ score = 0
67
+
68
+ for cue in _NEGATIVE_CUES:
69
+ if lower.startswith(cue) or f" {cue} " in lower:
70
+ return DetectResult(False, 0, [f"negative_cue:{cue!r}"], "")
71
+
72
+ tokens = re.findall(r"[a-záàâãéêíóôõúç]+", lower)
73
+ verbs = [t for t in tokens if t in _EDIT_VERBS]
74
+ if verbs:
75
+ score += 2
76
+ signals.append(f"verb:{verbs[0]}")
77
+
78
+ file_match = _FILE_EXT_RE.search(prompt)
79
+ if file_match:
80
+ score += 2
81
+ signals.append(f"file:{file_match.group(0)}")
82
+
83
+ nouns = [n for n in _CODE_NOUNS if n in lower]
84
+ if nouns:
85
+ score += 1
86
+ signals.append(f"noun:{nouns[0]}")
87
+
88
+ if any(s in lower for s in ("$simplicio", "/simplicio", "use simplicio", "rode o simplicio", "via simplicio")):
89
+ score += 5
90
+ signals.append("explicit_invocation")
91
+
92
+ is_code = score >= 3
93
+ hint = _render_hint(prompt, signals) if is_code else ""
94
+ return DetectResult(is_code, score, signals, hint)
95
+
96
+
97
+ def _render_hint(prompt: str, signals: list) -> str:
98
+ target_hint = next((s.split(":", 1)[1] for s in signals if s.startswith("file:")), None)
99
+ target_line = f"target = {target_hint}" if target_hint else "target = <ask user or infer via Explore>"
100
+ return (
101
+ "[SIMPLICIO_PROMPT_HINT]\n"
102
+ "This prompt looks like a small/medium code edit. Before editing by hand,\n"
103
+ "invoke the simplicio-cli skill (it stacks precedent + skill-router + 6-layer\n"
104
+ "prompt + test + verify-loop and measurably boosts pass-rate).\n"
105
+ f" goal = {prompt.strip()[:120]}\n"
106
+ f" {target_line}\n"
107
+ f" signals = {', '.join(signals)}\n"
108
+ "[/SIMPLICIO_PROMPT_HINT]"
109
+ )
110
+
111
+
112
+ def main(argv=None) -> int:
113
+ import argparse
114
+
115
+ ap = argparse.ArgumentParser(prog="simplicio detect")
116
+ ap.add_argument("--prompt", help="prompt text (default: read from stdin)")
117
+ ap.add_argument("--quiet", action="store_true", help="suppress hint on stderr")
118
+ ap.add_argument("--json", action="store_true", help="emit JSON result on stdout")
119
+ args = ap.parse_args(argv)
120
+
121
+ prompt = args.prompt if args.prompt is not None else sys.stdin.read()
122
+ result = detect(prompt)
123
+
124
+ if args.json:
125
+ import json
126
+ print(json.dumps({
127
+ "is_code_task": result.is_code_task,
128
+ "score": result.score,
129
+ "signals": result.signals,
130
+ }))
131
+
132
+ if result.is_code_task and not args.quiet:
133
+ print(result.hint, file=sys.stderr)
134
+
135
+ return 0
136
+
137
+
138
+ if __name__ == "__main__":
139
+ raise SystemExit(main())
@@ -0,0 +1,168 @@
1
+ """init.py — install skill + UserPromptSubmit hook into ~/.claude/.
2
+
3
+ Idempotent: re-running upgrades the skill, re-installs the hook script, and
4
+ re-merges the settings.json hook entry without duplicating.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import json
9
+ import shutil
10
+ import stat
11
+ from dataclasses import dataclass
12
+ from pathlib import Path
13
+
14
+ try:
15
+ from importlib.resources import files as _res_files
16
+ except ImportError: # pragma: no cover
17
+ from importlib_resources import files as _res_files # type: ignore
18
+
19
+ HOOK_MARKER = "simplicio-userpromptsubmit"
20
+
21
+
22
+ @dataclass
23
+ class InstallReport:
24
+ claude_home: Path
25
+ skill_path: Path
26
+ hook_script_path: Path
27
+ settings_path: Path
28
+ skill_installed: bool
29
+ hook_script_installed: bool
30
+ settings_updated: bool
31
+ dry_run: bool
32
+
33
+
34
+ def install(claude_home=None, dry_run: bool = False) -> InstallReport:
35
+ home = Path(claude_home) if claude_home else Path.home() / ".claude"
36
+ skill_dir = home / "skills" / "simplicio-cli"
37
+ hooks_dir = home / "hooks"
38
+ settings_path = home / "settings.json"
39
+
40
+ skill_target = skill_dir / "SKILL.md"
41
+ hook_target = hooks_dir / "simplicio-userpromptsubmit.sh"
42
+
43
+ skill_src = _resource_text("SKILL.md")
44
+ hook_src = _resource_text("userpromptsubmit-hook.sh")
45
+
46
+ skill_changed = _file_differs(skill_target, skill_src)
47
+ hook_changed = _file_differs(hook_target, hook_src)
48
+ settings_changed, new_settings = _plan_settings_update(settings_path, hook_target)
49
+
50
+ if not dry_run:
51
+ home.mkdir(parents=True, exist_ok=True)
52
+ skill_dir.mkdir(parents=True, exist_ok=True)
53
+ hooks_dir.mkdir(parents=True, exist_ok=True)
54
+
55
+ if skill_changed:
56
+ skill_target.write_text(skill_src, encoding="utf-8")
57
+ if hook_changed:
58
+ hook_target.write_text(hook_src, encoding="utf-8")
59
+ hook_target.chmod(hook_target.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
60
+ if settings_changed:
61
+ if settings_path.exists():
62
+ shutil.copy2(settings_path, settings_path.with_suffix(".json.bak"))
63
+ settings_path.write_text(json.dumps(new_settings, indent=2) + "\n", encoding="utf-8")
64
+
65
+ return InstallReport(
66
+ claude_home=home,
67
+ skill_path=skill_target,
68
+ hook_script_path=hook_target,
69
+ settings_path=settings_path,
70
+ skill_installed=skill_changed,
71
+ hook_script_installed=hook_changed,
72
+ settings_updated=settings_changed,
73
+ dry_run=dry_run,
74
+ )
75
+
76
+
77
+ def _resource_text(name: str) -> str:
78
+ pkg = _res_files("simplicio") / "templates" / name
79
+ return pkg.read_text(encoding="utf-8")
80
+
81
+
82
+ def _file_differs(target: Path, new_content: str) -> bool:
83
+ if not target.exists():
84
+ return True
85
+ try:
86
+ return target.read_text(encoding="utf-8") != new_content
87
+ except OSError:
88
+ return True
89
+
90
+
91
+ def _plan_settings_update(settings_path: Path, hook_target: Path):
92
+ settings: dict = {}
93
+ if settings_path.exists():
94
+ try:
95
+ settings = json.loads(settings_path.read_text(encoding="utf-8"))
96
+ except json.JSONDecodeError:
97
+ return False, settings
98
+
99
+ if not isinstance(settings, dict):
100
+ return False, settings
101
+
102
+ hooks = settings.setdefault("hooks", {})
103
+ if not isinstance(hooks, dict):
104
+ return False, settings
105
+
106
+ entries = hooks.setdefault("UserPromptSubmit", [])
107
+ if not isinstance(entries, list):
108
+ return False, settings
109
+
110
+ command_str = str(hook_target)
111
+ already_present = any(
112
+ _entry_matches(e, command_str) for e in entries if isinstance(e, dict)
113
+ )
114
+ if already_present:
115
+ return False, settings
116
+
117
+ entries.append({
118
+ "matcher": "",
119
+ "hooks": [{
120
+ "type": "command",
121
+ "command": command_str,
122
+ }],
123
+ })
124
+ return True, settings
125
+
126
+
127
+ def _entry_matches(entry: dict, command_str: str) -> bool:
128
+ hooks = entry.get("hooks", [])
129
+ if not isinstance(hooks, list):
130
+ return False
131
+ for h in hooks:
132
+ if not isinstance(h, dict):
133
+ continue
134
+ cmd = h.get("command", "")
135
+ if HOOK_MARKER in cmd or cmd == command_str:
136
+ return True
137
+ return False
138
+
139
+
140
+ def main(argv=None) -> int:
141
+ import argparse
142
+
143
+ ap = argparse.ArgumentParser(
144
+ prog="simplicio init",
145
+ description="Install simplicio-cli skill + UserPromptSubmit hook into ~/.claude/",
146
+ )
147
+ ap.add_argument("--claude-home", help="override ~/.claude (for tests)")
148
+ ap.add_argument("--dry-run", action="store_true", help="show what would change, don't write")
149
+ args = ap.parse_args(argv)
150
+
151
+ home = Path(args.claude_home) if args.claude_home else None
152
+ report = install(claude_home=home, dry_run=args.dry_run)
153
+
154
+ print(f"claude_home: {report.claude_home}")
155
+ print(f"skill: {report.skill_path} ({'updated' if report.skill_installed else 'unchanged'})")
156
+ print(f"hook script: {report.hook_script_path} ({'updated' if report.hook_script_installed else 'unchanged'})")
157
+ print(f"settings.json: {report.settings_path} ({'updated' if report.settings_updated else 'unchanged'})")
158
+ if report.dry_run:
159
+ print("(dry-run — no files written)")
160
+ else:
161
+ print()
162
+ print("done. open a new Claude Code session — skill auto-fires on code-edit prompts,")
163
+ print("and the UserPromptSubmit hook prints a hint as a deterministic fallback.")
164
+ return 0
165
+
166
+
167
+ if __name__ == "__main__":
168
+ raise SystemExit(main())
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: simplicio-cli
3
+ description: Use simplicio-cli to turn a one-line task into a verified code change (diff + test + verify loop). Trigger ALWAYS when the user asks for a small/medium code edit in a known file — "hide X for non-admins", "add validation to Y", "fix the empty-state on Z", "rename the prop in <file>" — even if they do not mention the word "simplicio". Especially trigger when the active model is small/local (Ollama, Gemma, Llama 3 sub-8B, Phi, Qwen 7B), or the user mentions "task-to-code", "diff+test", "verify loop", "6-layer contract", "pass-rate", "precedent + skill router", or any of the benchmark numbers (+39 pts, +51 pts, +58 pts, 99% pass-rate). Use this skill BEFORE writing the edit by hand — simplicio-cli measurably boosts pass-rate on the same model from ~41% to ~99% on frontier and ~35% to ~74% on sub-4B by stacking mapper + precedent + skill-router + 6-layer prompt + test + verify-loop. Also trigger on explicit invocations: `$simplicio`, `/simplicio`, "use simplicio", "rode o simplicio".
4
+ ---
5
+
6
+ # Skill: `simplicio-cli`
7
+
8
+ Wrap a code task in simplicio-cli's 6-layer contract instead of asking the LLM to guess. Same model, same task — only the prompt structure changes. Measured: **+51 pts average gain across 14 models** (sub-4B to frontier 2026).
9
+
10
+ > Source: this repo (`simplicio-cli`, PyPI `simplicio-cli`, MIT, v0.2.10). See `README.md` for the full bench table and methodology, `docs/benchmark-4quadrant.md` for the 4-quadrant decomposition.
11
+
12
+ ---
13
+
14
+ ## When to trigger
15
+
16
+ **Always** when the user asks for a code edit that fits all of these:
17
+
18
+ - One concrete target file (or small set) the user named or you can resolve from `Explore`.
19
+ - Mensurable success criteria (button gone / validation rejects empty / endpoint returns 401).
20
+ - Stack is one of the indexed stacks (`angular`, `react`, `next`, `vue`, `django`, `laravel`, `springboot`, `nestjs`, `dotnet`, `flutter`, etc. — anything with skills under `SIMPLICIO_SKILLS_DIR`) or a generic edit (`--stack generic`).
21
+
22
+ **Also trigger** on:
23
+
24
+ - Small/local model active (Ollama, Gemma sub-8B, Llama 3 sub-8B, Phi, Qwen 7B) — simplicio adds the biggest absolute gain there (+39 pts to +58 pts).
25
+ - User explicitly says: `$simplicio`, `/simplicio`, "use simplicio", "rode o simplicio", "via simplicio-cli".
26
+ - User mentions verify-loop, 6-layer prompt, precedent injection, pass-rate, skill router, content-hash cache.
27
+
28
+ **Do NOT trigger** on:
29
+
30
+ - Pure read-only ask ("what does this function do?") — answer directly.
31
+ - Architectural decision / refactor amplo cross-file — that goes to `architect` agent + ADR.
32
+ - One-off shell command, lookup, install task.
33
+ - The user is already inside `ralph-loop` and explicitly wants edits by hand — respect.
34
+
35
+ ---
36
+
37
+ ## Steps
38
+
39
+ ### 1. Verify install + config
40
+
41
+ ```bash
42
+ # is simplicio on PATH?
43
+ command -v simplicio \
44
+ || pip install --user simplicio-cli \
45
+ || pip install -e . # fallback: editable install from repo root (locked venv / no PyPI)
46
+
47
+ # config check (one-shot, costs 1 LLM call)
48
+ simplicio smoke
49
+ ```
50
+
51
+ If `smoke` fails: set the env vars and retry. Read `~/.config/simplicio/.env` or current shell env. Required:
52
+
53
+ | Provider | `SIMPLICIO_MODEL` | `SIMPLICIO_BASE_URL` | Key env var |
54
+ |---|---|---|---|
55
+ | OpenRouter | `anthropic/claude-opus-4` (or any) | `https://openrouter.ai/api/v1` | `OPENROUTER_API_KEY` |
56
+ | GLM (z.ai) | `glm-4.6` | `https://api.z.ai/api/paas/v4` | `OPENAI_API_KEY` |
57
+ | DeepSeek | `deepseek-chat` | `https://api.deepseek.com` | `OPENAI_API_KEY` |
58
+ | OpenAI | `gpt-4.1` | `https://api.openai.com/v1` | `OPENAI_API_KEY` |
59
+ | Ollama local | `llama3` (or any) | `http://localhost:11434/v1` | `OPENAI_API_KEY=dummy` |
60
+ | Anthropic native | `claude-opus-4-7` | *(unset)* | `ANTHROPIC_API_KEY` |
61
+
62
+ `base_url` unset + `ANTHROPIC_API_KEY` present → native Anthropic SDK. Else OpenAI-compatible client.
63
+
64
+ ### 2. Index (cache warm-up)
65
+
66
+ First run on the repo (or after large changes): index once. Re-runs reuse embeddings keyed by content hash — unchanged blocks cost zero.
67
+
68
+ ```bash
69
+ simplicio index --stack <stack> # e.g. angular | react | django | dotnet | generic
70
+ ```
71
+
72
+ Skip if `.simplicio/` already exists and the affected files were not modified since last index (`ls .simplicio/ 2>/dev/null` non-empty → cache warm).
73
+
74
+ ### 3. Build the task call
75
+
76
+ Map the user's natural-language goal into the four flags:
77
+
78
+ | Flag | Meaning | Pull from |
79
+ |---|---|---|
80
+ | positional goal | one-line objective in user's words | the user's request |
81
+ | `--stack` | indexed stack name | detected from repo (look for `package.json`, `*.csproj`, `pyproject.toml`, `composer.json`, etc.) |
82
+ | `--target` | exact file path that holds the code to change | user said it, or `Explore` → grep for the affected symbol |
83
+ | `--criteria` | bullet list of mensurable success criteria | rephrase user's success into checkable bullets |
84
+ | `--constraints` | bullet list of guardrails | "don't touch X", "build still passes", "preserve public API" |
85
+
86
+ ### 4. Run the task
87
+
88
+ ```bash
89
+ simplicio task "<one-line goal>" \
90
+ --stack <stack> \
91
+ --target <path/to/file> \
92
+ --criteria "- <check 1>
93
+ - <check 2>" \
94
+ --constraints "- <guardrail 1>
95
+ - <guardrail 2>"
96
+ ```
97
+
98
+ simplicio internally: precedent (from cache) → skill match → stacks the 6 layers → LLM generates diff + test + Playwright → applies → runs `SIMPLICIO_TEST_CMD` → pass = done, fail = sends error back, fixes, retries up to 3×.
99
+
100
+ ### 5. Read the output
101
+
102
+ Output stream contains, in order:
103
+
104
+ 1. `MAPPER` — what file was identified as the target + neighbors.
105
+ 2. `PRECEDENT` — the in-repo snippet picked as the "this is how we already do it" example.
106
+ 3. `SKILL` — the one mapper skill matched and injected.
107
+ 4. `PROMPT` — the full 6-layer prompt sent (cache-friendly).
108
+ 5. `DIFF` — the patch the LLM emitted.
109
+ 6. `APPLY` — `git apply` result.
110
+ 7. `TEST` — `SIMPLICIO_TEST_CMD` exit code + stderr.
111
+ 8. `VERIFY` — pass/fail summary. If fail, loop up to 3× with the error appended.
112
+
113
+ > Canonical labels live in `simplicio/cli.py` — if the CLI output format changes, update this list against that file.
114
+
115
+ If `VERIFY: pass` → report to user with the diff and test artefacts. If `VERIFY: fail` after 3 retries → bubble up the last error + suggest splitting the task.
116
+
117
+ ### 6. Validate locally
118
+
119
+ Whatever the project's normal validation is — run it. The simplicio test command is a fast inner loop; the full project validation is the outer truth.
120
+
121
+ | Stack | Command |
122
+ |---|---|
123
+ | Node/TS | `npm run lint && npm test` |
124
+ | Python | `ruff check . && pytest` |
125
+ | .NET | `dotnet build && dotnet test` |
126
+ | Go | `go vet ./... && go test ./...` |
127
+ | Rust | `cargo clippy && cargo test` |
128
+
129
+ If it's a UI change, also run Playwright (`npx playwright test --reporter=list,html`) with trace + screenshot + video (this repo's hard DoD rule).
130
+
131
+ ---
132
+
133
+ ## Patterns
134
+
135
+ - **Relevant > complete** — never inject the whole file. simplicio's precedent layer already picks the *right* snippet; don't override with `--target` pointing at a 10k-line file unless it actually is the target.
136
+ - **Criteria as testable states** — "no admin perm: button absent from DOM" (testable). Not "button should be hidden properly" (vague).
137
+ - **Constraints bound the blast radius** — list what the LLM must NOT change ("save flow", "auth middleware", "public API of `UserService`"). Without constraints, models drift.
138
+ - **Stack `generic`** is fine for non-listed stacks — skips skill router but keeps mapper + precedent + 6-layer + test + verify.
139
+ - **Cache is content-hash keyed** — `.simplicio/` directory holds embeddings. Don't `.gitignore`-ignore it casually; sharing the cache speeds team runs.
140
+ - **Cost is real** — +61% input tokens, +24% wall-clock vs. raw prompt. Justified by **+58 pts pass-rate**. Don't use simplicio for a one-line typo fix — use it where pass-rate matters.
141
+
142
+ ---
143
+
144
+ ## Anti-patterns
145
+
146
+ - Running `simplicio task` without `--target` on an ambiguous goal → mapper guesses, often wrong on big repos.
147
+ - Passing `--criteria "make it work"` → no signal for the verify loop. Pass-rate collapses.
148
+ - Using simplicio inside a Ralph loop AND wrapping each Ralph step in simplicio → double-loop, confused state. Pick one: either Ralph drives and simplicio runs the `execute` step (use `.agents/simplicio-ralph.agent.md` composition), or simplicio runs standalone.
149
+ - Indexing `node_modules` / `.venv` / `target/` — bloats cache, slows precedent. Use `.simplicioignore` (same syntax as `.gitignore`).
150
+
151
+ ---
152
+
153
+ ## Definition of Done
154
+
155
+ - [ ] `simplicio smoke` returned a clean provider config print + one successful test call.
156
+ - [ ] `simplicio task ...` ran with `--stack` + `--target` + `--criteria` + `--constraints` all set.
157
+ - [ ] `VERIFY: pass` in the output, OR a clear "fail after 3 retries — escalate" message.
158
+ - [ ] Diff applied (`git diff` shows the change) and project's normal validation (lint + test) is green.
159
+ - [ ] If UI change: Playwright run with trace + screenshot + video saved to `playwright-report/`.
160
+ - [ ] User gets: the diff, the test command result, and a one-line summary of what changed.
161
+
162
+ ---
163
+
164
+ ## Notes
165
+
166
+ - **Composition with Ralph Loop**: see `.agents/simplicio-ralph.agent.md` — Ralph drives the outer `read → plan → execute → lint → unit → e2e → fix` loop, delegates the `execute` step to `simplicio task` instead of editing by hand. Best for tasks where Ralph's autonomy + simplicio's per-call precision compound.
167
+ - **Bench reproduction**: `python3 bench/run_offline.py` (no API key needed for the offline scoring), or `simplicio bench --cases bench/cases.json --stack <s>` for real-test pass-rate.
168
+ - **4-quadrant matrix**: `python3 bench/run_4quadrant.py` decomposes prompt-effect vs. loop-effect vs. composition. Q4 (simplicio + loop) wins on pass-rate AND stays close to Q2 on cost.
169
+ - **Plug points** if extending: `prompt.py::_mapper` (real mapper), `pipeline.py::_aplicar_e_testar` (real diff/test), `skill_router.py` (your skills dir via `SIMPLICIO_SKILLS_DIR`).
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+ # simplicio-userpromptsubmit — fires on every Claude Code UserPromptSubmit event.
3
+ #
4
+ # Reads the user prompt from CLAUDE_USER_PROMPT and pipes it to `simplicio
5
+ # detect`. If the heuristic decides it is a code-edit task, a PROMPT_HINT is
6
+ # printed to stderr nudging the agent to invoke the simplicio-cli skill. Always
7
+ # exits 0 — never blocks.
8
+ #
9
+ # Installed by `simplicio init`. Safe to delete to disable.
10
+ set -u
11
+
12
+ prompt="${CLAUDE_USER_PROMPT:-}"
13
+ if [ -z "$prompt" ]; then
14
+ exit 0
15
+ fi
16
+
17
+ if ! command -v simplicio >/dev/null 2>&1; then
18
+ exit 0
19
+ fi
20
+
21
+ printf '%s' "$prompt" | simplicio detect 2>&1 1>/dev/null || true
22
+ exit 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simplicio-cli
3
- Version: 0.2.9
3
+ Version: 0.2.12
4
4
  Summary: Portable task-to-code pipeline that works with any LLM. Turn a one-line task into a verified code change — diff + test + verify loop. +55 pts on a 156-check benchmark, 21% faster, ~same tokens.
5
5
  Author-email: Wesley Simplicio <wesleybob4@gmail.com>
6
6
  License: MIT
@@ -163,6 +163,82 @@ pip install simplicio-cli # from PyPI
163
163
  pip install -e . # from this repo
164
164
  ```
165
165
 
166
+ ### Auto-activation in Claude Code (often zero-step)
167
+
168
+ `pip install` puts `simplicio` on your PATH. To make Claude Code
169
+ **automatically** route code-edit tasks through simplicio, a skill + hook
170
+ need to land in `~/.claude/`.
171
+
172
+ **Zero-step path (recommended).** The first time you run *any* `simplicio`
173
+ command after install, if Claude Code is present (`~/.claude/` exists) and
174
+ the hook is missing, simplicio installs both for you and prints one stderr
175
+ line. PEP 517 wheels can't execute code on `pip install`, so this is the
176
+ closest equivalent that works on every machine.
177
+
178
+ ```bash
179
+ pip install simplicio-cli
180
+ simplicio smoke # ← first call also installs skill + hook (idempotent)
181
+ # stderr: "simplicio: auto-activation installed in Claude Code …"
182
+ ```
183
+
184
+ Opt out before the first call:
185
+
186
+ ```bash
187
+ export SIMPLICIO_SKIP_AUTO_INIT=1
188
+ ```
189
+
190
+ **Explicit path.** Same effect, no auto-magic:
191
+
192
+ ```bash
193
+ simplicio init # idempotent
194
+ simplicio init --dry-run # preview only
195
+ simplicio init --claude-home <path> # override target dir
196
+ ```
197
+
198
+ Either way, two files land in `~/.claude/`:
199
+
200
+ | File | Purpose |
201
+ |---|---|
202
+ | `~/.claude/skills/simplicio-cli/SKILL.md` | Skill the agent matches by description when your prompt looks like a code edit |
203
+ | `~/.claude/hooks/simplicio-userpromptsubmit.sh` + entry in `~/.claude/settings.json` | UserPromptSubmit hook that runs `simplicio detect` on every prompt and injects a hint when the heuristic catches a code-edit task the skill could miss |
204
+
205
+ A backup of your previous `settings.json` is written to `settings.json.bak`
206
+ before any merge.
207
+
208
+ ### How it works at runtime
209
+
210
+ After install, every prompt you type in Claude Code flows through two layers:
211
+
212
+ 1. **Skill layer (semantic).** Claude reads the SKILL.md description. When
213
+ your prompt looks like a programming task ("add X to Y.tsx", "fix the auth
214
+ bug in middleware.py"), Claude considers using `simplicio task` instead of
215
+ writing code directly.
216
+ 2. **Hook layer (deterministic).** Every prompt fires `simplicio detect` via
217
+ the UserPromptSubmit hook. The classifier scores the prompt (verbs + file
218
+ extensions + code nouns − read-only cues). Score ≥ 3 → it emits a
219
+ `[SIMPLICIO_PROMPT_HINT]` block on stderr. Claude sees the hint alongside
220
+ your prompt — a hard nudge toward `simplicio task <prompt> <repo>`.
221
+
222
+ The layers are complementary. Skill = "Claude *might* pick simplicio". Hook
223
+ = "Claude *sees* the hint regardless".
224
+
225
+ ### Why UserPromptSubmit and not PreToolUse
226
+
227
+ UserPromptSubmit fires **once, before Claude decides which tool to call** —
228
+ exactly when we want to steer. PreToolUse fires *after* the decision is made,
229
+ and again for every tool call in the turn, with no access to the original
230
+ user prompt. UserPromptSubmit is the right pre-hook for routing decisions.
231
+
232
+ ### Disable / re-enable
233
+
234
+ | Goal | How |
235
+ |---|---|
236
+ | Block the auto-bootstrap | `export SIMPLICIO_SKIP_AUTO_INIT=1` before the first `simplicio` call |
237
+ | Disable hook permanently | Delete `~/.claude/hooks/simplicio-userpromptsubmit.sh` and its entry in `~/.claude/settings.json` |
238
+ | Re-install / repair | `simplicio init` (idempotent — won't double-write) |
239
+ | Preview without writing | `simplicio init --dry-run` |
240
+ | Skill-only (no hook) | Copy `.skills/simplicio-cli/SKILL.md` to `~/.claude/skills/simplicio-cli/SKILL.md` manually, skip `simplicio init` |
241
+
166
242
  ## Configure — any LLM, nothing hardcoded
167
243
 
168
244
  | Provider | SIMPLICIO_MODEL | SIMPLICIO_BASE_URL |
@@ -5,12 +5,16 @@ simplicio/__init__.py
5
5
  simplicio/bench.py
6
6
  simplicio/cache.py
7
7
  simplicio/cli.py
8
+ simplicio/detect.py
9
+ simplicio/init.py
8
10
  simplicio/pipeline.py
9
11
  simplicio/precedent.py
10
12
  simplicio/prompt.py
11
13
  simplicio/providers.py
12
14
  simplicio/skill_router.py
15
+ simplicio/templates/SKILL.md
13
16
  simplicio/templates/simplicio_prompt.md
17
+ simplicio/templates/userpromptsubmit-hook.sh
14
18
  simplicio_cli.egg-info/PKG-INFO
15
19
  simplicio_cli.egg-info/SOURCES.txt
16
20
  simplicio_cli.egg-info/dependency_links.txt
@@ -1,43 +0,0 @@
1
- """cli.py — commands: index (cache repo), task (run pipeline), bench, smoke."""
2
- import argparse
3
- from .precedent import index_repo
4
- from .pipeline import run
5
- from .bench import run_bench
6
- from .providers import generate, info
7
-
8
- def main():
9
- ap = argparse.ArgumentParser(prog="simplicio")
10
- sub = ap.add_subparsers(dest="cmd", required=True)
11
-
12
- pi = sub.add_parser("index", help="index/cache the repo (once, or after changes)")
13
- pi.add_argument("--root", default="."); pi.add_argument("--stack", default="angular")
14
-
15
- pt = sub.add_parser("task", help="run a task")
16
- pt.add_argument("goal")
17
- pt.add_argument("--root", default="."); pt.add_argument("--stack", default="angular")
18
- pt.add_argument("--target", required=True)
19
- pt.add_argument("--criteria", default="- true state\n- false state")
20
- pt.add_argument("--constraints", default="- build passes")
21
-
22
-
23
- pb = sub.add_parser("bench", help="compare with vs without (real numbers)")
24
- pb.add_argument("--root", default="."); pb.add_argument("--stack", default="angular")
25
- pb.add_argument("--cases", default="bench/cases.json")
26
-
27
-
28
- sub.add_parser("smoke", help="one proof call: connect+generate (needs SIMPLICIO_MODEL+KEY)")
29
-
30
- a = ap.parse_args()
31
- if a.cmd == "index":
32
- index_repo(a.root, a.stack)
33
- elif a.cmd == "smoke":
34
- print("provider:", info())
35
- out = generate("Reply exactly: OK simplicio connected.")
36
- print("model reply:", out.strip()[:200])
37
- elif a.cmd == "bench":
38
- run_bench(a.root, a.stack, a.cases)
39
- else:
40
- run(a.root, a.stack, a.goal, a.target, a.criteria, a.constraints)
41
-
42
- if __name__ == "__main__":
43
- main()
File without changes
File without changes