skillset 0.0.1 → 0.1.0-beta.1

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 (75) hide show
  1. package/README.md +319 -0
  2. package/docs/README.md +11 -0
  3. package/docs/adrs/0000-source-first-loadouts.md +56 -0
  4. package/docs/adrs/0001-root-compile-policy.md +70 -0
  5. package/docs/adrs/README.md +18 -0
  6. package/docs/adrs/decision-map.json +93 -0
  7. package/docs/adrs/drafts/20260604-agent-source-model.md +90 -0
  8. package/docs/adrs/drafts/20260604-changelog-and-versioning.md +114 -0
  9. package/docs/adrs/drafts/20260604-feature-reference-and-schema-registry.md +332 -0
  10. package/docs/adrs/drafts/20260604-first-class-sets.md +187 -0
  11. package/docs/adrs/drafts/20260604-global-xdg-managed-installs-and-sync.md +89 -0
  12. package/docs/adrs/drafts/20260604-model-and-reasoning-alias-profiles.md +217 -0
  13. package/docs/adrs/drafts/20260604-reviewed-settings-suggestions.md +190 -0
  14. package/docs/adrs/drafts/README.md +24 -0
  15. package/docs/adrs/drafts/decision-map.json +194 -0
  16. package/docs/adrs/template.md +38 -0
  17. package/docs/features/README.md +70 -0
  18. package/docs/features/agents.md +74 -0
  19. package/docs/features/apps.md +32 -0
  20. package/docs/features/build-scopes.md +59 -0
  21. package/docs/features/commands.md +31 -0
  22. package/docs/features/executables.md +34 -0
  23. package/docs/features/feature-source-pointers.md +60 -0
  24. package/docs/features/hooks.md +34 -0
  25. package/docs/features/instructions.md +35 -0
  26. package/docs/features/lsp-servers.md +32 -0
  27. package/docs/features/mcp-servers.md +34 -0
  28. package/docs/features/monitors.md +33 -0
  29. package/docs/features/output-styles.md +31 -0
  30. package/docs/features/plugins.md +36 -0
  31. package/docs/features/resources.md +45 -0
  32. package/docs/features/settings.md +32 -0
  33. package/docs/features/skills.md +36 -0
  34. package/docs/features/target-native-islands.md +54 -0
  35. package/docs/features/themes.md +31 -0
  36. package/docs/features/tool-intent.md +36 -0
  37. package/docs/layout.md +372 -0
  38. package/docs/target-surfaces.md +156 -0
  39. package/docs/tenets.md +137 -0
  40. package/package.json +51 -51
  41. package/src/authoring.ts +255 -0
  42. package/src/build.ts +537 -0
  43. package/src/cli.ts +541 -0
  44. package/src/config.ts +555 -0
  45. package/src/hooks.ts +128 -0
  46. package/src/import.ts +509 -0
  47. package/src/lint.ts +319 -0
  48. package/src/path.ts +40 -0
  49. package/src/preprocess.ts +166 -0
  50. package/src/render.ts +2028 -0
  51. package/src/resolver.ts +914 -0
  52. package/src/resources.ts +483 -0
  53. package/src/setup.ts +211 -0
  54. package/src/skill-policy.ts +547 -0
  55. package/src/structured-output.ts +147 -0
  56. package/src/types.ts +187 -0
  57. package/src/versioning.ts +78 -0
  58. package/src/yaml.ts +79 -0
  59. package/dist/hook.js +0 -14
  60. package/dist/index.js +0 -110
  61. package/dist/types/cache/index.d.ts +0 -9
  62. package/dist/types/cli.d.ts +0 -1
  63. package/dist/types/config/index.d.ts +0 -29
  64. package/dist/types/doctor.d.ts +0 -12
  65. package/dist/types/format/index.d.ts +0 -3
  66. package/dist/types/hook.d.ts +0 -1
  67. package/dist/types/hooks/hook-runner.d.ts +0 -1
  68. package/dist/types/index.d.ts +0 -2
  69. package/dist/types/indexer/index.d.ts +0 -6
  70. package/dist/types/logger/index.d.ts +0 -2
  71. package/dist/types/resolver/index.d.ts +0 -3
  72. package/dist/types/tokenizer/index.d.ts +0 -2
  73. package/dist/types/tree/index.d.ts +0 -24
  74. package/dist/types/tree/markdown.d.ts +0 -18
  75. package/dist/types/types.d.ts +0 -43
package/README.md ADDED
@@ -0,0 +1,319 @@
1
+ # Skillset
2
+
3
+ `skillset` compiles portable agent plugin and skill source into target-native Claude and Codex outputs.
4
+
5
+ It is developed as public source under Outfitter. The npm package is published under the `beta` tag while the compiler contract is still settling; `latest` remains reserved for stable releases.
6
+
7
+ This repo also self-hosts a small `.skillset/` source tree:
8
+
9
+ - standalone internal skills for developing the compiler in Claude and Codex;
10
+ - one generated `skillset` plugin that teaches agents how to use the compiler.
11
+
12
+ ## Docs
13
+
14
+ - [Skillset Design Tenets](docs/tenets.md): the slow-moving doctrine for source-first loadout authoring and target-native lowering.
15
+ - [Architecture Decision Records](docs/adrs/README.md): accepted and proposed decisions for source vocabulary, lowering policy, and generated-output promises.
16
+ - [Feature Reference](docs/features/README.md): source feature support, target adapter status, and future-only surfaces.
17
+ - [Skillset Docs](docs/README.md): the docs map.
18
+ - [Layout](docs/layout.md): the current source layout, output shape, and compiler behavior reference.
19
+
20
+ ## Usage
21
+
22
+ From a content repo:
23
+
24
+ ```bash
25
+ skillset init # preview a minimal .skillset/ scaffold for the current repo
26
+ skillset create # preview a new my-skillset source repo scaffold
27
+ skillset build # plan generated changes without writing
28
+ skillset build --yes # write generated outputs
29
+ skillset lint # source authoring diagnostics
30
+ skillset check # fail if generated outputs are stale
31
+ skillset diff # show pending generated changes without writing
32
+ skillset explain <path> # explain a source or generated path (lowering, lock provenance, hashes)
33
+ skillset doctor # aggregate lint issues + drift + warnings
34
+ ```
35
+
36
+ `init`, `create`, and `build` are plan-first: they print pending filesystem changes and write only with `--yes`; `--dry-run` always prevents writes, even when paired with `--yes`. `--scope repo`, `--scope plugins`, `--scope project`, and combinations filter generated destinations for build, diff, check, list, and explain; `--scope user` is accepted but currently has no build outputs. `diff`, `explain`, and `doctor` are read-only authoring aids: they never write generated outputs, install, trust, publish, or mutate user-level config. `diff`, `check`, and `doctor` report missing managed outputs separately from new outputs so intentional deletion and stale locks are visible. `explain` accepts either a source path (e.g. `.skillset/skills/foo/SKILL.md`) or a generated output path and reports how it lowers, its lock entry, target state, and source/output hashes. `doctor` exits non-zero when it finds lint issues, drift, or a build error.
37
+
38
+ The default contract is:
39
+
40
+ - source root: `.skillset/`
41
+ - root config: `.skillset/config.yaml`
42
+ - plugin source: `.skillset/plugins/<plugin-name>/`
43
+ - standalone skill source: `.skillset/skills/<skill-name>/`
44
+ - instruction source: `.skillset/instructions/**/*.md` (`.skillset/rules/**/*.md` is a compatibility alias)
45
+ - Claude plugin repo output: `plugins-claude/`
46
+ - Codex plugin repo output: `plugins-codex/`
47
+ - Claude standalone skill output: `.claude/skills`
48
+ - Codex standalone skill output: `.agents/skills`
49
+ - Claude rule output: `.claude/rules`
50
+ - Codex rule output: `AGENTS.md` files at derived repo directories
51
+
52
+ Use explicit paths when building another repo:
53
+
54
+ ```bash
55
+ skillset build --root /path/to/content-repo
56
+ skillset check --root /path/to/content-repo
57
+ skillset build --root /tmp/example --source custom-source --dist generated
58
+ ```
59
+
60
+ `--dist` is a compatibility override for plugin outputs. Without it, plugin outputs default to `plugins-claude/` and `plugins-codex/`. Source config can also set explicit output roots in target output objects such as `claude.plugins.path` or `codex.skills.path`.
61
+
62
+ ## Setup
63
+
64
+ Initialize Skillset source in an existing repo:
65
+
66
+ ```bash
67
+ skillset init --root /path/to/content-repo
68
+ skillset init --root /path/to/content-repo --targets claude --with-agents --with-islands --yes
69
+ ```
70
+
71
+ Create a new source repo, defaulting to `my-skillset` under the current directory:
72
+
73
+ ```bash
74
+ skillset create
75
+ skillset create team-loadout --name team-loadout --targets claude,codex --yes
76
+ ```
77
+
78
+ For a user-global source checkout, `skillset create --global` defaults to `~/.skillset/src`. This is still Skillset-owned source, not a live Claude or Codex runtime directory. The corresponding preview/build area is documented as `~/.skillset/build`, but setup does not create it or write to `~/.claude`, `~/.codex`, or `.agents`. The beta package can be run through package managers with commands such as `npx skillset@beta create` or `bunx skillset@beta create`; setup still routes through the same plan-first `create` flow.
79
+
80
+ Setup commands create only source files: `.skillset/config.yaml`, `.skillset/src/.gitkeep`, and optional `.skillset/instructions/project.md`, `.skillset/src/agents/`, `.skillset/src/claude/`, and `.skillset/src/codex/rules/` placeholders when requested. The generated config uses `compile.targets`; target adapter config still belongs in `claude` and `codex` blocks or root `defaults.<target>.<surface>`.
81
+
82
+ ## Import
83
+
84
+ Seed source from an existing skill, skills root, plugin, or plugin repository. The happy path infers the kind from the path:
85
+
86
+ ```bash
87
+ skillset import /path/to/skill-dir --root /path/to/content-repo
88
+ skillset import /path/to/SKILL.md --root /path/to/content-repo
89
+ skillset import /path/to/skills-root --kind skills --root /path/to/content-repo
90
+ skillset import /path/to/plugin-dir --root /path/to/content-repo
91
+ skillset import /path/to/plugins-root --kind plugins --root /path/to/content-repo
92
+ ```
93
+
94
+ The explicit compatibility form still works:
95
+
96
+ ```bash
97
+ skillset import skill /path/to/skill-dir --root /path/to/content-repo --name custom-name
98
+ skillset import plugin /path/to/plugin-dir --root /path/to/content-repo
99
+ ```
100
+
101
+ Provider shortcuts import user-global skills from the matching local skill root:
102
+
103
+ ```bash
104
+ skillset import claude --root /path/to/content-repo # ~/.claude/skills
105
+ skillset import codex --root /path/to/content-repo # ~/.codex/skills
106
+ skillset import agents --root /path/to/content-repo # ~/.agents/skills
107
+ ```
108
+
109
+ Imports copy files into `.skillset/skills/<name>` or `.skillset/plugins/<name>`. Passing a `SKILL.md` path imports the full containing skill directory, including sibling `references/`, `scripts/`, `assets/`, `agents/`, and other sidecars. Skills-root imports de-dupe symlinked directories by real path, so the same global skill is not imported twice when `.claude/skills`, `.codex/skills`, and `.agents/skills` point at one another. Plugin imports write plugin-local `skillset.yaml`; when importing a native Claude/Codex generated plugin that only has `.claude-plugin/plugin.json` or `.codex-plugin/plugin.json`, Skillset synthesizes a minimal source `skillset.yaml` from the native manifest while preserving the native manifest files as imported context. Import does not install, trust, symlink, publish, mutate registries, or change user-level Claude/Codex config.
110
+
111
+ Import is a safe bridge, not a lossy copier. It returns a report — printed by the CLI — summarizing the copied files, the source fields it recognized, target-native fields preserved verbatim (e.g. Claude `allowed-tools`, `disable-model-invocation`), unrecognized fields kept as-is, warnings, and the next checks to run (`skillset lint`, `build`, `check`). Target-native and unknown frontmatter is preserved rather than dropped, so nothing is silently lost; the warnings point you at fields worth moving to a portable source key or a `claude`/`codex` block. Import never overwrites an existing source — remove it or import under a different `--name`.
112
+
113
+ ## Source Contract
114
+
115
+ Root source metadata lives at `.skillset/config.yaml`.
116
+
117
+ Each plugin lives at `.skillset/plugins/<plugin-name>/` and has its own `skillset.yaml`. Portable plugin fields live under `skillset`; target-specific overrides live under top-level `claude` and `codex` blocks. Skill source frontmatter can use top-level `title`, `summary`, `description`, `version`, `resources`, `implicit_invocation`, `allowed_tools`, and the source-only `tools` escape map; the compiler derives target-native `name`, `description`, generated metadata, Claude frontmatter, Codex `agents/openai.yaml` policy where supported, and skill-local copies of declared resources.
118
+
119
+ Use `skillset.name` as the stable machine identity. `skillset.id` is accepted as a compatibility alias for older source. Use root `compile.targets` for provider selection, and do not use bare top-level `targets:`. `compile.build` defaults to `updated` and accepts `all`; CLI `--updated` and `--all` override config for the current command and the resolved mode is recorded in lock metadata. `compile.skillset.metadata: false` suppresses Skillset's generated skill frontmatter metadata. `compile.unsupported` currently defaults to `error`; softer modes are reserved until warning, skip, or force provenance is implemented.
120
+
121
+ Target adapter configuration stays in `claude` and `codex` blocks. Root `defaults.<target>.<surface>` is shorthand for target defaults, and `claude.defaults.<surface>` / `codex.defaults.<surface>` is the canonical target-local form:
122
+
123
+ ```yaml
124
+ defaults:
125
+ codex:
126
+ skills:
127
+ model: gpt-5
128
+
129
+ claude:
130
+ projectRoot: .claude
131
+ userRoot: ~/.claude
132
+ defaults:
133
+ skills:
134
+ model: sonnet
135
+ ```
136
+
137
+ Defaults fill omitted target options for the named surface (`agents`, `instructions`, `plugins`, or `skills`). Exact file-level `claude` / `codex` fields win over plugin defaults, plugin defaults win over root defaults, and target-specific fields win over shared portable fields at render time. A top-level skill or project-agent `model` is source-only and warns in v1 unless every enabled target has a target-specific model from defaults or an override; use `claude.model`, `codex.model`, or target defaults instead.
138
+
139
+ Generated output strips source-only keys such as `skillset`, `claude`, `codex`, `agents`, `resources`, `implicit_invocation`, `allowed_tools`, `tools`, `model`, `defaults`, and `targets`. Generated skills receive only lightweight metadata unless `compile.skillset.metadata: false` suppresses it:
140
+
141
+ ```yaml
142
+ metadata:
143
+ version: 0.1.0
144
+ generated: skillset@0.1.0
145
+ ```
146
+
147
+ Generated roots also receive `.skillset.lock` files with deterministic provenance and hashes.
148
+
149
+ ## Shared Resources
150
+
151
+ Use `.skillset/shared/` for root shared inputs and `.skillset/plugins/<plugin-name>/shared/` for plugin-local shared inputs. Shared inputs are not copied wholesale. A skill opts into exact files or directories with source-only `resources` frontmatter:
152
+
153
+ ```yaml
154
+ resources:
155
+ references:
156
+ - shared:references/common.md
157
+ - plugin:references/plugin.md
158
+ scripts:
159
+ - plugin:scripts/check.sh
160
+ templates:
161
+ - from: shared:templates/report.md
162
+ to: templates/report.md
163
+ ```
164
+
165
+ `shared:` points at `.skillset/shared/`; `root:` is accepted as an alias. `plugin:` points at `.skillset/plugins/<plugin-name>/shared/` and is valid only for plugin-bound skills. Grouped resources default to skill-local target paths such as `references/common.md`, `scripts/check.sh`, `assets/...`, or `templates/...`; use `from` / `to` when the output path should differ.
166
+
167
+ Generated Claude and Codex skills receive the copied files beside `SKILL.md`, so links and script references stay skill-root-relative. Markdown links that use declared `shared:` or `plugin:` resource URLs are rewritten to the generated skill-local path; undeclared shared resource links fail the build with a suggested `resources` entry. When a resource uses a custom `to`, a bare (schemeless) link to the resource's source path is ambiguous and fails the build with a diagnostic: link to the emitted target path or use the `shared:`/`plugin:` resource URL instead. Resource mappings cannot write outside the generated skill directory or overwrite `SKILL.md`, generated Codex sidecars, or skill-local files. Resource contents participate in `.skillset.lock` hashes and `skillset check`.
168
+
169
+ `skillset lint` adds earlier, actionable diagnostics: undeclared resource links (with a suggested entry), skill bodies that depend on plugin-root script paths instead of skill-local copies, and declared `scripts/` resources whose source file is missing an executable bit.
170
+
171
+ `skillset.schema` marks the source-contract schema and is separate from content versions. It is an optional integer (currently `1`) on root and plugin config that defaults to the current schema when absent; future or non-integer values fail the build. Source `skillset.version` and skill `version` fields must be semantic versions. `skillset check` reports explicit version drift when a generated plugin manifest or skill `metadata.version` is stale.
172
+
173
+ Plugin lock entries include the emitted plugin version plus `includedSkills`, `skippedSkills`, and `targetState`. When a target-specific skill version bump does not affect the other target's generated skill or manifest, that target's lock can still explain the intentionally skipped source version.
174
+
175
+ Portable skill policy can be shared or targeted:
176
+
177
+ ```yaml
178
+ implicit_invocation:
179
+ claude: false
180
+ codex: false
181
+ allowed_tools:
182
+ claude:
183
+ - Read
184
+ - Grep
185
+ codex: false
186
+ ```
187
+
188
+ `implicit_invocation` lowers to Claude `disable-model-invocation` and Codex `agents/openai.yaml` `policy.allow_implicit_invocation`. `allowed_tools` lowers to Claude `allowed-tools`; Codex has no confirmed skill-local allowed-tools equivalent, so Codex-enabled source must omit `allowed_tools.codex` or set it to `false`.
189
+
190
+ Portable tool policy uses the `tool_intent` block (the legacy `tools` key is a compatibility alias; setting both fails). The name reflects authoring *intent*, not a target-enforced sandbox. Target-native escape hatches use underscore keys: shared escapes live under top-level `tool_intent`, and target-local escapes live under `claude.tool_intent` or `codex.tool_intent`:
191
+
192
+ ```yaml
193
+ tool_intent:
194
+ allow:
195
+ read:
196
+ - docs/**
197
+ search: true
198
+ shell:
199
+ - git status
200
+ - prefix:
201
+ - bun
202
+ - run
203
+ web_fetch:
204
+ domains:
205
+ - example.com
206
+ mcp:
207
+ linear:
208
+ tools:
209
+ - issues.*
210
+ deny:
211
+ edit:
212
+ - secrets/**
213
+ _allow:
214
+ claude:
215
+ - Read
216
+ codex:
217
+ mcp:
218
+ linear:
219
+ tools:
220
+ - issues.*
221
+ claude:
222
+ tool_intent:
223
+ _allow:
224
+ - "NewClaudeTool(project:*)"
225
+ - rule: "Bash(newcli safe *)"
226
+ codex:
227
+ tool_intent:
228
+ _deny:
229
+ mcp:
230
+ linear:
231
+ tools:
232
+ - experimental.delete
233
+ ```
234
+
235
+ Portable `tool_intent.allow` and `tool_intent.deny` accept only known keys: `read`, `search`, `write`, `edit`, `shell`, `web_fetch`, `web_search`, and `mcp`. Unknown keys fail lint/build. Portable `allow` / `deny` belongs in the source top-level `tool_intent` block; target-local `claude.tool_intent` and `codex.tool_intent` accept only `_allow` / `_deny` escape keys. The legacy `tools` key remains a compatibility alias at both levels, and setting `tool_intent` and `tools` together fails with a conflict.
236
+
237
+ `tool_intent` is intent and metadata, not a portable security boundary. Claude lowers portable entries to `allowed-tools` and `disallowed-tools`, which are **preapproval / no-prompt** hints — they reduce permission prompts for listed tools, not a sandbox that blocks everything else. Codex has no documented skill-local enforcement surface, so Codex preserves portable intent in generated `.skillset.tools.yaml` metadata without mutating user-level Codex policy or trust. Claude `_allow` and `_deny` entries lower to native rules too. Codex `_allow` and `_deny` entries emit to `.skillset.tools.yaml` under `target_native`, so they are committed, locked, and reviewable.
238
+
239
+ ## Instructions
240
+
241
+ Use `.skillset/instructions/**/*.md` for repo instructions that should become Claude rules and Codex `AGENTS.md` files. `.skillset/rules/**/*.md` is a compatibility alias that still builds but warns; consolidating both directories fails the build.
242
+
243
+ ```yaml
244
+ ---
245
+ paths:
246
+ - docs/**/*.md
247
+ ---
248
+
249
+ # Docs Rules
250
+
251
+ - Keep docs concise and current.
252
+ ```
253
+
254
+ The compiler preserves the source hierarchy when writing Claude rules, so `.skillset/instructions/docs/writing.md` becomes `.claude/rules/docs/writing.md`. `paths` frontmatter is kept for Claude and stripped from Codex output. Generated output is byte-identical whether the source lives in `instructions/` or the `rules/` compatibility alias.
255
+
256
+ For Codex, `skillset` derives the nearest useful `AGENTS.md` destination from each path pattern. `docs/**/*.md` writes `docs/AGENTS.md`; `**/*.ts` scans matching repo files and writes to the lowest common directory, such as `src/AGENTS.md` when matching TypeScript files live under `src/`. Multiple source rules that land at the same destination are concatenated deterministically, each preceded by a `<!-- source: ... -->` boundary comment naming its source. Codex truncates `AGENTS.md` beyond `project_doc_max_bytes` (32 KiB default); `skillset build`/`check` warns when a generated `AGENTS.md` exceeds it so you can split instructions across nested directories or raise the limit.
257
+
258
+ Skill and instruction Markdown bodies use Skillset preprocessing before target serialization. `{{this.<field>}}` reads a simple string field from the current document's shared frontmatter; missing fields fail with the source path and field name. Instructions also support Skillset build-time variables when prose needs target-correct paths:
259
+
260
+ ```md
261
+ - Review {{this.description}}.
262
+ - Run checks from {{skillset.repo_root}}.
263
+ - This generated instruction file lives under {{skillset.output_dir}}.
264
+ - Source rule: {{skillset.source_rule}}.
265
+ ```
266
+
267
+ `{{skillset.repo_root}}` renders as the relative path from the generated file directory back to the repository root, or `.` at the root. `{{skillset.output_dir}}` renders as the generated file directory relative to the repository root, or `.` at the root. `{{skillset.source_rule}}` renders as the source rule path. Unknown `skillset.*` variables fail the build.
268
+
269
+ Partials use `{{> shared:path.md}}`, `{{> plugin:path.md}}`, or a file path relative to the current source file. Shared partials read from `.skillset/shared/`; plugin partials read from the current plugin's `.skillset/plugins/<plugin>/shared/` and are valid only for plugin-bound source. Missing fields, missing partials, path traversal, and plugin partials outside the current plugin fail loudly. Preprocessing dependencies participate in lock hashes and `skillset explain` output.
270
+
271
+ Set `skillset.preprocess: false` in source frontmatter when a Markdown body should keep literal braces. The control is source-only and is stripped from generated output.
272
+
273
+ Skillset-owned variables use `{{skillset.lower_snake_case}}` to match the source YAML naming style. Target-native variables such as Claude `$ARGUMENTS` and `${CLAUDE_*}` remain target-specific and are not rendered by the preprocessing layer.
274
+
275
+ Rule target toggles use the same top-level target keys:
276
+
277
+ ```yaml
278
+ ---
279
+ paths:
280
+ - docs/**/*.md
281
+ claude: true
282
+ codex: false
283
+ ---
284
+ ```
285
+
286
+ Generated Codex `AGENTS.md` files are tracked by the root `.skillset.lock`. The build refuses to overwrite an unmanaged `AGENTS.md`, so existing hand-written guidance stays protected until it is moved into `.skillset/instructions` or removed deliberately.
287
+
288
+ `codex: symlink` is intentionally not implemented yet. Path-scoped Claude rules need YAML `paths` frontmatter, and a direct symlink would expose that control block to Codex as instructions.
289
+
290
+ ## Target-Specific Plugin Surfaces
291
+
292
+ Portable project agents live under `.skillset/src/agents/*.md`. They lower to Claude `.claude/agents/<resolved-name>.md` and Codex `.codex/agents/<resolved-name>.toml`, require `description` plus a body, support shared `skills` and `initialPrompt`, and keep target-native fields under `claude` and `codex` blocks. Codex `skills` become a deterministic `developer_instructions` preface; configure it with `codex.defaults.agents.skillsPrefaceTemplate` or `defaults.codex.agents.skillsPrefaceTemplate`. Project-agent outputs are tracked in the root `.skillset.lock` and are visible through `skillset list` / `skillset explain`.
293
+
294
+ Plugin companion directories are target-native. Claude receives `commands/`, `agents/`, `hooks/hooks.json`, `.mcp.json`, `.lsp.json`, `output-styles/`, `themes/`, `monitors/`, `assets/`, `scripts/`, and `src/` when those source paths exist; the generated manifest declares each with its documented field (`lspServers`, `outputStyles`, `experimental.themes`, `experimental.monitors`). Codex receives `hooks/hooks.json`, `.mcp.json`, `.app.json`, `assets/`, `scripts/`, and `src/`; Claude plugin `agents/` is not copied into Codex plugin output, and a Codex-enabled plugin with `agents/` fails loudly because Codex plugins do not document that component. Feature keys can own repo source pointers directly: `mcp.source: repo:path/to/mcp.json` copies a repo-owned MCP file to `.mcp.json` for enabled plugin targets, and `bin.source: repo:path/to/bin` copies a repo-owned directory to Claude plugin `bin/`. `mcp: false` or `bin: false` disables conventional discovery, while absent keys auto-discover conventional `.mcp.json` and Claude `bin/` paths. Codex plugin `bin` output is unsupported and fails loudly when enabled. Pass-through paths are copied as opaque content unless a feature owns validation. Plugin-root `settings.json` is target-native but future-only for reviewed settings suggestion workflows. Build still does not install, trust, enable, or mutate user-level Claude/Codex config.
295
+
296
+ Hook files are emitted as definitions only. `skillset` does not install, trust, or enable hooks in user-level Claude/Codex config. Both targets emit hooks at the documented default `hooks/hooks.json` with a top-level `{ "hooks": { ... } }` object, sourced from a shared `hooks/hooks.json`. A legacy root `hooks.json` is a Codex compatibility source — it still builds (flat event maps are normalized and emitted to `hooks/hooks.json`) but warns. The compiler does not auto-lower Claude hooks into Codex hooks.
297
+
298
+ Hook definitions are checked for target compatibility. Codex hook files must use Codex-supported events — `PreToolUse`, `PermissionRequest`, `PostToolUse`, `PreCompact`, `PostCompact`, `SessionStart`, `SubagentStart`, `SubagentStop`, `UserPromptSubmit`, `Stop` — and synchronous `command` handlers only, because Codex parses but skips prompt handlers, agent handlers, and `async: true` command handlers. Unsupported Codex events or skipped handler forms fail both `skillset build` and `skillset lint`. Claude hook validation stays broad (JSON-object shape) because Claude's hook surface is wider and still evolving.
299
+
300
+ ## Self-Hosted Outputs
301
+
302
+ In this repo, run:
303
+
304
+ ```bash
305
+ bun run skillset:build
306
+ bun run skillset:lint
307
+ bun run skillset:check
308
+ bun run check
309
+ ```
310
+
311
+ Self-hosted source lives under `.skillset/`. Generated outputs are:
312
+
313
+ - `.claude/skills/skillset-claude-development`
314
+ - `.agents/skills/skillset-codex-development`
315
+ - `.claude/rules` when source rules exist
316
+ - `plugins-claude/plugins/skillset`
317
+ - `plugins-codex/plugins/skillset`
318
+
319
+ These are repo-local generated artifacts. Do not symlink them into global Claude/Codex config or publish them as part of normal compiler development.
package/docs/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # Skillset Docs
2
+
3
+ This directory holds durable documentation for the local Skillset compiler.
4
+
5
+ - [Tenets](tenets.md): the slow-moving doctrine for how Skillset makes source-first Claude/Codex loadouts easier to author and safer to lower.
6
+ - [Architecture Decision Records](adrs/README.md): accepted decisions for source vocabulary, target lowering, compiler promises, and authoring workflows. Draft decisions live under [adrs/drafts](adrs/drafts/README.md).
7
+ - [Feature Reference](features/README.md): the support registry layer for source features, target adapters, future-only surfaces, and feature-specific provenance.
8
+ - [Layout](layout.md): the current source layout, generated output shape, shared-resource behavior, rules/instructions lowering, hooks, skill policy, and import flow.
9
+ - [Target Surfaces](target-surfaces.md): the evidence matrix mapping Skillset source to Claude/Codex target surfaces, with support vocabulary and live-doc verification dates. Golden manifest tests pin the shapes it claims.
10
+
11
+ When changing the source contract, read the tenets first, check ADRs for prior decisions, use the feature reference for support shape, and use the layout reference for current behavior.
@@ -0,0 +1,56 @@
1
+ ---
2
+ id: 0
3
+ slug: source-first-loadouts
4
+ title: Source-First Loadouts
5
+ status: accepted
6
+ created: 2026-06-04
7
+ updated: 2026-06-04
8
+ owners: ['[galligan](https://github.com/galligan)']
9
+ ---
10
+
11
+ # ADR-0000: Source-First Loadouts
12
+
13
+ ## Context
14
+
15
+ Skillset exists because authoring parallel Claude and Codex loadouts by hand creates avoidable drift. The same skill, instruction, hook definition, or plugin intent can end up repeated across target-specific trees, and small differences become hard to audit once generated output is treated as source truth.
16
+
17
+ The repo already carries this doctrine in [Tenets](../tenets.md), but agents need a numbered decision trail for changes that affect source vocabulary, target lowering, generated-output promises, and future schema migrations. A baseline ADR gives future records a stable decision to extend, specialize, or supersede.
18
+
19
+ ## Decision
20
+
21
+ Skillset is a source-first compiler for agent loadouts.
22
+
23
+ This means:
24
+
25
+ - `.skillset/` is the authored source of truth.
26
+ - Claude and Codex outputs are deterministic, target-native projections of that source.
27
+ - Build, check, lint, diff, doctor, explain, and import are authoring tools; they do not install, trust, publish, or activate generated artifacts.
28
+ - Portable source keys exist only when Skillset can lower the author intent faithfully.
29
+ - Target-specific truth stays visible through `claude` and `codex` blocks, lower-level opt-outs, diagnostics, lock provenance, or explicit target-native escape hatches.
30
+
31
+ The test for new source vocabulary is simple: it should reduce repeated authoring, make drift easier to see, and preserve target-native behavior. If a key only makes two different target features look the same, it does not belong in the portable contract.
32
+
33
+ ## Consequences
34
+
35
+ ### Positive
36
+
37
+ Future ADRs can build on one baseline decision instead of re-arguing why `.skillset/` is source truth or why generated output remains disposable.
38
+
39
+ Compiler changes have a clearer review frame: they either strengthen source-first authoring and faithful lowering, or they must explain why the doctrine should change.
40
+
41
+ ### Tradeoffs
42
+
43
+ Skillset accepts extra compiler responsibility. Derivation, validation, locking, and diagnostics need to be good enough that authors can trust generated output without editing it by hand.
44
+
45
+ The compiler also has to say no. A provider feature that cannot lower faithfully may require a target-specific escape hatch, an explicit opt-out, or a failing diagnostic instead of a convenient but false abstraction.
46
+
47
+ ### What This Does NOT Decide
48
+
49
+ This ADR does not decide every portable key in the source schema.
50
+
51
+ It does not decide how future agent, hook, resource, MCP, app, or install workflows should lower. Those decisions need their own ADRs when the target evidence and implementation plan are concrete.
52
+
53
+ ## References
54
+
55
+ - [Tenets](../tenets.md) - governing design principles for source-first loadouts and target-native lowering.
56
+ - [ADR-0001: Root Compile Policy](0001-root-compile-policy.md) - accepted `compile.targets` and `compile.unsupported` direction.
@@ -0,0 +1,70 @@
1
+ ---
2
+ id: 1
3
+ slug: root-compile-policy
4
+ title: Root Compile Policy
5
+ status: accepted
6
+ created: 2026-06-04
7
+ updated: 2026-06-04
8
+ owners: ['[galligan](https://github.com/galligan)']
9
+ depends_on: [0]
10
+ ---
11
+
12
+ # ADR-0001: Root Compile Policy
13
+
14
+ ## Context
15
+
16
+ Skillset originally let target provider blocks such as `claude` and `codex` sit at the top level of configuration. That worked for target-native options, but it made provider selection awkward. A source repo that wanted to compile both providers had to repeat boolean-ish target settings, and new source surfaces could look like silent failures if they were added without revisiting every target block.
17
+
18
+ Provider selection is not a Claude or Codex semantic feature. It is a compile concern: which projections should Skillset build from the source graph. Unsupported lowering is also a compile concern: what happens when authored source cannot lower faithfully to an enabled provider.
19
+
20
+ ## Decision
21
+
22
+ Root provider selection belongs under `compile`.
23
+
24
+ The root source contract uses:
25
+
26
+ ```yaml
27
+ compile:
28
+ targets:
29
+ - claude
30
+ - codex
31
+ unsupported: error
32
+ ```
33
+
34
+ This means:
35
+
36
+ - `compile.targets` chooses which provider projections to build.
37
+ - Omitting `compile.targets` defaults to every supported provider.
38
+ - Bare top-level `targets:` is rejected so provider selection has one canonical home.
39
+ - `claude` and `codex` blocks remain target-specific options, output settings, target-native escape hatches, and lower-level opt-outs.
40
+ - `compile.unsupported` defaults to `error`.
41
+ - `warn`, `skip`, and `force` are reserved until warnings, doctor output, and lock provenance can record exactly what happened.
42
+
43
+ The test: if a setting decides whether Skillset builds a provider projection, it belongs under `compile`. If it configures the shape of a provider-native output, it belongs under that provider's block or a lower-level target override.
44
+
45
+ ## Consequences
46
+
47
+ ### Positive
48
+
49
+ The common case gets smaller. Authors can say "compile these providers" once, then let source presence drive skills, plugins, instructions, hooks, and future surfaces.
50
+
51
+ New source surfaces are less likely to disappear silently. If a provider is enabled and Skillset cannot lower authored source faithfully, the default policy fails before generated output can look synchronized.
52
+
53
+ Target-specific configuration stays honest. `claude` and `codex` remain the visible places for target-native differences instead of becoming a mix of provider selection and target semantics.
54
+
55
+ ### Tradeoffs
56
+
57
+ The resolver now has to distinguish provider selection from target-native configuration. That adds a small amount of schema and validation responsibility, but it keeps the source contract sharper.
58
+
59
+ Soft unsupported policies are intentionally delayed. Migration users may eventually need `warn`, `skip`, or `force`, but enabling them before provenance exists would recreate the silent-drift problem this ADR is trying to prevent.
60
+
61
+ ### What This Does NOT Decide
62
+
63
+ This ADR does not enable `warn`, `skip`, or `force`. It reserves those modes and requires provenance before implementation.
64
+
65
+ This ADR does not define a portable source model for agents, hook activation, installs, or registry sync. Those surfaces need separate target evidence and separate decisions.
66
+
67
+ ## References
68
+
69
+ - [ADR-0000: Source-First Loadouts](0000-source-first-loadouts.md) - baseline source-first compiler doctrine.
70
+ - [Tenets](../tenets.md) - governing design principles for source-first loadouts and target-native lowering.
@@ -0,0 +1,18 @@
1
+ # Architecture Decision Records
2
+
3
+ ADRs document the significant design decisions behind Skillset: choices that, if reversed, would change the source contract, target lowering model, compiler promises, or authoring workflow. They capture the context, the decision, the consequences, and the alternatives considered.
4
+
5
+ ## Conventions
6
+
7
+ - Numbered ADRs live at `docs/adrs/NNNN-slug.md`.
8
+ - Draft ADRs live at `docs/adrs/drafts/YYYYMMDD-slug.md`.
9
+ - New ADRs should start from [template.md](template.md).
10
+ - Owners use `['[galligan](https://github.com/galligan)']` until a decision changes repository ownership metadata.
11
+ - Use `bun scripts/adr.ts check` before handoff and `bun scripts/adr.ts map` after ADR lifecycle changes.
12
+
13
+ ## Index
14
+
15
+ | ADR | Title | Status |
16
+ | --- | --- | --- |
17
+ | [0000](0000-source-first-loadouts.md) | Source-First Loadouts | Accepted |
18
+ | [0001](0001-root-compile-policy.md) | Root Compile Policy | Accepted |
@@ -0,0 +1,93 @@
1
+ {
2
+ "entries": [
3
+ {
4
+ "created": "2026-06-04",
5
+ "depends_on": [],
6
+ "inbound": [
7
+ {
8
+ "context": "- [ADR-0000: Source-First Loadouts](0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
9
+ "from": "0001",
10
+ "fromPath": "docs/adrs/0001-root-compile-policy.md"
11
+ },
12
+ {
13
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
14
+ "from": "20260604",
15
+ "fromPath": "docs/adrs/drafts/20260604-agent-source-model.md"
16
+ },
17
+ {
18
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
19
+ "from": "20260604",
20
+ "fromPath": "docs/adrs/drafts/20260604-changelog-and-versioning.md"
21
+ },
22
+ {
23
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
24
+ "from": "20260604",
25
+ "fromPath": "docs/adrs/drafts/20260604-feature-reference-and-schema-registry.md"
26
+ },
27
+ {
28
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - source-first and generated-output doctrine.",
29
+ "from": "20260604",
30
+ "fromPath": "docs/adrs/drafts/20260604-first-class-sets.md"
31
+ },
32
+ {
33
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
34
+ "from": "20260604",
35
+ "fromPath": "docs/adrs/drafts/20260604-global-xdg-managed-installs-and-sync.md"
36
+ },
37
+ {
38
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - source-first and target-native doctrine.",
39
+ "from": "20260604",
40
+ "fromPath": "docs/adrs/drafts/20260604-model-and-reasoning-alias-profiles.md"
41
+ },
42
+ {
43
+ "context": "- [ADR-0000: Source-First Loadouts](../0000-source-first-loadouts.md) - baseline source-first compiler doctrine.",
44
+ "from": "20260604",
45
+ "fromPath": "docs/adrs/drafts/20260604-reviewed-settings-suggestions.md"
46
+ }
47
+ ],
48
+ "number": "0000",
49
+ "owners": ["[galligan](https://github.com/galligan)"],
50
+ "path": "docs/adrs/0000-source-first-loadouts.md",
51
+ "slug": "source-first-loadouts",
52
+ "status": "accepted",
53
+ "superseded_by": null,
54
+ "title": "Source-First Loadouts",
55
+ "updated": "2026-06-04"
56
+ },
57
+ {
58
+ "created": "2026-06-04",
59
+ "depends_on": ["0"],
60
+ "inbound": [
61
+ {
62
+ "context": "- [ADR-0001: Root Compile Policy](0001-root-compile-policy.md) - accepted `compile.targets` and `compile.unsupported` direction.",
63
+ "from": "0000",
64
+ "fromPath": "docs/adrs/0000-source-first-loadouts.md"
65
+ },
66
+ {
67
+ "context": "- [ADR-0001: Root Compile Policy](../0001-root-compile-policy.md) - provider selection and target-specific config boundaries.",
68
+ "from": "20260604",
69
+ "fromPath": "docs/adrs/drafts/20260604-first-class-sets.md"
70
+ },
71
+ {
72
+ "context": "- [ADR-0001: Root Compile Policy](../0001-root-compile-policy.md) - provider selection and target-specific config boundaries.",
73
+ "from": "20260604",
74
+ "fromPath": "docs/adrs/drafts/20260604-model-and-reasoning-alias-profiles.md"
75
+ },
76
+ {
77
+ "context": "- [ADR-0001: Root Compile Policy](../0001-root-compile-policy.md) - provider selection and fail-loud unsupported behavior.",
78
+ "from": "20260604",
79
+ "fromPath": "docs/adrs/drafts/20260604-reviewed-settings-suggestions.md"
80
+ }
81
+ ],
82
+ "number": "0001",
83
+ "owners": ["[galligan](https://github.com/galligan)"],
84
+ "path": "docs/adrs/0001-root-compile-policy.md",
85
+ "slug": "root-compile-policy",
86
+ "status": "accepted",
87
+ "superseded_by": null,
88
+ "title": "Root Compile Policy",
89
+ "updated": "2026-06-04"
90
+ }
91
+ ],
92
+ "version": 1
93
+ }