help2skill 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.
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.5
2
+ Name: help2skill
3
+ Version: 0.1.0
4
+ Summary: Make Python CLIs ready for LLM agents: --llms output, SKILL.md generation and drift checks for Click, Typer and argparse.
5
+ Project-URL: Homepage, https://github.com/huysonmind/help2skill
6
+ Project-URL: Issues, https://github.com/huysonmind/help2skill/issues
7
+ Project-URL: Changelog, https://github.com/huysonmind/help2skill/blob/main/CHANGELOG.md
8
+ Author-email: huysonmind <350970572+huysonmind@users.noreply.github.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agent-skills,agents,argparse,cli,click,llm,llms-txt,skill-md,typer
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Topic :: Software Development :: Documentation
18
+ Classifier: Topic :: Software Development :: User Interfaces
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+
23
+ # help2skill
24
+
25
+ > **Status: alpha.** The output format may still change before 1.0.
26
+
27
+ `--help` for LLM agents. Make a Click, Typer or argparse CLI easy for coding agents
28
+ (Claude Code, Codex, Cursor, Gemini CLI…) to use correctly:
29
+
30
+ - **`--llms` flag**: prints a compact Markdown reference of the command tree (every
31
+ subcommand, argument, option, choice, default and env var), generated from the CLI
32
+ itself, so it never goes stale.
33
+ - **`SKILL.md` export**: writes an [Agent Skills](https://agentskills.io) file whose
34
+ reference block is regenerated from the CLI while your hand-written guidance is kept.
35
+ - **Drift check for CI**: fails when the generated block is stale, or when hand-written
36
+ examples mention a subcommand or option that does not exist (or an option placed at
37
+ the wrong level, e.g. a group option after the subcommand).
38
+
39
+ No runtime dependencies. Works with Typer ≥ 0.26 (vendored Click), where code that does
40
+ `isinstance(cmd, click.Group)` silently finds nothing.
41
+
42
+ ## Quick start
43
+
44
+ ### Click
45
+
46
+ ```python
47
+ import click
48
+ from help2skill.click import llms_option
49
+
50
+
51
+ @click.group()
52
+ @llms_option()
53
+ def cli(): ...
54
+ ```
55
+
56
+ ```console
57
+ $ mytool --llms
58
+ ```
59
+
60
+ `llms_option()` adds the flag to the root only, which prints the whole tree. To get
61
+ `--llms` on every subcommand too (`mytool db --llms` prints just that subtree):
62
+
63
+ ```python
64
+ from help2skill.click import add_llms_option
65
+
66
+ add_llms_option(cli)
67
+ ```
68
+
69
+ ### Typer
70
+
71
+ Root flag, no change to your entry point:
72
+
73
+ ```python
74
+ import typer
75
+ from help2skill.typer import LlmsOption
76
+
77
+ app = typer.Typer()
78
+
79
+
80
+ @app.callback()
81
+ def main(llms: LlmsOption = False): ...
82
+ ```
83
+
84
+ Or `--llms` at every level: build the command once and make it your console script.
85
+
86
+ ```python
87
+ # mytool/cli.py
88
+ import help2skill.typer
89
+
90
+ main = help2skill.typer.command(app, name="mytool")
91
+ ```
92
+
93
+ ```toml
94
+ # pyproject.toml
95
+ [project.scripts]
96
+ mytool = "mytool.cli:main"
97
+ ```
98
+
99
+ No `click` package is needed with Typer ≥ 0.26, which ships its own copy.
100
+
101
+ ### argparse
102
+
103
+ argparse has no hook for an extra flag, so use the command line (or the Python API):
104
+
105
+ ```console
106
+ $ help2skill markdown mytool.cli:parser
107
+ $ help2skill markdown "mytool.cli:build_parser()" # a function that returns the parser
108
+ ```
109
+
110
+ ### Large CLIs
111
+
112
+ `--llms` prints the full reference when it fits in 20,000 characters (about 5k tokens).
113
+ Above that it prints the top-level help plus an index of every command, and tells the
114
+ agent how to ask for one command (`mytool <command> --llms`, or `--help` when only the
115
+ root has the flag). Set `HELP2SKILL_LLMS_MAX_CHARS=0` for everything. Options repeated
116
+ identically in three or more commands are described once, under "Shared options".
117
+
118
+ ### Lazy commands
119
+
120
+ Click's documented `LazyGroup` pattern works as is. Placeholder commands with a
121
+ `materialize()` method are loaded automatically; for anything else pass
122
+ `resolve=` (Python API) or `--resolve module:func` (command line).
123
+
124
+ ## SKILL.md and drift checks
125
+
126
+ ```console
127
+ $ help2skill skill mytool.cli:app --name mytool --description "Use mytool to ..." \
128
+ -o src/mytool/.agents/skills/mytool/SKILL.md
129
+ $ help2skill check mytool.cli:app src/mytool/.agents/skills/mytool/SKILL.md
130
+ ```
131
+
132
+ `skill` creates the file, or refreshes only the block between
133
+ `<!-- help2skill:begin … -->` and `<!-- help2skill:end -->` if it already exists
134
+ (`--name` is then optional). Write your own guidance above or below the block.
135
+
136
+ **Program name.** Commands are written with the name users type. help2skill uses
137
+ `--program` if given, else the installed console script that points at the target,
138
+ else the CLI's own name (`@click.group(name="mytool")`, `ArgumentParser(prog="mytool")`),
139
+ else the skill name. `markdown` warns when it can only guess.
140
+
141
+ **Settings are stored in the file.** The begin marker records the program name,
142
+ `--max-chars` and `--hide-default`, so `check`, a refresh and the pytest helper reuse
143
+ them without repeating any option.
144
+
145
+ **Stable in CI.** The output does not depend on the machine or on the Click/Typer
146
+ version: commands are sorted, type names are normalised and your home directory is
147
+ written as `~` (other machine-specific paths trigger a warning). A default computed at
148
+ run time (CPU count, today's date) would still differ, so leave it out:
149
+
150
+ ```console
151
+ $ help2skill skill mytool.cli:app -o SKILL.md --hide-default workers --hide-default --since
152
+ ```
153
+
154
+ When the reference is longer than 30,000 characters, `SKILL.md` keeps an index and the
155
+ full reference goes to `references/commands.md` beside it (fully generated; agents read
156
+ it on demand). Change the limit with `--max-chars` (0 = never split).
157
+
158
+ **What the check catches** in code spans and fenced blocks of your hand-written text:
159
+ unknown subcommands and options (with "did you mean"), options at the wrong level,
160
+ values not among an option's or argument's choices, values given to flags, and
161
+ single-letter clusters such as `-fq`. Lines continued with `\` are joined, and lines
162
+ are recognised with launchers in front: `uv run [--with …] mytool …`, `uvx`,
163
+ `pipx run`, `poetry run`, `python -m mytool`, `VAR=value mytool …`.
164
+
165
+ Shipping the skill inside your package under `.agents/skills/<name>/` makes it
166
+ installable with [library-skills](https://github.com/tiangolo/library-skills). With
167
+ setuptools, add the folder to `package-data`; hatchling includes it by default.
168
+
169
+ In pytest (build the path from `__file__` so the test runs from any directory):
170
+
171
+ ```python
172
+ from pathlib import Path
173
+
174
+ from help2skill.testing import assert_skill_in_sync
175
+ from mytool.cli import app
176
+
177
+ SKILL = Path(__file__).parents[1] / "src/mytool/.agents/skills/mytool/SKILL.md"
178
+
179
+
180
+ def test_skill_in_sync():
181
+ assert_skill_in_sync(app, SKILL)
182
+ ```
183
+
184
+ With a `src/` layout that is not installed, pass `--app-dir src` to the command line.
185
+
186
+ ## Python API
187
+
188
+ ```python
189
+ import help2skill
190
+
191
+ tree = help2skill.introspect(app, "mytool") # Click, Typer or argparse
192
+ print(help2skill.render_markdown(tree))
193
+ help2skill.write_skill(app, "SKILL.md", name="mytool")
194
+ problems = help2skill.check_skill_file(app, "SKILL.md")
195
+ ```
196
+
197
+ ## Security
198
+
199
+ `help2skill` imports the module you point it at, the same as running your CLI. It calls
200
+ a function only when you write `module:func()` or the function's name contains
201
+ "parser"; it never calls your `main()`. Generated files copy your help text verbatim, so review them
202
+ for machine-specific values before committing. See [SECURITY.md](https://github.com/huysonmind/help2skill/blob/main/SECURITY.md).
203
+
204
+ ## License
205
+
206
+ [MIT](https://github.com/huysonmind/help2skill/blob/main/LICENSE). Built with AI assistance (Claude).
@@ -0,0 +1,18 @@
1
+ help2skill/__init__.py,sha256=Bqc3NtdXN1EqOc2cqps5b9AWZwu1f969MlNJ8a9-Xuw,8687
2
+ help2skill/__main__.py,sha256=k1ocEWawweo1qCJWNFAAvyxz3tcY13dzvCenHszij30,48
3
+ help2skill/_argparse.py,sha256=x58Yc7Dzc9WRp4e64JpsyXfvP3jLe_r-6l5K4xhWWrM,6262
4
+ help2skill/_click.py,sha256=BbpK2BercOkat9Y98m_F7vGxXBg2u5-3huO8dCcug94,8945
5
+ help2skill/cli.py,sha256=0Fn6nmtFLq1TEIBWPdwJ7JdwqaAxaZr9KQmkZDGf6qE,10030
6
+ help2skill/click.py,sha256=0TWSFvzgY2d2SXpoG9TjdV5kdPzj1K5wnykF0mbLmcw,2968
7
+ help2skill/model.py,sha256=aVmDl-fp4EtZSC8bxpswSedduxDlmnQi2TvOzXbjD54,3021
8
+ help2skill/privacy.py,sha256=OdeL59R2E7ltWaPug0Z0u3SkMpy_dHhRYqPKym1YKLM,1234
9
+ help2skill/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ help2skill/render.py,sha256=hZpruGwot5pjoOzCUh_flTpCpPVpCFb0AnlAgj6ZfWs,9933
11
+ help2skill/sync.py,sha256=0Jccq8UHNrCH-gJ1uVp5eFybQNTdlAG9PsMLdR0-VAA,17391
12
+ help2skill/testing.py,sha256=66f0LeEyihN9a0FnMbIWIPHq0fDzedXGD8h-amVhwPs,1235
13
+ help2skill/typer.py,sha256=dieYYFdtz14qPevPrrs0TBOpvt9Z3UaCsZq1OzOYpyE,1034
14
+ help2skill-0.1.0.dist-info/METADATA,sha256=UBLJ2RqGsxVjIadNRPEiKo_BIkb4l3RZ4k_QAzOaPpQ,7569
15
+ help2skill-0.1.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
16
+ help2skill-0.1.0.dist-info/entry_points.txt,sha256=ozWOfUQCiT1o6LodAg9x8Z6Bwoh4u8-HXHowgi_wbCk,51
17
+ help2skill-0.1.0.dist-info/licenses/LICENSE,sha256=6sVsij8RLQMer7EYynJVovhnk1ESme1Eh5KokDX0Gg8,1067
18
+ help2skill-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.33.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ help2skill = help2skill.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 huysonmind
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.