boost-skill-cli 1.0.1__tar.gz → 1.0.4__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.
- boost_skill_cli-1.0.4/.gitignore +221 -0
- boost_skill_cli-1.0.4/CONTRIBUTING.md +39 -0
- boost_skill_cli-1.0.4/MANIFEST.in +12 -0
- boost_skill_cli-1.0.4/Makefile +47 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/PKG-INFO +19 -2
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/README.md +18 -1
- boost_skill_cli-1.0.4/SECURITY.md +22 -0
- boost_skill_cli-1.0.4/boost +39 -0
- boost_skill_cli-1.0.4/boost_cli/__init__.py +38 -0
- boost_skill_cli-1.0.4/boost_cli/_version.py +24 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/taps.py +66 -3
- boost_skill_cli-1.0.4/boost_cli/core/catalog.py +240 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/config.py +13 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/paths.py +5 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/store.py +8 -0
- boost_skill_cli-1.0.4/boost_cli/data/registries.json +1042 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/PKG-INFO +19 -2
- boost_skill_cli-1.0.4/boost_skill_cli.egg-info/SOURCES.txt +80 -0
- boost_skill_cli-1.0.4/docs/.claude/settings.local.json +11 -0
- boost_skill_cli-1.0.4/docs/demo.gif +0 -0
- boost_skill_cli-1.0.4/docs/demo.tape +36 -0
- boost_skill_cli-1.0.4/docs/overview.html +966 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/pyproject.toml +15 -3
- boost_skill_cli-1.0.4/scripts/build_registries.py +204 -0
- boost_skill_cli-1.0.4/scripts/mutation_gate.py +60 -0
- boost_skill_cli-1.0.4/tests/conftest.py +89 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_configuration.py +756 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_discovery.py +613 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_info.py +328 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_intelligence.py +510 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_pkg.py +719 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_quality.py +465 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_taps.py +288 -0
- boost_skill_cli-1.0.4/tests/functional/test_cli_team.py +462 -0
- boost_skill_cli-1.0.4/tests/functional/test_everyday_loop.py +66 -0
- boost_skill_cli-1.0.4/tests/make_fixture.py +146 -0
- boost_skill_cli-1.0.4/tests/smoke.sh +221 -0
- boost_skill_cli-1.0.4/tests/unit/test_agents.py +74 -0
- boost_skill_cli-1.0.4/tests/unit/test_ai.py +259 -0
- boost_skill_cli-1.0.4/tests/unit/test_catalog.py +453 -0
- boost_skill_cli-1.0.4/tests/unit/test_config.py +196 -0
- boost_skill_cli-1.0.4/tests/unit/test_errors_and_cli_table.py +229 -0
- boost_skill_cli-1.0.4/tests/unit/test_frontmatter.py +195 -0
- boost_skill_cli-1.0.4/tests/unit/test_gitutil.py +155 -0
- boost_skill_cli-1.0.4/tests/unit/test_journal.py +144 -0
- boost_skill_cli-1.0.4/tests/unit/test_lockfile.py +159 -0
- boost_skill_cli-1.0.4/tests/unit/test_mutation_hardening.py +243 -0
- boost_skill_cli-1.0.4/tests/unit/test_output.py +232 -0
- boost_skill_cli-1.0.4/tests/unit/test_paths.py +118 -0
- boost_skill_cli-1.0.4/tests/unit/test_policy.py +151 -0
- boost_skill_cli-1.0.4/tests/unit/test_registry.py +218 -0
- boost_skill_cli-1.0.4/tests/unit/test_store.py +371 -0
- boost_skill_cli-1.0.4/tests/unit/test_util.py +366 -0
- boost_skill_cli-1.0.4/tests/unit/test_version.py +50 -0
- boost_skill_cli-1.0.1/boost_cli/__init__.py +0 -5
- boost_skill_cli-1.0.1/boost_cli/core/catalog.py +0 -144
- boost_skill_cli-1.0.1/boost_skill_cli.egg-info/SOURCES.txt +0 -37
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/LICENSE +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/setup.cfg +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# PyPI configuration file
|
|
210
|
+
.pypirc
|
|
211
|
+
|
|
212
|
+
# Marimo
|
|
213
|
+
marimo/_static/
|
|
214
|
+
marimo/_lsp/
|
|
215
|
+
__marimo__/
|
|
216
|
+
|
|
217
|
+
# Streamlit
|
|
218
|
+
.streamlit/secrets.toml
|
|
219
|
+
|
|
220
|
+
# setuptools-scm generated version file
|
|
221
|
+
boost_cli/_version.py
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Contributing to boost
|
|
2
|
+
|
|
3
|
+
Thanks for taking an interest! boost is deliberately small and dependency-free,
|
|
4
|
+
so contributing is mostly about keeping the quality gates green.
|
|
5
|
+
|
|
6
|
+
## Dev setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/jonnyeclectic/boost && cd boost
|
|
10
|
+
make venv # pytest, coverage, mutmut, ruff, mypy — runtime stays stdlib-only
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Every test runs against a throwaway `$HOME`, so nothing touches your real
|
|
14
|
+
agent configs.
|
|
15
|
+
|
|
16
|
+
## The gates (CI runs all of these)
|
|
17
|
+
|
|
18
|
+
| Command | Gate |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `make test` | unit + functional suites, **≥80% line coverage** |
|
|
21
|
+
| `bash tests/smoke.sh` | 152 end-to-end checks through the real `./boost` shim |
|
|
22
|
+
| `make mutation` | mutmut over `boost_cli/core`, **≥80% mutants killed** |
|
|
23
|
+
| `ruff check boost_cli tests` | lint, zero findings |
|
|
24
|
+
| `mypy` | type check, zero errors |
|
|
25
|
+
|
|
26
|
+
## Ground rules
|
|
27
|
+
|
|
28
|
+
- **Stdlib only** at runtime. No third-party imports in `boost_cli/`.
|
|
29
|
+
- New commands live in `boost_cli/commands/<group>.py` as
|
|
30
|
+
`def cmd_<name>(argv) -> int` and are dispatched lazily from `cli.py`.
|
|
31
|
+
- Behavior changes need tests — functional tests drive the CLI in-process via
|
|
32
|
+
`boost_cli.cli.main` (see `tests/conftest.py` for the fixtures).
|
|
33
|
+
- Anything under `boost_cli/core/` is mutation-tested; expect to add unit
|
|
34
|
+
tests that actually kill your mutants.
|
|
35
|
+
|
|
36
|
+
## Pull requests
|
|
37
|
+
|
|
38
|
+
Branch from `main`, keep PRs focused, and write the PR description in the
|
|
39
|
+
commit message (it becomes the release notes via release-drafter).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Keep source releases lean: the runtime is boost_cli/ (with its bundled
|
|
2
|
+
# data), plus the usual metadata. Everything below is dev-only or generated
|
|
3
|
+
# and should never ship in the sdist.
|
|
4
|
+
include README.md LICENSE pyproject.toml setup.cfg
|
|
5
|
+
recursive-include boost_cli *.py *.json
|
|
6
|
+
prune mutants
|
|
7
|
+
prune dist
|
|
8
|
+
prune .idea
|
|
9
|
+
prune .claude
|
|
10
|
+
prune .github
|
|
11
|
+
exclude .coverage
|
|
12
|
+
global-exclude __pycache__ *.pyc *.pyo .DS_Store
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# boost — test & quality gates
|
|
2
|
+
# `make check` is the full production gate: unit + functional with >=80%
|
|
3
|
+
# coverage, the shell-level smoke suite, and >=80% mutation strength.
|
|
4
|
+
|
|
5
|
+
VENV := .venv
|
|
6
|
+
PY := $(VENV)/bin/python
|
|
7
|
+
PYTEST := $(VENV)/bin/pytest
|
|
8
|
+
|
|
9
|
+
.PHONY: venv test unit functional smoke coverage mutation lint check demo clean-test
|
|
10
|
+
|
|
11
|
+
venv:
|
|
12
|
+
python3 -m venv $(VENV)
|
|
13
|
+
$(VENV)/bin/pip -q install pytest pytest-cov coverage mutmut ruff mypy
|
|
14
|
+
|
|
15
|
+
unit:
|
|
16
|
+
$(PYTEST) tests/unit -q
|
|
17
|
+
|
|
18
|
+
functional:
|
|
19
|
+
$(PYTEST) tests/functional -q
|
|
20
|
+
|
|
21
|
+
# pytest suites with the 80% line-coverage gate (fail_under in pyproject.toml)
|
|
22
|
+
test:
|
|
23
|
+
$(PYTEST) tests/unit tests/functional --cov=boost_cli --cov-report=term-missing -q
|
|
24
|
+
|
|
25
|
+
coverage: test
|
|
26
|
+
|
|
27
|
+
# shell-level functional suite: drives the real shim end-to-end in a sandbox
|
|
28
|
+
smoke:
|
|
29
|
+
bash tests/smoke.sh
|
|
30
|
+
|
|
31
|
+
# mutation testing over boost_cli/core with the unit suite; 80% kill gate
|
|
32
|
+
mutation:
|
|
33
|
+
$(PY) scripts/mutation_gate.py --run --min 80
|
|
34
|
+
|
|
35
|
+
lint:
|
|
36
|
+
$(VENV)/bin/ruff check boost_cli tests
|
|
37
|
+
$(VENV)/bin/mypy
|
|
38
|
+
|
|
39
|
+
# regenerate docs/demo.gif (brew install vhs)
|
|
40
|
+
demo:
|
|
41
|
+
vhs docs/demo.tape
|
|
42
|
+
|
|
43
|
+
check: lint test smoke mutation
|
|
44
|
+
@echo "== all gates passed =="
|
|
45
|
+
|
|
46
|
+
clean-test:
|
|
47
|
+
rm -rf mutants .coverage htmlcov .pytest_cache
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.4
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -740,9 +740,26 @@ Needs Python 3.9+ and `git`.
|
|
|
740
740
|
```bash
|
|
741
741
|
pipx install boost-skill-cli # or: pip install boost-skill-cli
|
|
742
742
|
boost --version
|
|
743
|
-
boost tap --defaults # pull in the starter registries
|
|
743
|
+
boost tap --defaults # pull in the 5 starter registries
|
|
744
744
|
```
|
|
745
745
|
|
|
746
|
+
Want the whole ecosystem instead of the starter set? boost ships a **curated
|
|
747
|
+
registry catalog** — 90+ classified GitHub registries of skills, Cursor/Windsurf
|
|
748
|
+
**rules**, and Claude Code **workflows** (slash commands & subagents),
|
|
749
|
+
collectively indexing thousands of items:
|
|
750
|
+
|
|
751
|
+
```bash
|
|
752
|
+
boost tap --catalog --dry-run # browse the classified catalog
|
|
753
|
+
boost tap --catalog --type skill --limit 20 # tap the 20 biggest skill packs
|
|
754
|
+
boost tap --catalog --type rule # every rules registry
|
|
755
|
+
boost tap --catalog --category security # filter by category
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
boost indexes three item kinds out of the same registries: `SKILL.md` **skills**,
|
|
759
|
+
`.mdc`/`.cursorrules`/`.windsurfrules` **rules**, and command/agent **workflows**
|
|
760
|
+
(Markdown under `commands/`·`agents/`·`workflows/`, or carrying subagent
|
|
761
|
+
frontmatter). Rules and workflows are searchable today; only skills install.
|
|
762
|
+
|
|
746
763
|
Or run it straight from a checkout — the runtime is stdlib-only, so there's
|
|
747
764
|
nothing to install beyond the shim:
|
|
748
765
|
|
|
@@ -36,9 +36,26 @@ Needs Python 3.9+ and `git`.
|
|
|
36
36
|
```bash
|
|
37
37
|
pipx install boost-skill-cli # or: pip install boost-skill-cli
|
|
38
38
|
boost --version
|
|
39
|
-
boost tap --defaults # pull in the starter registries
|
|
39
|
+
boost tap --defaults # pull in the 5 starter registries
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
+
Want the whole ecosystem instead of the starter set? boost ships a **curated
|
|
43
|
+
registry catalog** — 90+ classified GitHub registries of skills, Cursor/Windsurf
|
|
44
|
+
**rules**, and Claude Code **workflows** (slash commands & subagents),
|
|
45
|
+
collectively indexing thousands of items:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
boost tap --catalog --dry-run # browse the classified catalog
|
|
49
|
+
boost tap --catalog --type skill --limit 20 # tap the 20 biggest skill packs
|
|
50
|
+
boost tap --catalog --type rule # every rules registry
|
|
51
|
+
boost tap --catalog --category security # filter by category
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
boost indexes three item kinds out of the same registries: `SKILL.md` **skills**,
|
|
55
|
+
`.mdc`/`.cursorrules`/`.windsurfrules` **rules**, and command/agent **workflows**
|
|
56
|
+
(Markdown under `commands/`·`agents/`·`workflows/`, or carrying subagent
|
|
57
|
+
frontmatter). Rules and workflows are searchable today; only skills install.
|
|
58
|
+
|
|
42
59
|
Or run it straight from a checkout — the runtime is stdlib-only, so there's
|
|
43
60
|
nothing to install beyond the shim:
|
|
44
61
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Only the latest release receives security fixes.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Please **do not** open a public issue for security reports. Instead, use
|
|
10
|
+
GitHub's private vulnerability reporting:
|
|
11
|
+
|
|
12
|
+
**[Report a vulnerability](https://github.com/jonnyeclectic/boost/security/advisories/new)**
|
|
13
|
+
|
|
14
|
+
You can expect an acknowledgement within a few days. Please include steps to
|
|
15
|
+
reproduce and the affected command(s).
|
|
16
|
+
|
|
17
|
+
## Scope notes
|
|
18
|
+
|
|
19
|
+
boost executes `git` against registry URLs you tap and symlinks skills into
|
|
20
|
+
agent directories. Reports about tap-supplied content escaping the store,
|
|
21
|
+
path traversal via `SKILL.md` frontmatter, or command injection through
|
|
22
|
+
skill/tap names are especially valuable.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# boost — Homebrew for AI coding skills.
|
|
3
|
+
# Thin shim: finds Python 3.9+, runs the boost_cli package that lives
|
|
4
|
+
# next to this script (resolving symlinks, so `ln -s .../boost ~/bin/boost`
|
|
5
|
+
# just works). No PyPI, no Artifactory — stdlib only.
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
SOURCE="${BASH_SOURCE[0]:-$0}"
|
|
9
|
+
while [ -h "$SOURCE" ]; do
|
|
10
|
+
DIR="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"
|
|
11
|
+
SOURCE="$(readlink "$SOURCE")"
|
|
12
|
+
[[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE"
|
|
13
|
+
done
|
|
14
|
+
ROOT="$(cd -P "$(dirname "$SOURCE")" >/dev/null 2>&1 && pwd)"
|
|
15
|
+
|
|
16
|
+
find_python() {
|
|
17
|
+
for py in python3 python; do
|
|
18
|
+
if command -v "$py" >/dev/null 2>&1; then
|
|
19
|
+
if "$py" -c 'import sys; sys.exit(0 if sys.version_info >= (3, 9) else 1)' 2>/dev/null; then
|
|
20
|
+
echo "$py"
|
|
21
|
+
return 0
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
return 1
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
PY="$(find_python)" || {
|
|
29
|
+
echo "boost: Python 3.9+ is required but was not found on PATH" >&2
|
|
30
|
+
echo " hint: brew install python3" >&2
|
|
31
|
+
exit 1
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exec "$PY" -S -c "
|
|
35
|
+
import sys
|
|
36
|
+
sys.path.insert(0, '$ROOT')
|
|
37
|
+
from boost_cli.cli import main
|
|
38
|
+
sys.exit(main(sys.argv[1:]))
|
|
39
|
+
" "$@"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""boost — Homebrew for AI coding skills."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _detect_version() -> str:
|
|
5
|
+
"""Resolve the package version without a hard-coded constant.
|
|
6
|
+
|
|
7
|
+
Order: the file setuptools-scm writes at build time, then installed
|
|
8
|
+
package metadata, then a git-checkout fallback (stdlib only, so the
|
|
9
|
+
dependency-free runtime stays intact), then a sentinel.
|
|
10
|
+
"""
|
|
11
|
+
try:
|
|
12
|
+
from ._version import version as scm_version
|
|
13
|
+
return scm_version
|
|
14
|
+
except Exception:
|
|
15
|
+
pass
|
|
16
|
+
try:
|
|
17
|
+
from importlib.metadata import version as dist_version
|
|
18
|
+
return dist_version("boost-skill-cli")
|
|
19
|
+
except Exception:
|
|
20
|
+
pass
|
|
21
|
+
try:
|
|
22
|
+
import subprocess
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
root = Path(__file__).resolve().parent.parent
|
|
25
|
+
proc = subprocess.run(
|
|
26
|
+
["git", "-C", str(root), "describe", "--tags", "--always", "--dirty"],
|
|
27
|
+
capture_output=True, text=True, timeout=3)
|
|
28
|
+
described = proc.stdout.strip()
|
|
29
|
+
if proc.returncode == 0 and described:
|
|
30
|
+
return described.lstrip("v")
|
|
31
|
+
except Exception:
|
|
32
|
+
pass
|
|
33
|
+
return "0.0.0+unknown"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__version__ = _detect_version()
|
|
37
|
+
PRODUCT = "boost"
|
|
38
|
+
TAGLINE = "AI Skill Package Manager"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# file generated by vcs-versioning
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"__version__",
|
|
7
|
+
"__version_tuple__",
|
|
8
|
+
"version",
|
|
9
|
+
"version_tuple",
|
|
10
|
+
"__commit_id__",
|
|
11
|
+
"commit_id",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
version: str
|
|
15
|
+
__version__: str
|
|
16
|
+
__version_tuple__: tuple[int | str, ...]
|
|
17
|
+
version_tuple: tuple[int | str, ...]
|
|
18
|
+
commit_id: str | None
|
|
19
|
+
__commit_id__: str | None
|
|
20
|
+
|
|
21
|
+
__version__ = version = '1.0.4'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 4)
|
|
23
|
+
|
|
24
|
+
__commit_id__ = commit_id = None
|
|
@@ -21,8 +21,58 @@ def _tilde(p) -> str:
|
|
|
21
21
|
return s
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
def _tap_catalog(args) -> int:
|
|
25
|
+
"""Tap every registry in the filtered catalog selection."""
|
|
26
|
+
selection = _catalog_selection(args)
|
|
27
|
+
if not selection:
|
|
28
|
+
out.warn("no catalog registries match that filter")
|
|
29
|
+
return 1
|
|
30
|
+
if args.dry_run:
|
|
31
|
+
rows = [(e["name"], e["type"], e.get("category", ""),
|
|
32
|
+
"~%d" % (e.get("est_items") or 0),
|
|
33
|
+
out.c(e.get("focus", ""), out.DIM)) for e in selection]
|
|
34
|
+
out.table(rows, headers=("NAME", "TYPE", "CATEGORY", "EST", "FOCUS"))
|
|
35
|
+
print()
|
|
36
|
+
out.dim("%d registries · ~%d items (dry run — nothing tapped)"
|
|
37
|
+
% (len(selection), sum(e.get("est_items") or 0 for e in selection)))
|
|
38
|
+
return 0
|
|
39
|
+
existing = {t.name for t in registry.list_taps()}
|
|
40
|
+
rc = 0
|
|
41
|
+
for e in selection:
|
|
42
|
+
if e["name"] in existing:
|
|
43
|
+
out.info(out.c("%s already tapped" % e["name"], out.DIM))
|
|
44
|
+
continue
|
|
45
|
+
try:
|
|
46
|
+
tap = registry.add(str(e["url"]), curated=True)
|
|
47
|
+
entries = catalog.rebuild_tap(tap)
|
|
48
|
+
except BoostError as err:
|
|
49
|
+
out.warn("could not tap %s: %s" % (e["name"], err.message))
|
|
50
|
+
rc = 1
|
|
51
|
+
continue
|
|
52
|
+
journal.log("tap", tap.name)
|
|
53
|
+
out.ok("tapped %s (%d items) — %s"
|
|
54
|
+
% (tap.name, len(entries), e.get("focus", "")))
|
|
55
|
+
return rc
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _catalog_selection(args) -> list:
|
|
59
|
+
"""Filter the bundled registry catalog by --type/--category/--limit."""
|
|
60
|
+
entries = config.load_registry_catalog()
|
|
61
|
+
if args.type:
|
|
62
|
+
entries = [e for e in entries
|
|
63
|
+
if e.get("type") == args.type or args.type in e.get("also_types", [])]
|
|
64
|
+
if args.category:
|
|
65
|
+
entries = [e for e in entries if e.get("category") == args.category]
|
|
66
|
+
if not args.include_lists:
|
|
67
|
+
entries = [e for e in entries if not e.get("list_only")]
|
|
68
|
+
entries.sort(key=lambda e: (-int(e.get("est_items") or 0), e["name"].lower()))
|
|
69
|
+
if args.limit:
|
|
70
|
+
entries = entries[:args.limit]
|
|
71
|
+
return entries
|
|
72
|
+
|
|
73
|
+
|
|
24
74
|
def cmd_tap(argv) -> int:
|
|
25
|
-
"""boost tap [SPEC] [--defaults] [--curated]"""
|
|
75
|
+
"""boost tap [SPEC] [--defaults] [--catalog] [--curated]"""
|
|
26
76
|
p = argparse.ArgumentParser(
|
|
27
77
|
prog="boost tap",
|
|
28
78
|
description="Add a GitHub repo as a skill registry")
|
|
@@ -30,13 +80,26 @@ def cmd_tap(argv) -> int:
|
|
|
30
80
|
help="owner/repo, a git URL, or a local directory")
|
|
31
81
|
p.add_argument("--defaults", action="store_true",
|
|
32
82
|
help="tap the recommended public registries")
|
|
83
|
+
p.add_argument("--catalog", action="store_true",
|
|
84
|
+
help="tap from the bundled curated registry catalog")
|
|
85
|
+
p.add_argument("--type", choices=("skill", "rule", "workflow"),
|
|
86
|
+
help="with --catalog: restrict to one item type")
|
|
87
|
+
p.add_argument("--category", help="with --catalog: restrict to one category")
|
|
88
|
+
p.add_argument("--limit", type=int, metavar="N",
|
|
89
|
+
help="with --catalog: only the top N registries by est. size")
|
|
90
|
+
p.add_argument("--include-lists", action="store_true",
|
|
91
|
+
help="with --catalog: also tap awesome-list/index repos")
|
|
92
|
+
p.add_argument("--dry-run", action="store_true",
|
|
93
|
+
help="with --catalog: print what would be tapped, tap nothing")
|
|
33
94
|
p.add_argument("--curated", action="store_true",
|
|
34
95
|
help="mark the tap as curated (★ in listings)")
|
|
35
96
|
args = p.parse_args(argv)
|
|
36
|
-
if not args.spec and not args.defaults:
|
|
37
|
-
p.error("provide a SPEC or --
|
|
97
|
+
if not args.spec and not args.defaults and not args.catalog:
|
|
98
|
+
p.error("provide a SPEC, --defaults, or --catalog")
|
|
38
99
|
|
|
39
100
|
rc = 0
|
|
101
|
+
if args.catalog:
|
|
102
|
+
rc |= _tap_catalog(args)
|
|
40
103
|
if args.defaults:
|
|
41
104
|
existing = {t.name for t in registry.list_taps()}
|
|
42
105
|
for default in config.DEFAULT_TAPS:
|