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.
Files changed (84) hide show
  1. boost_skill_cli-1.0.4/.gitignore +221 -0
  2. boost_skill_cli-1.0.4/CONTRIBUTING.md +39 -0
  3. boost_skill_cli-1.0.4/MANIFEST.in +12 -0
  4. boost_skill_cli-1.0.4/Makefile +47 -0
  5. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/PKG-INFO +19 -2
  6. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/README.md +18 -1
  7. boost_skill_cli-1.0.4/SECURITY.md +22 -0
  8. boost_skill_cli-1.0.4/boost +39 -0
  9. boost_skill_cli-1.0.4/boost_cli/__init__.py +38 -0
  10. boost_skill_cli-1.0.4/boost_cli/_version.py +24 -0
  11. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/taps.py +66 -3
  12. boost_skill_cli-1.0.4/boost_cli/core/catalog.py +240 -0
  13. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/config.py +13 -0
  14. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/paths.py +5 -0
  15. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/store.py +8 -0
  16. boost_skill_cli-1.0.4/boost_cli/data/registries.json +1042 -0
  17. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/PKG-INFO +19 -2
  18. boost_skill_cli-1.0.4/boost_skill_cli.egg-info/SOURCES.txt +80 -0
  19. boost_skill_cli-1.0.4/docs/.claude/settings.local.json +11 -0
  20. boost_skill_cli-1.0.4/docs/demo.gif +0 -0
  21. boost_skill_cli-1.0.4/docs/demo.tape +36 -0
  22. boost_skill_cli-1.0.4/docs/overview.html +966 -0
  23. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/pyproject.toml +15 -3
  24. boost_skill_cli-1.0.4/scripts/build_registries.py +204 -0
  25. boost_skill_cli-1.0.4/scripts/mutation_gate.py +60 -0
  26. boost_skill_cli-1.0.4/tests/conftest.py +89 -0
  27. boost_skill_cli-1.0.4/tests/functional/test_cli_configuration.py +756 -0
  28. boost_skill_cli-1.0.4/tests/functional/test_cli_discovery.py +613 -0
  29. boost_skill_cli-1.0.4/tests/functional/test_cli_info.py +328 -0
  30. boost_skill_cli-1.0.4/tests/functional/test_cli_intelligence.py +510 -0
  31. boost_skill_cli-1.0.4/tests/functional/test_cli_pkg.py +719 -0
  32. boost_skill_cli-1.0.4/tests/functional/test_cli_quality.py +465 -0
  33. boost_skill_cli-1.0.4/tests/functional/test_cli_taps.py +288 -0
  34. boost_skill_cli-1.0.4/tests/functional/test_cli_team.py +462 -0
  35. boost_skill_cli-1.0.4/tests/functional/test_everyday_loop.py +66 -0
  36. boost_skill_cli-1.0.4/tests/make_fixture.py +146 -0
  37. boost_skill_cli-1.0.4/tests/smoke.sh +221 -0
  38. boost_skill_cli-1.0.4/tests/unit/test_agents.py +74 -0
  39. boost_skill_cli-1.0.4/tests/unit/test_ai.py +259 -0
  40. boost_skill_cli-1.0.4/tests/unit/test_catalog.py +453 -0
  41. boost_skill_cli-1.0.4/tests/unit/test_config.py +196 -0
  42. boost_skill_cli-1.0.4/tests/unit/test_errors_and_cli_table.py +229 -0
  43. boost_skill_cli-1.0.4/tests/unit/test_frontmatter.py +195 -0
  44. boost_skill_cli-1.0.4/tests/unit/test_gitutil.py +155 -0
  45. boost_skill_cli-1.0.4/tests/unit/test_journal.py +144 -0
  46. boost_skill_cli-1.0.4/tests/unit/test_lockfile.py +159 -0
  47. boost_skill_cli-1.0.4/tests/unit/test_mutation_hardening.py +243 -0
  48. boost_skill_cli-1.0.4/tests/unit/test_output.py +232 -0
  49. boost_skill_cli-1.0.4/tests/unit/test_paths.py +118 -0
  50. boost_skill_cli-1.0.4/tests/unit/test_policy.py +151 -0
  51. boost_skill_cli-1.0.4/tests/unit/test_registry.py +218 -0
  52. boost_skill_cli-1.0.4/tests/unit/test_store.py +371 -0
  53. boost_skill_cli-1.0.4/tests/unit/test_util.py +366 -0
  54. boost_skill_cli-1.0.4/tests/unit/test_version.py +50 -0
  55. boost_skill_cli-1.0.1/boost_cli/__init__.py +0 -5
  56. boost_skill_cli-1.0.1/boost_cli/core/catalog.py +0 -144
  57. boost_skill_cli-1.0.1/boost_skill_cli.egg-info/SOURCES.txt +0 -37
  58. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/LICENSE +0 -0
  59. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/__main__.py +0 -0
  60. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/cli.py +0 -0
  61. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/__init__.py +0 -0
  62. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/configuration.py +0 -0
  63. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/discovery.py +0 -0
  64. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/info.py +0 -0
  65. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/intelligence.py +0 -0
  66. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/pkg.py +0 -0
  67. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/quality.py +0 -0
  68. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/commands/team.py +0 -0
  69. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/__init__.py +0 -0
  70. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/agents.py +0 -0
  71. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/ai.py +0 -0
  72. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/frontmatter.py +0 -0
  73. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/gitutil.py +0 -0
  74. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/journal.py +0 -0
  75. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/lockfile.py +0 -0
  76. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/output.py +0 -0
  77. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/policy.py +0 -0
  78. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/registry.py +0 -0
  79. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/core/util.py +0 -0
  80. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_cli/errors.py +0 -0
  81. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  82. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  83. {boost_skill_cli-1.0.1 → boost_skill_cli-1.0.4}/boost_skill_cli.egg-info/top_level.txt +0 -0
  84. {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.1
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 --defaults")
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: