spawn-cli 0.1.3__tar.gz → 0.1.5__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 (52) hide show
  1. spawn_cli-0.1.5/LICENSE +21 -0
  2. spawn_cli-0.1.5/PKG-INFO +214 -0
  3. spawn_cli-0.1.5/README.md +197 -0
  4. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/pyproject.toml +9 -1
  5. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/high_level.py +103 -17
  6. spawn_cli-0.1.5/src/spawn_cli.egg-info/PKG-INFO +214 -0
  7. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli.egg-info/SOURCES.txt +1 -0
  8. spawn_cli-0.1.3/PKG-INFO +0 -11
  9. spawn_cli-0.1.3/README.md +0 -114
  10. spawn_cli-0.1.3/src/spawn_cli.egg-info/PKG-INFO +0 -11
  11. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/setup.cfg +0 -0
  12. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/__init__.py +0 -0
  13. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/cli.py +0 -0
  14. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/__init__.py +0 -0
  15. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/download.py +0 -0
  16. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/errors.py +0 -0
  17. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/low_level.py +0 -0
  18. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/core/scripts.py +0 -0
  19. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/errors.py +0 -0
  20. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/__init__.py +0 -0
  21. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/_helpers.py +0 -0
  22. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/_stub.py +0 -0
  23. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/_vacancy.py +0 -0
  24. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/claude_code.py +0 -0
  25. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/codex.py +0 -0
  26. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/cursor.py +0 -0
  27. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/gemini_cli.py +0 -0
  28. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/github_copilot.py +0 -0
  29. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/registry.py +0 -0
  30. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/ide/windsurf.py +0 -0
  31. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/__init__.py +0 -0
  32. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/json_io.py +0 -0
  33. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/lock.py +0 -0
  34. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/paths.py +0 -0
  35. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/text_io.py +0 -0
  36. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/toml_io.py +0 -0
  37. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/io/yaml_io.py +0 -0
  38. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/__init__.py +0 -0
  39. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/config.py +0 -0
  40. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/mcp.py +0 -0
  41. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/metadata.py +0 -0
  42. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/navigation.py +0 -0
  43. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/models/skill.py +0 -0
  44. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/resources/__init__.py +0 -0
  45. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/resources/default_core_config.yaml +0 -0
  46. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli/warnings_display.py +0 -0
  47. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli.egg-info/dependency_links.txt +0 -0
  48. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli.egg-info/entry_points.txt +0 -0
  49. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli.egg-info/requires.txt +0 -0
  50. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/src/spawn_cli.egg-info/top_level.txt +0 -0
  51. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/tests/test_cli.py +0 -0
  52. {spawn_cli-0.1.3 → spawn_cli-0.1.5}/tests/test_warnings_display.py +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 spawn-cli contributors
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.
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: spawn-cli
3
+ Version: 0.1.5
4
+ Summary: A minimal installable Python CLI package.
5
+ License: MIT
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: ruamel.yaml>=0.18
12
+ Requires-Dist: filelock>=3.12
13
+ Requires-Dist: httpx>=0.27
14
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
15
+ Requires-Dist: tomli-w>=1.0
16
+ Dynamic: license-file
17
+
18
+ ## What is Spawn?
19
+
20
+ Spawn is a framework for building **AIDD** (AI-driven development) methodologies. It supports both **authoring** methodologies and **applying** them in a project. Within a single repository you can use **several** AIDD methodologies in a coherent way—shared navigation, skills, rules, and tooling stay aligned instead of competing ad hoc setups.
21
+
22
+ ## What is spawn-cli?
23
+
24
+ **spawn-cli** is the utility that manages methodologies installed in your project. In Spawn terminology those packs are **extensions**: versioned content that usually lives in a **Git** repository. The CLI **instantiates** instruction files, process descriptions, rules, agent skills, and wires their behavior together (navigation, IDE-facing outputs, optional lifecycle hooks). Extensions can also declare **MCP servers**, **agent-ignore** patterns, **git-ignore** entries, and similar integration points—see [`spec/design/extension-author-guide.md`](spec/design/extension-author-guide.md).
25
+
26
+ ### How spawn-cli keeps methodologies coherent
27
+
28
+ Several methodologies in one repo stay aligned because Spawn maintains **one shared navigation index**: [`spawn/navigation.yaml`](spec/design/data-structure.md) aggregates mandatory and contextual reads from **every installed extension** plus local [`spawn/rules/`](spec/design/user-guide.md) (refreshed with `spawn rules refresh`). Agents are steered through that file instead of chasing disconnected README fragments.
29
+
30
+ On each install or refresh, the CLI **regenerates IDE-facing artifacts** so skills and entry points stay consistent across extensions: rendered skill bodies include **paths and descriptions** wired from navigation (required reads, contextual hints, rule files), MCP snippets normalize server definitions per IDE adapter, and ignore lists merge without manual copy-paste. The net effect is that methodology files, generated skill links, and repo rules **compose** rather than contradict each other.
31
+
32
+ **Example:** [**spawn-ext-spectask**](https://github.com/noant/spawn-ext-spectask) (Spec-Tasks methodology: spec layout, skills, design index) and [**spawn-ext-creator**](https://github.com/noant/spawn-ext-creator) (authoring flows, including agent-guided extension bootstrap) can be installed in the **same** repository and still share that single index and merged IDE outputs.
33
+
34
+ ## How to install spawn-cli
35
+
36
+ **Recommended:** install `spawn` on your `PATH` with **uv**:
37
+
38
+ ```bash
39
+ uv tool install spawn-cli && spawn --help
40
+ ```
41
+
42
+ Run once without installing (ephemeral **uvx**):
43
+
44
+ ```bash
45
+ uvx --from spawn-cli spawn --help
46
+ ```
47
+
48
+ **Upgrade** the persistent uv tool:
49
+
50
+ ```bash
51
+ uv tool upgrade spawn-cli && spawn --help
52
+ ```
53
+
54
+ Force a fresh resolver for a one-shot run:
55
+
56
+ ```bash
57
+ uvx --refresh --from spawn-cli spawn --help
58
+ ```
59
+
60
+ Additional installers (**pip**, **pipx**, local checkout) and upgrade notes: **[spec/design/user-guide.md](spec/design/user-guide.md#other-installation-options)**.
61
+
62
+ ## How spawn-cli works
63
+
64
+ Run commands from the **root of the repository** you are configuring. Almost every command requires `spawn init` first (it creates the `spawn/` tree). Only one Spawn process should touch a repo at a time (file lock).
65
+
66
+ ### Initialize a repo
67
+
68
+ ```bash
69
+ spawn init
70
+ ```
71
+
72
+ ### IDE adapters
73
+
74
+ For each **supported IDE** adapter, show whether it **looks used in the current repository** and what it can render (e.g. skills, MCP, agent-ignore):
75
+
76
+ ```bash
77
+ spawn ide list-supported-ides
78
+ ```
79
+
80
+ Register or drop IDE keys for **this** repo (examples: `cursor`, `codex`):
81
+
82
+ ```bash
83
+ spawn ide add cursor
84
+ spawn ide add cursor codex
85
+ spawn ide remove codex
86
+ spawn ide list
87
+ ```
88
+
89
+ ### Extensions
90
+
91
+ Add from a Git URL, optional branch (also supports ZIP paths and local directories/archives):
92
+
93
+ ```bash
94
+ spawn extension add https://github.com/noant/spawn-ext-spectask
95
+ spawn extension add https://github.com/noant/spawn-ext-spectask --branch main
96
+ ```
97
+
98
+ Maintain installed packs:
99
+
100
+ ```bash
101
+ spawn extension list
102
+ spawn extension update spectask
103
+ spawn extension reinstall spectask
104
+ spawn extension remove spectask
105
+ spawn extension healthcheck spectask
106
+ ```
107
+
108
+ Authoring helpers (run inside or next to an extension project):
109
+
110
+ ```bash
111
+ spawn extension init ./my-ext --name my-ext
112
+ spawn extension check ./my-ext
113
+ spawn extension check ./my-ext --strict
114
+ spawn extension from-rules ./repo-with-spawn-rules --name my-ext --output ./out
115
+ ```
116
+
117
+ ### Navigation from repo rules
118
+
119
+ After editing files under `spawn/rules/`, refresh mandatory reads in `spawn/navigation.yaml`:
120
+
121
+ ```bash
122
+ spawn rules refresh
123
+ ```
124
+
125
+ ### Batch install from a build manifest
126
+
127
+ `spawn build list` / `spawn build install` take a **build source** (positional argument; there is no implicit default):
128
+
129
+ - **Local directory** whose root contains **`extensions.yaml`**. Spawn resolves the path (e.g. `.` → current working directory) and reads **`<that-directory>/extensions.yaml`** — not a path to the YAML file itself.
130
+ - Otherwise a **Git URL**, **ZIP URL**, or **local path** to a repository tree: Spawn stages it, then looks for **`extensions.yaml`** at that root or, if there is exactly one top-level subdirectory, under that folder (`extensions.yaml not found` if neither applies).
131
+
132
+ Each manifest entry is an extension source; optional per-entry `branch` overrides the CLI default for that row.
133
+
134
+ Minimal `extensions.yaml`:
135
+
136
+ ```yaml
137
+ extensions:
138
+ - path: https://github.com/org/extension-one.git
139
+ branch: main
140
+ - path: https://github.com/org/extension-two.git
141
+ ```
142
+
143
+ Dry-run (prints resolved entries as YAML), then install:
144
+
145
+ ```bash
146
+ # Manifest at ./extensions.yaml (cwd is usually your initialized target repo if you keep it there)
147
+ spawn build list .
148
+ spawn build install .
149
+
150
+ spawn build install /path/to/methodology-bundle
151
+ spawn build install https://github.com/org/team-methodology.git --branch main
152
+ ```
153
+
154
+ The **`--branch`** flag applies when the **build source** is Git (clone revision). Entries that omit `branch` fall back to that value.
155
+
156
+ ### Example extension
157
+
158
+ [spawn-ext-spectask](https://github.com/noant/spawn-ext-spectask) is a concrete extension you can install with `spawn extension add` as shown above.
159
+
160
+ ---
161
+
162
+ - **Python:** 3.10+ (see `pyproject.toml`).
163
+ - **Deep dives:** [spec/design/user-guide.md](spec/design/user-guide.md) and [spec/design/utility.md](spec/design/utility.md).
164
+
165
+ ## How to create an extension
166
+
167
+ An extension can be a **full** AIDD methodology, **team** conventions (review rules, codestyle), **scaffolds** for projects that default to AIDD-friendly layouts, **skill-only** bundles, or anything else you can express as declarative files plus optional setup hooks—anything that fits the `extsrc/` layout described in the author guide.
168
+
169
+ **Bootstrap with the creator extension** (install like any other extension after `spawn init`):
170
+
171
+ ```bash
172
+ spawn extension add https://github.com/noant/spawn-ext-creator
173
+ ```
174
+
175
+ **Scaffold an empty extension** with the CLI (requires `spawn init` in the repo you run from — same as other subcommands). This lays out `extsrc/` with a starter `config.yaml`, plus empty `skills/`, `files/`, and `setup/`:
176
+
177
+ ```bash
178
+ spawn extension init --name my-extension
179
+ spawn extension init ./my-extension --name my-extension
180
+ ```
181
+
182
+ **Agent-guided scaffold** with **[spawn-ext-creator](https://github.com/noant/spawn-ext-creator)** (install the extension above, then `spawn ide add <ide>` so skills render into your IDE): invoke the **`spawn-ext-bootstrap`** skill so the agent lays out a fuller extension repo than the bare CLI skeleton—for example:
183
+
184
+ > Use the **spawn-ext-bootstrap** skill to bootstrap a new Spawn extension with stable id `my-extension` under `./my-extension`.
185
+
186
+ Other creator skills (declaring `config.yaml`, skill sources, MCP, verification, etc.) ship under the same extension; see the rendered skill list after install.
187
+
188
+ Read **[spec/design/extension-author-guide.md](spec/design/extension-author-guide.md)** for the full model: required `extsrc/config.yaml`, mapping files under `extsrc/files/`, optional `skills/`, `mcp.json`, `agent-ignore`, `setup/` scripts, and how static vs artifact content is updated on `spawn extension update`.
189
+
190
+ **Minimal mental model:**
191
+
192
+ - `**extsrc/config.yaml`** — `schema`, `version`, stable `**name`** (install path `spawn/.extend/<name>/`), plus `files`, `skills`, ignores, etc.
193
+ - `**extsrc/files/**` — template tree mirrored into the target repo according to `files:` entries.
194
+ - `**spawn extension check . --strict**` — validate before publishing or tagging a release.
195
+
196
+ ## How to add rules without creating an extension
197
+
198
+ Project-local conventions can live under **`spawn/rules/`** without packaging them as an extension. After **`spawn init`**, add any files there (for example `spawn/rules/team.md`); Spawn discovers **every file** under that directory tree.
199
+
200
+ Wire those paths into **`spawn/navigation.yaml`** so mandatory reads stay aligned with what is on disk:
201
+
202
+ ```bash
203
+ spawn rules refresh
204
+ ```
205
+
206
+ That rescans **`spawn/rules/`**, attaches missing rule files under a **`rules`** group inside **`read-required`** (default description **`Local rule file.`** until you edit it), and drops stale entries whose files were deleted (you may see a warning).
207
+
208
+ Rule files can be **mandatory** (**`read-required`**) or **contextual** (**`read-contextual`**). **`spawn rules refresh`** only auto-adds **new** paths into **`read-required` → `rules`**. To keep a rule **contextual**, declare it under **`read-contextual` → `rules`** in **`spawn/navigation.yaml`** with the same shape (`path`, `description`)—once a path appears in either rules list, refresh will not duplicate it into the other tier. You can move entries between **`read-required`** and **`read-contextual`** by editing **`spawn/navigation.yaml`**, then run **`spawn rules refresh`** so both lists stay consistent with files on disk.
209
+
210
+ Extension-backed reads (`ext:` entries) are unrelated—you only maintain **`spawn/rules/**`** plus **`spawn rules refresh`** for repo-local rules.
211
+
212
+ ## License
213
+
214
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,197 @@
1
+ ## What is Spawn?
2
+
3
+ Spawn is a framework for building **AIDD** (AI-driven development) methodologies. It supports both **authoring** methodologies and **applying** them in a project. Within a single repository you can use **several** AIDD methodologies in a coherent way—shared navigation, skills, rules, and tooling stay aligned instead of competing ad hoc setups.
4
+
5
+ ## What is spawn-cli?
6
+
7
+ **spawn-cli** is the utility that manages methodologies installed in your project. In Spawn terminology those packs are **extensions**: versioned content that usually lives in a **Git** repository. The CLI **instantiates** instruction files, process descriptions, rules, agent skills, and wires their behavior together (navigation, IDE-facing outputs, optional lifecycle hooks). Extensions can also declare **MCP servers**, **agent-ignore** patterns, **git-ignore** entries, and similar integration points—see [`spec/design/extension-author-guide.md`](spec/design/extension-author-guide.md).
8
+
9
+ ### How spawn-cli keeps methodologies coherent
10
+
11
+ Several methodologies in one repo stay aligned because Spawn maintains **one shared navigation index**: [`spawn/navigation.yaml`](spec/design/data-structure.md) aggregates mandatory and contextual reads from **every installed extension** plus local [`spawn/rules/`](spec/design/user-guide.md) (refreshed with `spawn rules refresh`). Agents are steered through that file instead of chasing disconnected README fragments.
12
+
13
+ On each install or refresh, the CLI **regenerates IDE-facing artifacts** so skills and entry points stay consistent across extensions: rendered skill bodies include **paths and descriptions** wired from navigation (required reads, contextual hints, rule files), MCP snippets normalize server definitions per IDE adapter, and ignore lists merge without manual copy-paste. The net effect is that methodology files, generated skill links, and repo rules **compose** rather than contradict each other.
14
+
15
+ **Example:** [**spawn-ext-spectask**](https://github.com/noant/spawn-ext-spectask) (Spec-Tasks methodology: spec layout, skills, design index) and [**spawn-ext-creator**](https://github.com/noant/spawn-ext-creator) (authoring flows, including agent-guided extension bootstrap) can be installed in the **same** repository and still share that single index and merged IDE outputs.
16
+
17
+ ## How to install spawn-cli
18
+
19
+ **Recommended:** install `spawn` on your `PATH` with **uv**:
20
+
21
+ ```bash
22
+ uv tool install spawn-cli && spawn --help
23
+ ```
24
+
25
+ Run once without installing (ephemeral **uvx**):
26
+
27
+ ```bash
28
+ uvx --from spawn-cli spawn --help
29
+ ```
30
+
31
+ **Upgrade** the persistent uv tool:
32
+
33
+ ```bash
34
+ uv tool upgrade spawn-cli && spawn --help
35
+ ```
36
+
37
+ Force a fresh resolver for a one-shot run:
38
+
39
+ ```bash
40
+ uvx --refresh --from spawn-cli spawn --help
41
+ ```
42
+
43
+ Additional installers (**pip**, **pipx**, local checkout) and upgrade notes: **[spec/design/user-guide.md](spec/design/user-guide.md#other-installation-options)**.
44
+
45
+ ## How spawn-cli works
46
+
47
+ Run commands from the **root of the repository** you are configuring. Almost every command requires `spawn init` first (it creates the `spawn/` tree). Only one Spawn process should touch a repo at a time (file lock).
48
+
49
+ ### Initialize a repo
50
+
51
+ ```bash
52
+ spawn init
53
+ ```
54
+
55
+ ### IDE adapters
56
+
57
+ For each **supported IDE** adapter, show whether it **looks used in the current repository** and what it can render (e.g. skills, MCP, agent-ignore):
58
+
59
+ ```bash
60
+ spawn ide list-supported-ides
61
+ ```
62
+
63
+ Register or drop IDE keys for **this** repo (examples: `cursor`, `codex`):
64
+
65
+ ```bash
66
+ spawn ide add cursor
67
+ spawn ide add cursor codex
68
+ spawn ide remove codex
69
+ spawn ide list
70
+ ```
71
+
72
+ ### Extensions
73
+
74
+ Add from a Git URL, optional branch (also supports ZIP paths and local directories/archives):
75
+
76
+ ```bash
77
+ spawn extension add https://github.com/noant/spawn-ext-spectask
78
+ spawn extension add https://github.com/noant/spawn-ext-spectask --branch main
79
+ ```
80
+
81
+ Maintain installed packs:
82
+
83
+ ```bash
84
+ spawn extension list
85
+ spawn extension update spectask
86
+ spawn extension reinstall spectask
87
+ spawn extension remove spectask
88
+ spawn extension healthcheck spectask
89
+ ```
90
+
91
+ Authoring helpers (run inside or next to an extension project):
92
+
93
+ ```bash
94
+ spawn extension init ./my-ext --name my-ext
95
+ spawn extension check ./my-ext
96
+ spawn extension check ./my-ext --strict
97
+ spawn extension from-rules ./repo-with-spawn-rules --name my-ext --output ./out
98
+ ```
99
+
100
+ ### Navigation from repo rules
101
+
102
+ After editing files under `spawn/rules/`, refresh mandatory reads in `spawn/navigation.yaml`:
103
+
104
+ ```bash
105
+ spawn rules refresh
106
+ ```
107
+
108
+ ### Batch install from a build manifest
109
+
110
+ `spawn build list` / `spawn build install` take a **build source** (positional argument; there is no implicit default):
111
+
112
+ - **Local directory** whose root contains **`extensions.yaml`**. Spawn resolves the path (e.g. `.` → current working directory) and reads **`<that-directory>/extensions.yaml`** — not a path to the YAML file itself.
113
+ - Otherwise a **Git URL**, **ZIP URL**, or **local path** to a repository tree: Spawn stages it, then looks for **`extensions.yaml`** at that root or, if there is exactly one top-level subdirectory, under that folder (`extensions.yaml not found` if neither applies).
114
+
115
+ Each manifest entry is an extension source; optional per-entry `branch` overrides the CLI default for that row.
116
+
117
+ Minimal `extensions.yaml`:
118
+
119
+ ```yaml
120
+ extensions:
121
+ - path: https://github.com/org/extension-one.git
122
+ branch: main
123
+ - path: https://github.com/org/extension-two.git
124
+ ```
125
+
126
+ Dry-run (prints resolved entries as YAML), then install:
127
+
128
+ ```bash
129
+ # Manifest at ./extensions.yaml (cwd is usually your initialized target repo if you keep it there)
130
+ spawn build list .
131
+ spawn build install .
132
+
133
+ spawn build install /path/to/methodology-bundle
134
+ spawn build install https://github.com/org/team-methodology.git --branch main
135
+ ```
136
+
137
+ The **`--branch`** flag applies when the **build source** is Git (clone revision). Entries that omit `branch` fall back to that value.
138
+
139
+ ### Example extension
140
+
141
+ [spawn-ext-spectask](https://github.com/noant/spawn-ext-spectask) is a concrete extension you can install with `spawn extension add` as shown above.
142
+
143
+ ---
144
+
145
+ - **Python:** 3.10+ (see `pyproject.toml`).
146
+ - **Deep dives:** [spec/design/user-guide.md](spec/design/user-guide.md) and [spec/design/utility.md](spec/design/utility.md).
147
+
148
+ ## How to create an extension
149
+
150
+ An extension can be a **full** AIDD methodology, **team** conventions (review rules, codestyle), **scaffolds** for projects that default to AIDD-friendly layouts, **skill-only** bundles, or anything else you can express as declarative files plus optional setup hooks—anything that fits the `extsrc/` layout described in the author guide.
151
+
152
+ **Bootstrap with the creator extension** (install like any other extension after `spawn init`):
153
+
154
+ ```bash
155
+ spawn extension add https://github.com/noant/spawn-ext-creator
156
+ ```
157
+
158
+ **Scaffold an empty extension** with the CLI (requires `spawn init` in the repo you run from — same as other subcommands). This lays out `extsrc/` with a starter `config.yaml`, plus empty `skills/`, `files/`, and `setup/`:
159
+
160
+ ```bash
161
+ spawn extension init --name my-extension
162
+ spawn extension init ./my-extension --name my-extension
163
+ ```
164
+
165
+ **Agent-guided scaffold** with **[spawn-ext-creator](https://github.com/noant/spawn-ext-creator)** (install the extension above, then `spawn ide add <ide>` so skills render into your IDE): invoke the **`spawn-ext-bootstrap`** skill so the agent lays out a fuller extension repo than the bare CLI skeleton—for example:
166
+
167
+ > Use the **spawn-ext-bootstrap** skill to bootstrap a new Spawn extension with stable id `my-extension` under `./my-extension`.
168
+
169
+ Other creator skills (declaring `config.yaml`, skill sources, MCP, verification, etc.) ship under the same extension; see the rendered skill list after install.
170
+
171
+ Read **[spec/design/extension-author-guide.md](spec/design/extension-author-guide.md)** for the full model: required `extsrc/config.yaml`, mapping files under `extsrc/files/`, optional `skills/`, `mcp.json`, `agent-ignore`, `setup/` scripts, and how static vs artifact content is updated on `spawn extension update`.
172
+
173
+ **Minimal mental model:**
174
+
175
+ - `**extsrc/config.yaml`** — `schema`, `version`, stable `**name`** (install path `spawn/.extend/<name>/`), plus `files`, `skills`, ignores, etc.
176
+ - `**extsrc/files/**` — template tree mirrored into the target repo according to `files:` entries.
177
+ - `**spawn extension check . --strict**` — validate before publishing or tagging a release.
178
+
179
+ ## How to add rules without creating an extension
180
+
181
+ Project-local conventions can live under **`spawn/rules/`** without packaging them as an extension. After **`spawn init`**, add any files there (for example `spawn/rules/team.md`); Spawn discovers **every file** under that directory tree.
182
+
183
+ Wire those paths into **`spawn/navigation.yaml`** so mandatory reads stay aligned with what is on disk:
184
+
185
+ ```bash
186
+ spawn rules refresh
187
+ ```
188
+
189
+ That rescans **`spawn/rules/`**, attaches missing rule files under a **`rules`** group inside **`read-required`** (default description **`Local rule file.`** until you edit it), and drops stale entries whose files were deleted (you may see a warning).
190
+
191
+ Rule files can be **mandatory** (**`read-required`**) or **contextual** (**`read-contextual`**). **`spawn rules refresh`** only auto-adds **new** paths into **`read-required` → `rules`**. To keep a rule **contextual**, declare it under **`read-contextual` → `rules`** in **`spawn/navigation.yaml`** with the same shape (`path`, `description`)—once a path appears in either rules list, refresh will not duplicate it into the other tier. You can move entries between **`read-required`** and **`read-contextual`** by editing **`spawn/navigation.yaml`**, then run **`spawn rules refresh`** so both lists stay consistent with files on disk.
192
+
193
+ Extension-backed reads (`ext:` entries) are unrelated—you only maintain **`spawn/rules/**`** plus **`spawn rules refresh`** for repo-local rules.
194
+
195
+ ## License
196
+
197
+ MIT — see [LICENSE](LICENSE).
@@ -4,9 +4,14 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "spawn-cli"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "A minimal installable Python CLI package."
9
+ readme = "README.md"
9
10
  requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ classifiers = [
13
+ "License :: OSI Approved :: MIT License",
14
+ ]
10
15
  dependencies = [
11
16
  "pydantic>=2.0",
12
17
  "ruamel.yaml>=0.18",
@@ -19,6 +24,9 @@ dependencies = [
19
24
  [project.scripts]
20
25
  spawn = "spawn_cli.cli:main"
21
26
 
27
+ [tool.setuptools]
28
+ license-files = ["LICENSE"]
29
+
22
30
  [tool.setuptools.packages.find]
23
31
  where = ["src"]
24
32
 
@@ -9,7 +9,7 @@ from spawn_cli.core import download as dl
9
9
  from spawn_cli.core import low_level as ll
10
10
  from spawn_cli.core import scripts
11
11
  from spawn_cli.core.errors import SpawnError, SpawnWarning
12
- from spawn_cli.ide.registry import get as ide_get
12
+ from spawn_cli.ide.registry import IdeCapabilities, get as ide_get
13
13
  from spawn_cli.io.json_io import load_json
14
14
  from spawn_cli.io.paths import ensure_dir, safe_path
15
15
  from spawn_cli.io.yaml_io import load_yaml, save_yaml
@@ -21,6 +21,37 @@ Read every file listed under `read-required`.
21
21
  Inspect `read-contextual` descriptions and read only files relevant to the current task.
22
22
  """
23
23
 
24
+ MCP_MERGED_NOTICE = (
25
+ "MCP was merged for this workspace; you may need to press Enable in your IDE MCP UI."
26
+ )
27
+
28
+
29
+ def _any_extension_has_skill_files(target_root: Path) -> bool:
30
+ return any(ll.list_skills(target_root, ext) for ext in ll.list_extensions(target_root))
31
+
32
+
33
+ def _any_extension_has_mcp_servers(target_root: Path) -> bool:
34
+ return any(ll.list_mcp(target_root, ext).servers for ext in ll.list_extensions(target_root))
35
+
36
+
37
+ def _warn_capability_gaps(
38
+ ide_key: str,
39
+ caps: IdeCapabilities,
40
+ *,
41
+ needs_skill_render: bool,
42
+ needs_mcp_merge: bool,
43
+ ) -> None:
44
+ if needs_skill_render and caps.skills == "unsupported":
45
+ warnings.warn(
46
+ f"IDE {ide_key!r} does not support skills; skills were skipped",
47
+ SpawnWarning,
48
+ )
49
+ if needs_mcp_merge and caps.mcp in ("unsupported", "external"):
50
+ warnings.warn(
51
+ f"IDE {ide_key!r} has limited MCP support ({caps.mcp})",
52
+ SpawnWarning,
53
+ )
54
+
24
55
 
25
56
  def _require_init(target_root: Path) -> None:
26
57
  if not (target_root / "spawn").is_dir():
@@ -85,6 +116,16 @@ def refresh_skills(target_root: Path, ide: str, extension: str) -> None:
85
116
  ll.save_skills_rendered(target_root, ide, extension, rendered)
86
117
 
87
118
 
119
+ def _refresh_skills_all_extensions_for_ide(target_root: Path, ide: str) -> None:
120
+ """Re-render every extension's skills on *ide*.
121
+
122
+ Skill metadata merges global reads from all installed extensions; peers must
123
+ be rebuilt when any extension's global read set changes.
124
+ """
125
+ for ext in ll.list_extensions(target_root):
126
+ refresh_skills(target_root, ide, ext)
127
+
128
+
88
129
  def remove_skills(target_root: Path, ide: str, extension: str) -> None:
89
130
  _require_init(target_root)
90
131
  prior = ll.get_rendered_skills(target_root, ide, extension)
@@ -92,7 +133,20 @@ def remove_skills(target_root: Path, ide: str, extension: str) -> None:
92
133
  ll.save_skills_rendered(target_root, ide, extension, [])
93
134
 
94
135
 
95
- def refresh_mcp(target_root: Path, ide: str, extension: str) -> None:
136
+ def refresh_mcp(
137
+ target_root: Path,
138
+ ide: str,
139
+ extension: str,
140
+ *,
141
+ emit_mcp_merged_notice: bool = True,
142
+ ) -> list[str]:
143
+ """Merge extension MCP into the IDE project config.
144
+
145
+ Persisted rendered server names from ``adapter.add_mcp`` are returned.
146
+ When ``emit_mcp_merged_notice`` is true and that list is non-empty, prints
147
+ ``MCP_MERGED_NOTICE`` once to stdout (callers that batch refreshes, e.g.
148
+ ``add_ide``, should pass ``emit_mcp_merged_notice=False`` and print once).
149
+ """
96
150
  _require_init(target_root)
97
151
  prior = ll.get_rendered_mcp(target_root, ide, extension)
98
152
  ll.validate_rendered_identity(target_root)
@@ -101,6 +155,9 @@ def refresh_mcp(target_root: Path, ide: str, extension: str) -> None:
101
155
  adapter.remove_mcp(target_root, prior)
102
156
  new_names = adapter.add_mcp(target_root, nm)
103
157
  ll.save_mcp_rendered(target_root, ide, extension, new_names)
158
+ if new_names and emit_mcp_merged_notice:
159
+ print(MCP_MERGED_NOTICE)
160
+ return new_names
104
161
 
105
162
 
106
163
  def remove_mcp(target_root: Path, ide: str, extension: str) -> None:
@@ -116,8 +173,24 @@ def refresh_entry_point(target_root: Path, ide: str) -> None:
116
173
 
117
174
 
118
175
  def refresh_extension_for_ide(target_root: Path, ide: str, extension: str) -> None:
176
+ """Merge *extension* MCP on *ide* and re-render skills for every extension.
177
+
178
+ Mandatory reads in rendered skills are merged from all extensions'
179
+ ``globalRead`` metadata, so updating one extension can require re-rendering
180
+ skills owned by other extensions even when only this extension's MCP changed.
181
+ """
182
+ needs_skill = _any_extension_has_skill_files(target_root)
183
+ needs_mcp = bool(ll.list_mcp(target_root, extension).servers)
184
+ adapter = ide_get(ide)
185
+ dr = adapter.detect(target_root)
186
+ _warn_capability_gaps(
187
+ ide,
188
+ dr.capabilities,
189
+ needs_skill_render=needs_skill,
190
+ needs_mcp_merge=needs_mcp,
191
+ )
119
192
  refresh_mcp(target_root, ide, extension)
120
- refresh_skills(target_root, ide, extension)
193
+ _refresh_skills_all_extensions_for_ide(target_root, ide)
121
194
  refresh_agent_ignore(target_root, ide)
122
195
 
123
196
 
@@ -150,9 +223,19 @@ def refresh_rules_navigation(target_root: Path) -> None:
150
223
 
151
224
 
152
225
  def _refresh_extension_core(target_root: Path, extension: str) -> None:
226
+ needs_skill = _any_extension_has_skill_files(target_root)
227
+ needs_mcp = bool(ll.list_mcp(target_root, extension).servers)
228
+ for ide in ll.list_ides(target_root):
229
+ adapter = ide_get(ide)
230
+ _warn_capability_gaps(
231
+ ide,
232
+ adapter.detect(target_root).capabilities,
233
+ needs_skill_render=needs_skill,
234
+ needs_mcp_merge=needs_mcp,
235
+ )
153
236
  for ide in ll.list_ides(target_root):
154
237
  refresh_mcp(target_root, ide, extension)
155
- refresh_skills(target_root, ide, extension)
238
+ _refresh_skills_all_extensions_for_ide(target_root, ide)
156
239
  for ide in ll.list_ides(target_root):
157
240
  refresh_agent_ignore(target_root, ide)
158
241
  refresh_gitignore(target_root)
@@ -194,6 +277,8 @@ def remove_extension(target_root: Path, extension: str) -> None:
194
277
  for ide in ll.list_ides(target_root):
195
278
  refresh_agent_ignore(target_root, ide)
196
279
  refresh_entry_point(target_root, ide)
280
+ for ide in ll.list_ides(target_root):
281
+ _refresh_skills_all_extensions_for_ide(target_root, ide)
197
282
  scripts.run_after_uninstall_from_snapshot(target_root, extension, after_spec)
198
283
 
199
284
 
@@ -397,21 +482,21 @@ def add_ide(target_root: Path, ide: str) -> None:
397
482
  ll.add_ide_to_list(target_root, ide)
398
483
  adapter = ide_get(ide)
399
484
  dr = adapter.detect(target_root)
400
- caps = dr.capabilities
401
- if caps.skills == "unsupported":
402
- warnings.warn(
403
- f"IDE {ide!r} does not support skills; skills were skipped",
404
- SpawnWarning,
405
- )
406
- if caps.mcp in ("unsupported", "external"):
407
- warnings.warn(
408
- f"IDE {ide!r} has limited MCP support ({caps.mcp})",
409
- SpawnWarning,
410
- )
485
+ _warn_capability_gaps(
486
+ ide,
487
+ dr.capabilities,
488
+ needs_skill_render=_any_extension_has_skill_files(target_root),
489
+ needs_mcp_merge=_any_extension_has_mcp_servers(target_root),
490
+ )
411
491
  refresh_entry_point(target_root, ide)
492
+ merged_any = False
412
493
  for ext in ll.list_extensions(target_root):
413
- refresh_mcp(target_root, ide, ext)
414
- refresh_skills(target_root, ide, ext)
494
+ new_names = refresh_mcp(target_root, ide, ext, emit_mcp_merged_notice=False)
495
+ if new_names:
496
+ merged_any = True
497
+ _refresh_skills_all_extensions_for_ide(target_root, ide)
498
+ if merged_any:
499
+ print(MCP_MERGED_NOTICE)
415
500
  refresh_agent_ignore(target_root, ide)
416
501
 
417
502
 
@@ -435,6 +520,7 @@ def install_extension(target_root: Path, path: str, branch: str | None = None) -
435
520
 
436
521
 
437
522
  __all__ = [
523
+ "MCP_MERGED_NOTICE",
438
524
  "SPAWN_ENTRY_POINT_PROMPT",
439
525
  "_refresh_extension_core",
440
526
  "add_ide",
@@ -0,0 +1,214 @@
1
+ Metadata-Version: 2.4
2
+ Name: spawn-cli
3
+ Version: 0.1.5
4
+ Summary: A minimal installable Python CLI package.
5
+ License: MIT
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pydantic>=2.0
11
+ Requires-Dist: ruamel.yaml>=0.18
12
+ Requires-Dist: filelock>=3.12
13
+ Requires-Dist: httpx>=0.27
14
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
15
+ Requires-Dist: tomli-w>=1.0
16
+ Dynamic: license-file
17
+
18
+ ## What is Spawn?
19
+
20
+ Spawn is a framework for building **AIDD** (AI-driven development) methodologies. It supports both **authoring** methodologies and **applying** them in a project. Within a single repository you can use **several** AIDD methodologies in a coherent way—shared navigation, skills, rules, and tooling stay aligned instead of competing ad hoc setups.
21
+
22
+ ## What is spawn-cli?
23
+
24
+ **spawn-cli** is the utility that manages methodologies installed in your project. In Spawn terminology those packs are **extensions**: versioned content that usually lives in a **Git** repository. The CLI **instantiates** instruction files, process descriptions, rules, agent skills, and wires their behavior together (navigation, IDE-facing outputs, optional lifecycle hooks). Extensions can also declare **MCP servers**, **agent-ignore** patterns, **git-ignore** entries, and similar integration points—see [`spec/design/extension-author-guide.md`](spec/design/extension-author-guide.md).
25
+
26
+ ### How spawn-cli keeps methodologies coherent
27
+
28
+ Several methodologies in one repo stay aligned because Spawn maintains **one shared navigation index**: [`spawn/navigation.yaml`](spec/design/data-structure.md) aggregates mandatory and contextual reads from **every installed extension** plus local [`spawn/rules/`](spec/design/user-guide.md) (refreshed with `spawn rules refresh`). Agents are steered through that file instead of chasing disconnected README fragments.
29
+
30
+ On each install or refresh, the CLI **regenerates IDE-facing artifacts** so skills and entry points stay consistent across extensions: rendered skill bodies include **paths and descriptions** wired from navigation (required reads, contextual hints, rule files), MCP snippets normalize server definitions per IDE adapter, and ignore lists merge without manual copy-paste. The net effect is that methodology files, generated skill links, and repo rules **compose** rather than contradict each other.
31
+
32
+ **Example:** [**spawn-ext-spectask**](https://github.com/noant/spawn-ext-spectask) (Spec-Tasks methodology: spec layout, skills, design index) and [**spawn-ext-creator**](https://github.com/noant/spawn-ext-creator) (authoring flows, including agent-guided extension bootstrap) can be installed in the **same** repository and still share that single index and merged IDE outputs.
33
+
34
+ ## How to install spawn-cli
35
+
36
+ **Recommended:** install `spawn` on your `PATH` with **uv**:
37
+
38
+ ```bash
39
+ uv tool install spawn-cli && spawn --help
40
+ ```
41
+
42
+ Run once without installing (ephemeral **uvx**):
43
+
44
+ ```bash
45
+ uvx --from spawn-cli spawn --help
46
+ ```
47
+
48
+ **Upgrade** the persistent uv tool:
49
+
50
+ ```bash
51
+ uv tool upgrade spawn-cli && spawn --help
52
+ ```
53
+
54
+ Force a fresh resolver for a one-shot run:
55
+
56
+ ```bash
57
+ uvx --refresh --from spawn-cli spawn --help
58
+ ```
59
+
60
+ Additional installers (**pip**, **pipx**, local checkout) and upgrade notes: **[spec/design/user-guide.md](spec/design/user-guide.md#other-installation-options)**.
61
+
62
+ ## How spawn-cli works
63
+
64
+ Run commands from the **root of the repository** you are configuring. Almost every command requires `spawn init` first (it creates the `spawn/` tree). Only one Spawn process should touch a repo at a time (file lock).
65
+
66
+ ### Initialize a repo
67
+
68
+ ```bash
69
+ spawn init
70
+ ```
71
+
72
+ ### IDE adapters
73
+
74
+ For each **supported IDE** adapter, show whether it **looks used in the current repository** and what it can render (e.g. skills, MCP, agent-ignore):
75
+
76
+ ```bash
77
+ spawn ide list-supported-ides
78
+ ```
79
+
80
+ Register or drop IDE keys for **this** repo (examples: `cursor`, `codex`):
81
+
82
+ ```bash
83
+ spawn ide add cursor
84
+ spawn ide add cursor codex
85
+ spawn ide remove codex
86
+ spawn ide list
87
+ ```
88
+
89
+ ### Extensions
90
+
91
+ Add from a Git URL, optional branch (also supports ZIP paths and local directories/archives):
92
+
93
+ ```bash
94
+ spawn extension add https://github.com/noant/spawn-ext-spectask
95
+ spawn extension add https://github.com/noant/spawn-ext-spectask --branch main
96
+ ```
97
+
98
+ Maintain installed packs:
99
+
100
+ ```bash
101
+ spawn extension list
102
+ spawn extension update spectask
103
+ spawn extension reinstall spectask
104
+ spawn extension remove spectask
105
+ spawn extension healthcheck spectask
106
+ ```
107
+
108
+ Authoring helpers (run inside or next to an extension project):
109
+
110
+ ```bash
111
+ spawn extension init ./my-ext --name my-ext
112
+ spawn extension check ./my-ext
113
+ spawn extension check ./my-ext --strict
114
+ spawn extension from-rules ./repo-with-spawn-rules --name my-ext --output ./out
115
+ ```
116
+
117
+ ### Navigation from repo rules
118
+
119
+ After editing files under `spawn/rules/`, refresh mandatory reads in `spawn/navigation.yaml`:
120
+
121
+ ```bash
122
+ spawn rules refresh
123
+ ```
124
+
125
+ ### Batch install from a build manifest
126
+
127
+ `spawn build list` / `spawn build install` take a **build source** (positional argument; there is no implicit default):
128
+
129
+ - **Local directory** whose root contains **`extensions.yaml`**. Spawn resolves the path (e.g. `.` → current working directory) and reads **`<that-directory>/extensions.yaml`** — not a path to the YAML file itself.
130
+ - Otherwise a **Git URL**, **ZIP URL**, or **local path** to a repository tree: Spawn stages it, then looks for **`extensions.yaml`** at that root or, if there is exactly one top-level subdirectory, under that folder (`extensions.yaml not found` if neither applies).
131
+
132
+ Each manifest entry is an extension source; optional per-entry `branch` overrides the CLI default for that row.
133
+
134
+ Minimal `extensions.yaml`:
135
+
136
+ ```yaml
137
+ extensions:
138
+ - path: https://github.com/org/extension-one.git
139
+ branch: main
140
+ - path: https://github.com/org/extension-two.git
141
+ ```
142
+
143
+ Dry-run (prints resolved entries as YAML), then install:
144
+
145
+ ```bash
146
+ # Manifest at ./extensions.yaml (cwd is usually your initialized target repo if you keep it there)
147
+ spawn build list .
148
+ spawn build install .
149
+
150
+ spawn build install /path/to/methodology-bundle
151
+ spawn build install https://github.com/org/team-methodology.git --branch main
152
+ ```
153
+
154
+ The **`--branch`** flag applies when the **build source** is Git (clone revision). Entries that omit `branch` fall back to that value.
155
+
156
+ ### Example extension
157
+
158
+ [spawn-ext-spectask](https://github.com/noant/spawn-ext-spectask) is a concrete extension you can install with `spawn extension add` as shown above.
159
+
160
+ ---
161
+
162
+ - **Python:** 3.10+ (see `pyproject.toml`).
163
+ - **Deep dives:** [spec/design/user-guide.md](spec/design/user-guide.md) and [spec/design/utility.md](spec/design/utility.md).
164
+
165
+ ## How to create an extension
166
+
167
+ An extension can be a **full** AIDD methodology, **team** conventions (review rules, codestyle), **scaffolds** for projects that default to AIDD-friendly layouts, **skill-only** bundles, or anything else you can express as declarative files plus optional setup hooks—anything that fits the `extsrc/` layout described in the author guide.
168
+
169
+ **Bootstrap with the creator extension** (install like any other extension after `spawn init`):
170
+
171
+ ```bash
172
+ spawn extension add https://github.com/noant/spawn-ext-creator
173
+ ```
174
+
175
+ **Scaffold an empty extension** with the CLI (requires `spawn init` in the repo you run from — same as other subcommands). This lays out `extsrc/` with a starter `config.yaml`, plus empty `skills/`, `files/`, and `setup/`:
176
+
177
+ ```bash
178
+ spawn extension init --name my-extension
179
+ spawn extension init ./my-extension --name my-extension
180
+ ```
181
+
182
+ **Agent-guided scaffold** with **[spawn-ext-creator](https://github.com/noant/spawn-ext-creator)** (install the extension above, then `spawn ide add <ide>` so skills render into your IDE): invoke the **`spawn-ext-bootstrap`** skill so the agent lays out a fuller extension repo than the bare CLI skeleton—for example:
183
+
184
+ > Use the **spawn-ext-bootstrap** skill to bootstrap a new Spawn extension with stable id `my-extension` under `./my-extension`.
185
+
186
+ Other creator skills (declaring `config.yaml`, skill sources, MCP, verification, etc.) ship under the same extension; see the rendered skill list after install.
187
+
188
+ Read **[spec/design/extension-author-guide.md](spec/design/extension-author-guide.md)** for the full model: required `extsrc/config.yaml`, mapping files under `extsrc/files/`, optional `skills/`, `mcp.json`, `agent-ignore`, `setup/` scripts, and how static vs artifact content is updated on `spawn extension update`.
189
+
190
+ **Minimal mental model:**
191
+
192
+ - `**extsrc/config.yaml`** — `schema`, `version`, stable `**name`** (install path `spawn/.extend/<name>/`), plus `files`, `skills`, ignores, etc.
193
+ - `**extsrc/files/**` — template tree mirrored into the target repo according to `files:` entries.
194
+ - `**spawn extension check . --strict**` — validate before publishing or tagging a release.
195
+
196
+ ## How to add rules without creating an extension
197
+
198
+ Project-local conventions can live under **`spawn/rules/`** without packaging them as an extension. After **`spawn init`**, add any files there (for example `spawn/rules/team.md`); Spawn discovers **every file** under that directory tree.
199
+
200
+ Wire those paths into **`spawn/navigation.yaml`** so mandatory reads stay aligned with what is on disk:
201
+
202
+ ```bash
203
+ spawn rules refresh
204
+ ```
205
+
206
+ That rescans **`spawn/rules/`**, attaches missing rule files under a **`rules`** group inside **`read-required`** (default description **`Local rule file.`** until you edit it), and drops stale entries whose files were deleted (you may see a warning).
207
+
208
+ Rule files can be **mandatory** (**`read-required`**) or **contextual** (**`read-contextual`**). **`spawn rules refresh`** only auto-adds **new** paths into **`read-required` → `rules`**. To keep a rule **contextual**, declare it under **`read-contextual` → `rules`** in **`spawn/navigation.yaml`** with the same shape (`path`, `description`)—once a path appears in either rules list, refresh will not duplicate it into the other tier. You can move entries between **`read-required`** and **`read-contextual`** by editing **`spawn/navigation.yaml`**, then run **`spawn rules refresh`** so both lists stay consistent with files on disk.
209
+
210
+ Extension-backed reads (`ext:` entries) are unrelated—you only maintain **`spawn/rules/**`** plus **`spawn rules refresh`** for repo-local rules.
211
+
212
+ ## License
213
+
214
+ MIT — see [LICENSE](LICENSE).
@@ -1,3 +1,4 @@
1
+ LICENSE
1
2
  README.md
2
3
  pyproject.toml
3
4
  src/spawn_cli/__init__.py
spawn_cli-0.1.3/PKG-INFO DELETED
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: spawn-cli
3
- Version: 0.1.3
4
- Summary: A minimal installable Python CLI package.
5
- Requires-Python: >=3.10
6
- Requires-Dist: pydantic>=2.0
7
- Requires-Dist: ruamel.yaml>=0.18
8
- Requires-Dist: filelock>=3.12
9
- Requires-Dist: httpx>=0.27
10
- Requires-Dist: tomli>=2.0; python_version < "3.11"
11
- Requires-Dist: tomli-w>=1.0
spawn_cli-0.1.3/README.md DELETED
@@ -1,114 +0,0 @@
1
- # spawn-cli
2
-
3
- Installable CLI **`spawn`** for initializing and managing Spawn metadata (extensions, IDE adapters, navigation) in a repository.
4
-
5
- ## Quick start (uv)
6
-
7
- Install `spawn` on your `PATH` (persistent **uv** tool environment):
8
-
9
- ```bash
10
- uv tool install spawn-cli && spawn --help
11
- ```
12
-
13
- Run once without installing a tool (ephemeral **uvx**):
14
-
15
- ```bash
16
- uvx --from spawn-cli spawn --help
17
- ```
18
-
19
- ## Upgrade (uv)
20
-
21
- Upgrade the persistent tool:
22
-
23
- ```bash
24
- uv tool upgrade spawn-cli && spawn --help
25
- ```
26
-
27
- Latest resolver result for a one-shot run:
28
-
29
- ```bash
30
- uvx --refresh --from spawn-cli spawn --help
31
- ```
32
-
33
- ---
34
-
35
- - **Python:** 3.10+ (see `pyproject.toml`).
36
- - **Usage:** run from the **root of the repository** you configure; most commands need `spawn init` first.
37
-
38
- ## Install
39
-
40
- The PyPI package name is **`spawn-cli`**; the console script is **`spawn`**.
41
-
42
- ### From PyPI
43
-
44
- ```bash
45
- pip install spawn-cli
46
- spawn --help
47
- ```
48
-
49
- Isolated install:
50
-
51
- ```bash
52
- pipx install spawn-cli
53
- spawn --help
54
- ```
55
-
56
- With **uv** (tool on `PATH`):
57
-
58
- ```bash
59
- uv tool install spawn-cli
60
- spawn --help
61
- ```
62
-
63
- One-shot without installing into an environment:
64
-
65
- ```bash
66
- uvx --from spawn-cli spawn --help
67
- ```
68
-
69
- ### From a local checkout
70
-
71
- ```bash
72
- cd /path/to/spawn-cli
73
- uv sync
74
- uv run spawn --help
75
- ```
76
-
77
- Or editable install with **pip**:
78
-
79
- ```bash
80
- cd /path/to/spawn-cli
81
- pip install -e .
82
- spawn --help
83
- ```
84
-
85
- ## Upgrade
86
-
87
- Use the same installer you used for the initial install. **If you use uv only, see [Upgrade (uv)](#upgrade-uv) at the top.**
88
-
89
- **pip** (current environment):
90
-
91
- ```bash
92
- pip install --upgrade spawn-cli
93
- spawn --help
94
- ```
95
-
96
- **pipx**:
97
-
98
- ```bash
99
- pipx upgrade spawn-cli
100
- spawn --help
101
- ```
102
-
103
- **Local checkout:** pull changes, then reinstall so the editable install sees updates:
104
-
105
- ```bash
106
- cd /path/to/spawn-cli
107
- git pull
108
- uv sync
109
- # or: pip install -e .
110
- ```
111
-
112
- ## More
113
-
114
- Design and command details: `spec/design/user-guide.md` and `spec/design/utility.md`.
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: spawn-cli
3
- Version: 0.1.3
4
- Summary: A minimal installable Python CLI package.
5
- Requires-Python: >=3.10
6
- Requires-Dist: pydantic>=2.0
7
- Requires-Dist: ruamel.yaml>=0.18
8
- Requires-Dist: filelock>=3.12
9
- Requires-Dist: httpx>=0.27
10
- Requires-Dist: tomli>=2.0; python_version < "3.11"
11
- Requires-Dist: tomli-w>=1.0
File without changes
File without changes