@sous-io/sous 0.2.37 → 1.0.2
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.
- package/README.md +14 -256
- package/dist/bin.js +11 -0
- package/dist/sous.js +1094 -0
- package/docs/markdown/README.md +5 -4
- package/docs/markdown/_sidebar.md +21 -1
- package/docs/markdown/commands.md +294 -431
- package/docs/markdown/config-discovery.md +25 -14
- package/docs/markdown/config-inspection.md +53 -31
- package/docs/markdown/config-layers.md +168 -66
- package/docs/markdown/config-variables.md +44 -11
- package/docs/markdown/configuration.md +104 -17
- package/docs/markdown/design-principles.md +4 -1
- package/docs/markdown/repositories-authoring.md +30 -0
- package/docs/markdown/repositories-consuming.md +72 -14
- package/docs/markdown/repositories-file-formats.md +31 -13
- package/docs/markdown/repositories-providers.md +48 -57
- package/docs/markdown/repositories-quickstart.md +3 -2
- package/docs/markdown/repositories-troubleshooting.md +27 -1
- package/docs/markdown/repositories-variables.md +6 -1
- package/docs/markdown/repositories.md +18 -8
- package/package.json +48 -107
- package/recipes/core/sous-skills/skills/about-liquid-templates/SKILL.tpl.md +4 -6
- package/recipes/core/sous-skills/skills/about-liquid-templates/references/liquid-filters.tpl.md +2 -0
- package/recipes/core/sous-skills/skills/about-sous/SKILL.tpl.md +10 -9
- package/recipes/core/sous-skills/skills/about-sous-configuration/SKILL.tpl.md +35 -14
- package/recipes/core/sous-skills/skills/about-sous-recipes/SKILL.tpl.md +51 -20
- package/recipes/core/sous-skills/sous.recipe.yaml +1 -1
- package/sous.config.schema.json +351 -132
- package/bin/run.js +0 -51
- package/src/base-command.ts +0 -457
- package/src/commands/build.ts +0 -181
- package/src/commands/clear.ts +0 -79
- package/src/commands/compile.ts +0 -155
- package/src/commands/config/get.ts +0 -110
- package/src/commands/config/show.ts +0 -32
- package/src/commands/config/validate.ts +0 -53
- package/src/commands/help.ts +0 -46
- package/src/commands/init.ts +0 -289
- package/src/commands/launch.ts +0 -139
- package/src/commands/lock/rebuild.ts +0 -239
- package/src/commands/lock/show.ts +0 -115
- package/src/commands/namespace/list.ts +0 -138
- package/src/commands/namespace/show.ts +0 -130
- package/src/commands/prune.ts +0 -43
- package/src/commands/recipe/list.ts +0 -112
- package/src/commands/recipe/show.ts +0 -439
- package/src/commands/repo/add.ts +0 -145
- package/src/commands/repo/contribute.ts +0 -604
- package/src/commands/repo/gc.ts +0 -173
- package/src/commands/repo/init.ts +0 -136
- package/src/commands/repo/link.ts +0 -899
- package/src/commands/repo/list.ts +0 -236
- package/src/commands/repo/release.ts +0 -685
- package/src/commands/repo/remove.ts +0 -194
- package/src/commands/repo/search.ts +0 -243
- package/src/commands/repo/submit.ts +0 -341
- package/src/commands/repo/unlink.ts +0 -461
- package/src/commands/subscription/add.ts +0 -286
- package/src/commands/subscription/list.ts +0 -208
- package/src/commands/subscription/remove.ts +0 -182
- package/src/commands/subscription/update.ts +0 -216
- package/src/commands/update.ts +0 -178
- package/src/commands/vars/ask.ts +0 -417
- package/src/commands/vars/index.ts +0 -79
- package/src/commands/vars/list.ts +0 -67
- package/src/commands/vars/show.ts +0 -77
- package/src/config-command.ts +0 -30
- package/src/lib/build-preparation.ts +0 -128
- package/src/lib/build-service.ts +0 -580
- package/src/lib/config-discovery.ts +0 -378
- package/src/lib/config-inspect.ts +0 -145
- package/src/lib/config-kernel.mjs +0 -379
- package/src/lib/config-schema.ts +0 -401
- package/src/lib/env-file.ts +0 -328
- package/src/lib/env-local.ts +0 -212
- package/src/lib/errors.ts +0 -32
- package/src/lib/glob-pattern.ts +0 -24
- package/src/lib/include-resolver.ts +0 -523
- package/src/lib/interactive.ts +0 -165
- package/src/lib/markdown-compiler.ts +0 -947
- package/src/lib/package-info.ts +0 -25
- package/src/lib/pid-service.ts +0 -99
- package/src/lib/project-install.d.mts +0 -44
- package/src/lib/project-install.mjs +0 -234
- package/src/lib/project-scaffold/index.ts +0 -332
- package/src/lib/project-scaffold/templates.ts +0 -240
- package/src/lib/repos/catalog-display.ts +0 -215
- package/src/lib/repos/catalog-inputs.ts +0 -288
- package/src/lib/repos/catalog.ts +0 -842
- package/src/lib/repos/contribute.ts +0 -452
- package/src/lib/repos/core-recipe.ts +0 -105
- package/src/lib/repos/declarations.ts +0 -187
- package/src/lib/repos/defaults.ts +0 -175
- package/src/lib/repos/formats/common.ts +0 -440
- package/src/lib/repos/formats/index-file.ts +0 -253
- package/src/lib/repos/formats/links-map.ts +0 -98
- package/src/lib/repos/formats/lockfile.ts +0 -169
- package/src/lib/repos/formats/patterns.ts +0 -57
- package/src/lib/repos/formats/recipe-manifest.ts +0 -205
- package/src/lib/repos/formats/repo-manifest.ts +0 -97
- package/src/lib/repos/formats/store-entry.ts +0 -84
- package/src/lib/repos/formats/variable-definition.ts +0 -268
- package/src/lib/repos/freshness.ts +0 -264
- package/src/lib/repos/git-clone.ts +0 -850
- package/src/lib/repos/identity.ts +0 -89
- package/src/lib/repos/index.ts +0 -57
- package/src/lib/repos/links.ts +0 -356
- package/src/lib/repos/load-manifest.ts +0 -237
- package/src/lib/repos/lock-service.ts +0 -454
- package/src/lib/repos/locked-namespace-resolver.ts +0 -232
- package/src/lib/repos/locked-recipe-lookup.ts +0 -123
- package/src/lib/repos/locked-recipes.ts +0 -254
- package/src/lib/repos/managed-layer.ts +0 -422
- package/src/lib/repos/memories-hash-name.ts +0 -33
- package/src/lib/repos/namespace-resolver.ts +0 -527
- package/src/lib/repos/providers/base.ts +0 -268
- package/src/lib/repos/providers/git.ts +0 -245
- package/src/lib/repos/providers/github.ts +0 -589
- package/src/lib/repos/providers/gitlab.ts +0 -332
- package/src/lib/repos/providers/http.ts +0 -128
- package/src/lib/repos/providers/index-cache.ts +0 -421
- package/src/lib/repos/providers/index.ts +0 -106
- package/src/lib/repos/providers/local.ts +0 -410
- package/src/lib/repos/providers/provider.ts +0 -615
- package/src/lib/repos/recipe-config-layers.ts +0 -316
- package/src/lib/repos/recipe-key-matcher.ts +0 -62
- package/src/lib/repos/recipe-memories.ts +0 -178
- package/src/lib/repos/recipe-targets.ts +0 -236
- package/src/lib/repos/ref-search.ts +0 -46
- package/src/lib/repos/release/bump.ts +0 -161
- package/src/lib/repos/release/changelog.ts +0 -461
- package/src/lib/repos/release/git-state.ts +0 -460
- package/src/lib/repos/release/index-builder.ts +0 -1108
- package/src/lib/repos/release/index.ts +0 -19
- package/src/lib/repos/release/plan.ts +0 -521
- package/src/lib/repos/release/settle.ts +0 -154
- package/src/lib/repos/release/submissions.ts +0 -214
- package/src/lib/repos/release/submit-checkout.ts +0 -290
- package/src/lib/repos/release/submit-questions.ts +0 -153
- package/src/lib/repos/release/submit-service.ts +0 -898
- package/src/lib/repos/release/tags.ts +0 -239
- package/src/lib/repos/release/validate.ts +0 -463
- package/src/lib/repos/resolver.ts +0 -1028
- package/src/lib/repos/scaffold/index.ts +0 -245
- package/src/lib/repos/scaffold/templates.ts +0 -517
- package/src/lib/repos/seed.ts +0 -473
- package/src/lib/repos/store/contract.ts +0 -64
- package/src/lib/repos/store/hash.ts +0 -191
- package/src/lib/repos/store/recipe-store.ts +0 -599
- package/src/lib/repos/store/settings.ts +0 -58
- package/src/lib/repos/subscription-service.ts +0 -3859
- package/src/lib/repos/trust.ts +0 -447
- package/src/lib/repos/update-plan.ts +0 -235
- package/src/lib/self-update/index.ts +0 -14
- package/src/lib/self-update/installs.ts +0 -413
- package/src/lib/self-update/managers.ts +0 -126
- package/src/lib/self-update/plan.ts +0 -315
- package/src/lib/self-update/registry.ts +0 -99
- package/src/lib/self-update/run.ts +0 -506
- package/src/lib/self-update/versions.ts +0 -243
- package/src/lib/settings.ts +0 -1107
- package/src/lib/sous-home.ts +0 -104
- package/src/lib/state.ts +0 -167
- package/src/lib/vars/answers.ts +0 -192
- package/src/lib/vars/ask.ts +0 -1152
- package/src/lib/vars/definition-source.ts +0 -261
- package/src/lib/vars/display.ts +0 -231
- package/src/lib/vars/index.ts +0 -20
- package/src/lib/vars/ladder.ts +0 -282
- package/src/lib/vars/mappings.ts +0 -260
- package/src/lib/vars/names.ts +0 -94
- package/src/lib/vars/preanswers.ts +0 -395
- package/src/lib/vars/question-plan.ts +0 -241
- package/src/lib/vars/report.ts +0 -228
- package/src/lib/vars/safe-regex.ts +0 -235
- package/src/lib/vars/secrets.ts +0 -131
- package/src/lib/vars/validate.ts +0 -312
- package/src/lib/version-report.ts +0 -90
- package/src/lib/watch-loop.ts +0 -148
- package/src/lib/watch-service.ts +0 -116
- package/src/services/ref-resolver/container.ts +0 -107
- package/src/services/ref-resolver/dependency.ts +0 -60
- package/src/services/ref-resolver/format.ts +0 -197
- package/src/services/ref-resolver/glob.ts +0 -115
- package/src/services/ref-resolver/hash-names.ts +0 -155
- package/src/services/ref-resolver/index.ts +0 -55
- package/src/services/ref-resolver/injectable.ts +0 -36
- package/src/services/ref-resolver/location.ts +0 -62
- package/src/services/ref-resolver/lookups/cached-index-lookup.ts +0 -53
- package/src/services/ref-resolver/lookups/catalog-lookup.ts +0 -23
- package/src/services/ref-resolver/lookups/catalog-matcher.ts +0 -261
- package/src/services/ref-resolver/lookups/chained-lookup.ts +0 -27
- package/src/services/ref-resolver/lookups/env-var-lookup.ts +0 -65
- package/src/services/ref-resolver/lookups/fetched-index-lookup.ts +0 -150
- package/src/services/ref-resolver/lookups/recorded-dependency-lookup.ts +0 -62
- package/src/services/ref-resolver/lookups/ref-lookup.ts +0 -54
- package/src/services/ref-resolver/lookups/variable-lookup.ts +0 -123
- package/src/services/ref-resolver/named-refs.ts +0 -144
- package/src/services/ref-resolver/parser/env-var-splitter.ts +0 -27
- package/src/services/ref-resolver/parser/location-splitter.ts +0 -239
- package/src/services/ref-resolver/parser/name-path-splitter.ts +0 -200
- package/src/services/ref-resolver/parser/partial-ref.ts +0 -84
- package/src/services/ref-resolver/parser/query-splitter.ts +0 -61
- package/src/services/ref-resolver/parser/range-splitter.ts +0 -52
- package/src/services/ref-resolver/parser/ref-parser.ts +0 -115
- package/src/services/ref-resolver/parser/repo-qualifier-splitter.ts +0 -51
- package/src/services/ref-resolver/parts.ts +0 -115
- package/src/services/ref-resolver/pruners/command-line-pruner.ts +0 -47
- package/src/services/ref-resolver/pruners/include-pruner.ts +0 -66
- package/src/services/ref-resolver/pruners/manifest-pruner.ts +0 -130
- package/src/services/ref-resolver/pruners/ref-pruner.ts +0 -135
- package/src/services/ref-resolver/pruners/rule-helpers.ts +0 -44
- package/src/services/ref-resolver/pruners/stored-key-pruner.ts +0 -136
- package/src/services/ref-resolver/ref-helpers.ts +0 -62
- package/src/services/ref-resolver/ref-picker-service.ts +0 -204
- package/src/services/ref-resolver/ref-report.ts +0 -84
- package/src/services/ref-resolver/ref-resolve-arguments.ts +0 -47
- package/src/services/ref-resolver/ref-resolve-result.ts +0 -36
- package/src/services/ref-resolver/ref-resolver-service.ts +0 -323
- package/src/services/ref-resolver/source.ts +0 -48
- package/src/services/ref-resolver/tokens.ts +0 -25
- package/src/services/ref-resolver/types.ts +0 -155
- package/src/templating/filters/bullet-list.ts +0 -9
- package/src/templating/filters/index.ts +0 -8
- package/src/templating/init-liquid-engine.ts +0 -139
- package/src/templating/lib/glob-files.ts +0 -74
- package/src/templating/lib/import-export.ts +0 -32
- package/src/templating/lib/secret-scope.ts +0 -41
- package/src/templating/lib/tag-args.ts +0 -19
- package/src/templating/tags/exportScalarVarsJs.ts +0 -46
- package/src/templating/tags/getFiles.ts +0 -89
- package/src/templating/tags/index.ts +0 -14
- package/src/templating/tags/listFiles.ts +0 -54
- package/src/templating/tags/showVars.ts +0 -28
- package/src/utils/choice-prompt.ts +0 -143
- package/src/utils/command-errors.ts +0 -186
- package/src/utils/command-help.ts +0 -45
- package/src/utils/confirm-prompt.ts +0 -110
- package/src/utils/flags.ts +0 -177
- package/src/utils/formatting.ts +0 -849
- package/src/utils/prompts.ts +0 -53
- package/src/utils/sous-directory.ts +0 -245
- package/src/utils/table.ts +0 -603
- package/src/utils/value-prompt.ts +0 -119
|
@@ -7,7 +7,7 @@ user-level config (nothing is read from `~/.sous`) and no multi-project map.
|
|
|
7
7
|
## The config file
|
|
8
8
|
|
|
9
9
|
Exactly one primary config lives inside `.sous/`: `sous.config.js`, `sous.config.mjs`,
|
|
10
|
-
`sous.config.json`, `sous.config.jsonc`, or `sous.config.yaml`. Two or more candidates is an
|
|
10
|
+
`sous.config.ts`, `sous.config.json`, `sous.config.jsonc`, or `sous.config.yaml`. Two or more candidates is an
|
|
11
11
|
error, never a silent first-match. A typical config:
|
|
12
12
|
|
|
13
13
|
```js
|
|
@@ -16,8 +16,7 @@ export const config = {
|
|
|
16
16
|
name: "My Project", // optional display name
|
|
17
17
|
_env: { userHome: "HOME" }, // map config vars from env vars (top-level only)
|
|
18
18
|
_vars: {
|
|
19
|
-
|
|
20
|
-
docsDir: "${projectRoot}/docs", // declaration order never matters
|
|
19
|
+
docsDir: "${projectRoot}/docs", // projectRoot is set by sous; order never matters
|
|
21
20
|
},
|
|
22
21
|
_aliases: { myDocs: "${docsDir}" }, // extra @include bases (optional)
|
|
23
22
|
compilation: {
|
|
@@ -38,9 +37,16 @@ export const config = {
|
|
|
38
37
|
};
|
|
39
38
|
```
|
|
40
39
|
|
|
40
|
+
`${projectRoot}` is the directory that holds `.sous/`. Sous sets it, and setting `projectRoot` in any
|
|
41
|
+
`_vars` block is an error; see [Variables](config-variables.md#auto-vars).
|
|
42
|
+
|
|
43
|
+
The `.claude/skills` target above compiles the project's own skills. Skills from subscribed recipes
|
|
44
|
+
need no target of their own: the built-in Claude Code plugin sends them to `.claude/skills`, and
|
|
45
|
+
`recipes.skills.outputs` adds destinations of your own (see
|
|
46
|
+
[Consuming recipes](repositories-consuming.md)).
|
|
47
|
+
|
|
41
48
|
A JSON config may set `"$schema"` to bind the `sous.config.schema.json` artifact shipped with
|
|
42
|
-
sous for editor autocompletion; sous accepts and ignores the key.
|
|
43
|
-
writes one already bound to the copy of that artifact published for the running version.
|
|
49
|
+
sous for editor autocompletion; sous accepts and ignores the key.
|
|
44
50
|
|
|
45
51
|
?> Configs use `${var}` syntax. Template files use LiquidJS double-brace syntax instead; the two
|
|
46
52
|
are resolved at different stages and never mix.
|
|
@@ -72,32 +78,113 @@ A path may use glob syntax (`*`, `**`, `?`, `[..]`, `{a,b}`) and then includes e
|
|
|
72
78
|
path order. The same file may be included in more than one place; a circular include is an error, as is a line
|
|
73
79
|
that looks like an include (`@docs/notes.txt`, `@~workflow/missing`) but cannot be resolved, which fails the
|
|
74
80
|
build naming the file and the line. A line inside a fenced code block is left as written. An alias name may not
|
|
75
|
-
start with `~` or `#`.
|
|
76
|
-
[ref resolver](adrs/0013-one-ref-resolver.md); [Including recipe files in your own templates](repositories.md#including-recipe-files-in-your-own-templates)
|
|
81
|
+
start with `~` or `#`. [Including recipe files in your own templates](repositories.md#including-recipe-files-in-your-own-templates)
|
|
77
82
|
has the namespace rules.
|
|
78
83
|
|
|
79
84
|
## Composition
|
|
80
85
|
|
|
81
|
-
The primary config is optionally extended by drop-in
|
|
82
|
-
directly inside `.sous/conf.d/` is
|
|
83
|
-
|
|
84
|
-
|
|
86
|
+
The primary config is optionally extended by drop-in files: every `*.js|mjs|ts|json|jsonc|yaml`
|
|
87
|
+
file directly inside `.sous/conf.d/` is applied after the primary config, in the order of the
|
|
88
|
+
number its name starts with (`500-repos.jsonc` before `610-mac.jsonc`), and merged into it. Recipes and plugins can change the config too, and your own files are always
|
|
89
|
+
applied again after them, so a value you set wins. A
|
|
90
|
+
`.js`, `.mjs` or `.ts` file can also change the config through a `configure()` function, and a
|
|
91
|
+
`.patch.json` or `.patch.jsonl` file holds raw edits. [Layers and merging](config-layers.md) covers
|
|
92
|
+
the full semantics.
|
|
93
|
+
|
|
94
|
+
## Config expressions
|
|
95
|
+
|
|
96
|
+
A value in a JSON, JSONC or YAML config file may be an expression object, decided when sous builds
|
|
97
|
+
the config instead of when the file is written. The reserved keys are `$expr`, `$if`, `$elseif` and
|
|
98
|
+
`$else` (each `$if` and `$elseif` may carry a `:<name>` qualifier, and `$expr` a `:<language>` one).
|
|
99
|
+
Liquid is the expression language. An expression can read `host.platform`, `env.<NAME>`, variables
|
|
100
|
+
by their bare name, and recipe answers (except under `subscriptions` and `repos`).
|
|
101
|
+
|
|
102
|
+
A subscription switched off on a Mac only:
|
|
103
|
+
|
|
104
|
+
```jsonc
|
|
105
|
+
// conf.d/610-mac.jsonc
|
|
106
|
+
{
|
|
107
|
+
"subscriptions": {
|
|
108
|
+
"tool-usage/automated-browser-tasks": {
|
|
109
|
+
"enabled": {
|
|
110
|
+
"$if": {
|
|
111
|
+
"expr": "host.platform == 'darwin'",
|
|
112
|
+
"then": false
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
On a Mac, `enabled` is `false`. Elsewhere the condition is false and there is no `$else`, so the key
|
|
121
|
+
is dropped and the subscription stays on. An expression may appear at any depth, including inside
|
|
122
|
+
arrays. An object mixing a reserved key with any other key is an error, so a typo such as `"$iff"`
|
|
123
|
+
never passes through as config. The full rules are in
|
|
124
|
+
[the design of config expressions](architecture/specifications/S5-config-expressions.md).
|
|
125
|
+
|
|
126
|
+
## Plugins
|
|
127
|
+
|
|
128
|
+
Sous is a small engine plus plugins; the CLI, recipes, the compiler, skills, memories, Claude Code
|
|
129
|
+
support and the package-manager and repository-host integrations are all built-in plugins. Which
|
|
130
|
+
plugins load is an ordinary config key, so it may be set in any config file, a recipe's included.
|
|
131
|
+
There is no separate bootstrap config and no `"sous"` key in `package.json`.
|
|
132
|
+
|
|
133
|
+
- `plugins.discover` (`"dependencies" | "scan" = "dependencies"`): `"dependencies"` loads the
|
|
134
|
+
built-ins, the plugins in the project's `package.json` dependencies (and the workspace root's) and
|
|
135
|
+
those under `load`; `"scan"` also looks for installed plugins through the package managers.
|
|
136
|
+
- `plugins.load` (`string[]`): plugins to load though `package.json` does not list them.
|
|
137
|
+
- `plugins.disabled` (`string[]`): plugins never to load, built-ins included.
|
|
138
|
+
- `plugins.options` (`Record<string, object>`): each plugin's own options, keyed by plugin name.
|
|
139
|
+
|
|
140
|
+
```jsonc
|
|
141
|
+
// .sous/sous.config.jsonc
|
|
142
|
+
{
|
|
143
|
+
"plugins": {
|
|
144
|
+
"load": [
|
|
145
|
+
"sous-plugin-bun"
|
|
146
|
+
],
|
|
147
|
+
"disabled": [
|
|
148
|
+
"sous-plugin-old-thing"
|
|
149
|
+
],
|
|
150
|
+
"options": {
|
|
151
|
+
"sous-plugin-claude-code": {
|
|
152
|
+
"model": "opus"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Two more keys settle what plugins do:
|
|
160
|
+
|
|
161
|
+
- `services.replace` picks the winner when two plugins both take over the same piece of sous's
|
|
162
|
+
work. Each piece has a name, such as `git.runner` (how sous runs git), and two plugins replacing
|
|
163
|
+
the same one stops sous with an error until you choose one:
|
|
164
|
+
`"services": { "replace": { "git.runner": "sous-plugin-fast-git" } }`. Sous then warns on every
|
|
165
|
+
run that the other plugin may not work as expected.
|
|
166
|
+
- `budgets` changes how long a step may take before sous warns that it is slow; a budget set to
|
|
167
|
+
`false` turns that warning off. `--timings` on any command prints how long every step took.
|
|
168
|
+
|
|
169
|
+
`sous plugins show` lists every plugin and what it adds. Recipes may ship plugins too; see
|
|
170
|
+
[where plugins come from](architecture/specifications/S1-engine.md#where-plugins-come-from).
|
|
85
171
|
|
|
86
172
|
## Where to go next
|
|
87
173
|
|
|
88
174
|
- [Discovery and overrides](config-discovery.md): how sous finds the config, and the flags and
|
|
89
175
|
environment variables that override it
|
|
90
|
-
- [Layers and merging](config-layers.md):
|
|
91
|
-
`configure()`
|
|
92
|
-
- [Variables](config-variables.md):
|
|
176
|
+
- [Layers and merging](config-layers.md): the order files apply in, how values merge, the
|
|
177
|
+
`configure()` function, patch files
|
|
178
|
+
- [Variables](config-variables.md): where `${var}` values come from, the variables sous sets
|
|
179
|
+
(`projectRoot` among them), and variables that refer to other variables
|
|
93
180
|
- [Inspecting and validating](config-inspection.md): the `sous config` commands and the
|
|
94
181
|
validation pipeline
|
|
95
182
|
|
|
96
183
|
## Rules of the road
|
|
97
184
|
|
|
98
|
-
- Hand-written config belongs in the primary file or your own `conf.d/`
|
|
99
|
-
`conf.d/500-*` through `conf.d/599-*` band is reserved for
|
|
185
|
+
- Hand-written config belongs in the primary file or your own `conf.d/` files. The
|
|
186
|
+
`conf.d/500-*` through `conf.d/599-*` band is reserved for files the sous CLI itself writes.
|
|
100
187
|
Sous edits those by key, so you may edit them too and your comments, key order and formatting
|
|
101
|
-
survive; put a
|
|
188
|
+
survive; put a file of your own outside the band.
|
|
102
189
|
- Any config problem halts sous with a `ConfigError` naming the offending file; there is no
|
|
103
190
|
warn-and-continue.
|
|
@@ -52,7 +52,10 @@ sous at runtime.*
|
|
|
52
52
|
Everything gets an escape hatch, within practicality. The happy path stays maximally simple;
|
|
53
53
|
the escape hatches are advanced usage and may require the docs, but they must exist and they
|
|
54
54
|
still get thoughtful ergonomics. Projects control everything granularly, and an individual
|
|
55
|
-
user can override every project decision through their own
|
|
55
|
+
user can override every project decision through their own config files. Plugins get the same
|
|
56
|
+
reach: nearly everything sous does, the CLI included, is a plugin, and a plugin can change the
|
|
57
|
+
config, wrap or replace another plugin's work, and add commands. Where a choice is risky, sous
|
|
58
|
+
reports the problem and lets it happen rather than forbidding it.
|
|
56
59
|
|
|
57
60
|
*Example: subscribing to a recipe is one line and pulls in everything the recipe provides;
|
|
58
61
|
excluding one skill from that subscription may take a documented setting, but the setting is
|
|
@@ -99,6 +99,36 @@ template may include a file from a recipe this one depends on through the reserv
|
|
|
99
99
|
this recipe's own `depends` and `subscribes` at their pinned versions; see
|
|
100
100
|
[Including recipe files in your own templates](repositories.md#including-recipe-files-in-your-own-templates).
|
|
101
101
|
|
|
102
|
+
### Recipes that ship sous plugins
|
|
103
|
+
|
|
104
|
+
A recipe may ship a sous plugin: code that extends sous itself, with the same plugin interface an npm
|
|
105
|
+
plugin uses. It is one self-contained bundled file, because sous never runs `npm install` for a recipe.
|
|
106
|
+
The same rule holds for anything else in a recipe that runs, such as a helper script or a hook. The
|
|
107
|
+
manifest names the bundle, and optionally its type declarations:
|
|
108
|
+
|
|
109
|
+
```yaml
|
|
110
|
+
# sous.recipe.yaml
|
|
111
|
+
plugin:
|
|
112
|
+
bundle: plugin/index.js
|
|
113
|
+
types: plugin/index.d.ts # optional
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Nothing in a repository runs until the subscriber trusts the repository, so the trust question is the
|
|
117
|
+
gate for a recipe's plugin as for its other content. Sous copies a recipe plugin's `.d.ts` file into the
|
|
118
|
+
subscriber's `.sous/types/`, so other plugins in that project see its types; a plugin with no `.d.ts`
|
|
119
|
+
still works. A recipe may also require plugins from npm, each with a version range:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
# sous.recipe.yaml
|
|
123
|
+
requires:
|
|
124
|
+
plugins:
|
|
125
|
+
sous-plugin-claude-code: "^1.0.0"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
A subscriber is offered the missing plugin when they subscribe; see
|
|
129
|
+
[Subscribe to a recipe](repositories-consuming.md#subscribe-to-a-recipe). How a plugin is written is in
|
|
130
|
+
[the engine specification](architecture/specifications/S1-engine.md), under "Plugins".
|
|
131
|
+
|
|
102
132
|
## Declare the variables a recipe needs
|
|
103
133
|
|
|
104
134
|
A recipe that needs a value from the project asks through a **definition**: a published specification, never a
|
|
@@ -112,16 +112,16 @@ recorded in its canonical form, `namespace/recipe`.
|
|
|
112
112
|
The whole dependency closure resolves before anything is downloaded, and only then is anything
|
|
113
113
|
written; an install is whole or not at all.
|
|
114
114
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
115
|
+
A few flags change how it runs: `--yes` answers yes to the subscribe confirmation and the trust
|
|
116
|
+
question, `--answer <name>=<value>` answers a recipe's question ahead of time, `--dry-run` prints what
|
|
117
|
+
would be installed without writing or downloading anything, and `--non-interactive` fails instead of
|
|
118
|
+
asking, naming the flag that would have answered. `sous subscription add --help` lists every flag.
|
|
119
|
+
|
|
120
|
+
A recipe may require sous plugins from npm, each with a version range. When a required plugin is
|
|
121
|
+
missing or outside its range, `sous subscription add` refuses the recipe; run interactively, it offers
|
|
122
|
+
to install the plugin, and `--install-plugins` does that without asking. A build fails when a
|
|
123
|
+
subscribed recipe's requirement breaks later, for example after the plugin was removed, and the
|
|
124
|
+
message names the plugin and the command that installs it.
|
|
125
125
|
|
|
126
126
|
?> `sous subscribe` and `sous unsubscribe` are accepted spellings of these two commands, and every
|
|
127
127
|
topic answers to both spellings of its name (`sous subscriptions add`, `sous repos list`).
|
|
@@ -175,10 +175,21 @@ like `workflow/qa-helper` above, is fetched and pinned but stays out of your out
|
|
|
175
175
|
|
|
176
176
|
Recipe files compile under the [`.tpl.` convention](configuration.md#templates-and-the-tpl-convention): a file
|
|
177
177
|
with `.tpl.` in its name is rendered through LiquidJS and loses `.tpl.` on the way out, and anything else is copied
|
|
178
|
-
verbatim. Skills are written to the directories
|
|
179
|
-
[`recipes`](repositories-file-formats.md#recipes-what-each-content-kind-does) config key
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
verbatim. Skills are written to every skills directory a plugin for an agent tool names, and to the directories you name
|
|
179
|
+
under the [`recipes`](repositories-file-formats.md#recipes-what-each-content-kind-does) config key. The
|
|
180
|
+
Claude Code plugin built into sous adds `<project root>/.claude/skills`, so that is where skills land unless
|
|
181
|
+
you disable that plugin (see [Plugins](configuration.md#plugins)). To add a destination of your own:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
recipes: {
|
|
185
|
+
skills: {
|
|
186
|
+
outputs: ["${projectRoot}/.codex/skills"],
|
|
187
|
+
},
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`projectRoot` is set by sous (the directory holding `.sous/`), so you never define it. When no plugin names a skills directory
|
|
192
|
+
and you name none, skills go nowhere, and the build says so and how to fix it. Written skills are tracked
|
|
182
193
|
like every other file sous writes, so `sous prune` removes what an unsubscribed recipe used to write and
|
|
183
194
|
`sous clear` removes all of it; neither reaches into a linked checkout.
|
|
184
195
|
|
|
@@ -214,6 +225,11 @@ When a build finds a memory an active recipe publishes that no include of any ou
|
|
|
214
225
|
or the view) and `exclude` does not name, it warns, naming the memory and the line to add. Subscribing alone
|
|
215
226
|
includes nothing, and the warning is how that is never silent.
|
|
216
227
|
|
|
228
|
+
?> In sous 1.0 an agent's plugin can also name the instruction file that agent reads in every session
|
|
229
|
+
(`CLAUDE.md` for the Claude Code plugin built into sous). Sous then writes that file with one `@` include
|
|
230
|
+
line for each memory `recipes.memories` selects, so the memories reach the agent without a line of your own.
|
|
231
|
+
How that file and an instruction file your own templates write fit together is still being decided.
|
|
232
|
+
|
|
217
233
|
## Answer the questions
|
|
218
234
|
|
|
219
235
|
A recipe publishes variable definitions; you supply answers. Subscribing asks whatever is
|
|
@@ -354,6 +370,48 @@ there is no entry to delete: the one sous provides comes back on the next run, s
|
|
|
354
370
|
opt-out outlives it. `sous subscription add core` clears it again. If you remove `core`, make sure
|
|
355
371
|
something else tells your agents not to edit generated files.
|
|
356
372
|
|
|
373
|
+
## Switch a subscription off on one machine
|
|
374
|
+
|
|
375
|
+
A subscription stays in the config with `enabled: false`, so the opt-out is visible. A switched-off
|
|
376
|
+
subscription is not built: the recipes reached only through it are skipped, the outputs they wrote are
|
|
377
|
+
pruned, and their variables are neither asked nor required. Their pins stay in the committed lockfile,
|
|
378
|
+
so switching a recipe off on your machine never removes it for anyone else.
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
sous subscription disable tool-usage/automated-browser-tasks
|
|
382
|
+
sous subscription enable tool-usage/automated-browser-tasks
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Both edit `.sous/conf.d/510-subscriptions.jsonc` by key. To switch one off only on some machines, write
|
|
386
|
+
`enabled` in a `conf.d` file of your own that sorts after 510; a later file wins over the managed one:
|
|
387
|
+
|
|
388
|
+
```jsonc
|
|
389
|
+
// .sous/conf.d/610-mac.jsonc
|
|
390
|
+
{
|
|
391
|
+
"subscriptions": {
|
|
392
|
+
"tool-usage/automated-browser-tasks": {
|
|
393
|
+
"enabled": {
|
|
394
|
+
"$if": {
|
|
395
|
+
"expr": "host.platform == 'darwin'",
|
|
396
|
+
"then": false
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
The build prints one line per skipped recipe, saying why:
|
|
405
|
+
|
|
406
|
+
```text
|
|
407
|
+
$ sous build
|
|
408
|
+
Skipped tool-usage/automated-browser-tasks: its subscription is switched off (conf.d/610-mac.jsonc).
|
|
409
|
+
Pruned 4 outputs it had written.
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
The `$if` object is a config expression, decided each time sous builds the config; see
|
|
413
|
+
[Config expressions](configuration.md#config-expressions).
|
|
414
|
+
|
|
357
415
|
## Restore a fresh clone
|
|
358
416
|
|
|
359
417
|
A clone has the lockfile and the subscriptions, and no store. `sous build` restores what the
|
|
@@ -79,11 +79,23 @@ contents: # what a subscriber actually receives
|
|
|
79
79
|
| `depends`, `subscribes` | no | Build dependencies and co-subscriptions; within either list, no entry may repeat |
|
|
80
80
|
| `contents`, `variables` | no | Contents default to an empty list, which is what a curated bundle publishes; a duplicated variable name, or two definitions claiming one `env`, is an error |
|
|
81
81
|
| `submissions` | no | Whether this recipe takes proposed changes, winning over the repository's block; see [The submissions block](#the-submissions-block) |
|
|
82
|
+
| `plugin` | no | A sous plugin the recipe ships: `bundle`, the path of one self-contained bundled file, and optionally `types`, its `.d.ts` file; see [Recipes that ship sous plugins](repositories-authoring.md#recipes-that-ship-sous-plugins) |
|
|
83
|
+
| `requires` | no | `requires.plugins` maps npm sous plugin names to version ranges the recipe needs |
|
|
82
84
|
|
|
83
|
-
|
|
85
|
+
```yaml
|
|
86
|
+
plugin:
|
|
87
|
+
bundle: plugin/index.js
|
|
88
|
+
types: plugin/index.d.ts
|
|
89
|
+
requires:
|
|
90
|
+
plugins:
|
|
91
|
+
sous-plugin-claude-code: "^1.0.0"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`contents[].kind` is `skills`, `memories`, `prompts` or `config`; a sous plugin is not a content kind but the
|
|
95
|
+
`plugin` field above. `skills` are
|
|
84
96
|
written to the destinations named by [`recipes`](#recipes-what-each-content-kind-does); `memories` are included
|
|
85
97
|
into your instruction files by one line (see [Recipe memories](repositories-consuming.md#recipe-memories));
|
|
86
|
-
`config`
|
|
98
|
+
each `config` file joins the subscriber's config, under the project's own files so the project wins; nothing takes `prompts` yet, and the build warns about a recipe that
|
|
87
99
|
publishes them. `include` needs at least one glob, and both lists are recipe-relative.
|
|
88
100
|
|
|
89
101
|
### The submissions block
|
|
@@ -126,9 +138,8 @@ two readings that both publish what is named fail it too, naming the spellings t
|
|
|
126
138
|
|
|
127
139
|
### Ref forms
|
|
128
140
|
|
|
129
|
-
Every place a ref is written reads it
|
|
130
|
-
|
|
131
|
-
lookup that keeps the readings that exist. These forms are recognized everywhere; the table after them says
|
|
141
|
+
Every place a ref is written reads it the same way: sous lists every way the text can be read, drops the
|
|
142
|
+
readings that place does not accept, and keeps the ones that name something that exists. These forms are recognized everywhere; the table after them says
|
|
132
143
|
which each place allows. A refused form is an error saying what to write there instead.
|
|
133
144
|
|
|
134
145
|
| Form | Example | Names |
|
|
@@ -359,7 +370,7 @@ These live at the top level of the merged config; [The config file](configuratio
|
|
|
359
370
|
repos:
|
|
360
371
|
sous-recipes:
|
|
361
372
|
url: https://github.com/sous-io/sous-recipes
|
|
362
|
-
provider: github # inferred from the URL when omitted; github, gitlab or
|
|
373
|
+
provider: github # inferred from the URL when omitted; github, gitlab, local, or a host a plugin adds
|
|
363
374
|
enabled: true # false opts out of a repository sous provides itself
|
|
364
375
|
alwaysPull: false # install a newer in-range version rather than holding the lock
|
|
365
376
|
addedBy: sous # provenance; "user", "sous" for an entry sous provides itself, or the
|
|
@@ -373,7 +384,7 @@ store: # every value is a default you can change
|
|
|
373
384
|
freshnessSeconds: 300 # how long a fetched index stays fresh
|
|
374
385
|
watchPollSeconds: 300 # how often watch mode polls upstream
|
|
375
386
|
recipes: # what each content kind a subscribed recipe publishes does
|
|
376
|
-
skills: { outputs: ["${projectRoot}/.
|
|
387
|
+
skills: { outputs: ["${projectRoot}/.codex/skills"] } # added to the skills directories agent plugins name
|
|
377
388
|
memories: { first: ["communication/*"], exclude: ["tool-usage/automated-browser-tasks"] }
|
|
378
389
|
varMappings:
|
|
379
390
|
QA_SERVICE_TOKEN: workflow/qa-variables/qaServiceToken
|
|
@@ -395,15 +406,18 @@ the default stands.
|
|
|
395
406
|
|
|
396
407
|
### recipes: what each content kind does
|
|
397
408
|
|
|
398
|
-
One block per content kind a subscribed recipe publishes. A recipe's `config` contents
|
|
399
|
-
and a recipe's own config
|
|
409
|
+
One block per content kind a subscribed recipe publishes. A recipe's `config` contents join the config, not the
|
|
410
|
+
output files, and a recipe's own config file may set `recipes.skills` only; `recipes.memories` chooses what the project
|
|
400
411
|
includes, so it is dropped from a recipe's layer with a warning.
|
|
401
412
|
|
|
402
|
-
- `recipes.skills.outputs` (`string[]`, default
|
|
403
|
-
|
|
413
|
+
- `recipes.skills.outputs` (`string[]`, default none): your own directories recipe skill bundles are written
|
|
414
|
+
into, besides every skills directory a plugin for an agent tool names. `${var}` is substituted as in any config path. The
|
|
415
|
+
built-in Claude Code plugin adds `<project root>/.claude/skills`, so skills land there with no setting. When no
|
|
416
|
+
plugin names a skills directory and this list is empty, skills go nowhere, and the build says why. `${projectRoot}` is set by sous;
|
|
417
|
+
setting `projectRoot` in any `_vars` is an error.
|
|
404
418
|
- `recipes.memories.first` (`string[]`, default none): recipes whose memories lead the `#memories` view. An entry
|
|
405
419
|
is a glob over `namespace/recipe` keys (`communication/*`), or a regular expression written between two slashes
|
|
406
|
-
(`/^tool-usage\//`); a string, because
|
|
420
|
+
(`/^tool-usage\//`); a string, because the config is plain JSON data and cannot hold a `RegExp`.
|
|
407
421
|
- `recipes.memories.exclude` (`string[]`, default none): recipes whose memories the view leaves out, and the
|
|
408
422
|
build's unincluded-memory warning never lists. The same entry forms as `first`.
|
|
409
423
|
|
|
@@ -418,7 +432,7 @@ are `.jsonc` so they can carry real comments, and each opens with a header sayin
|
|
|
418
432
|
| Layer | Holds | Written by |
|
|
419
433
|
|-------|-------|-----------|
|
|
420
434
|
| `500-repos.jsonc` | `repos` | `sous repo add`, `sous repo remove` |
|
|
421
|
-
| `510-subscriptions.jsonc` | `subscriptions` | `sous subscription add`, `
|
|
435
|
+
| `510-subscriptions.jsonc` | `subscriptions` | `sous subscription add`, `remove`, `enable` and `disable` |
|
|
422
436
|
| `520-var-mappings.jsonc` | `varMappings` | `sous vars ask` |
|
|
423
437
|
|
|
424
438
|
```jsonc
|
|
@@ -438,6 +452,10 @@ so an interrupted write leaves the previous layer rather than a truncated one. A
|
|
|
438
452
|
old `.json` name is read as a fallback and migrates on the next write: the `.jsonc` file is written and the
|
|
439
453
|
`.json` one removed, so a project never ends up with both, which would be a hard config error.
|
|
440
454
|
|
|
455
|
+
No file is special to sous when it reads the config: a `conf.d` file of your own that sorts after 510 can
|
|
456
|
+
override a subscription the managed file lists, such as switching it off on one machine (see
|
|
457
|
+
[Switch a subscription off on one machine](repositories-consuming.md#switch-a-subscription-off-on-one-machine)).
|
|
458
|
+
|
|
441
459
|
## Where to go next
|
|
442
460
|
|
|
443
461
|
- [Repositories](repositories.md): the model, trust, and the lockfile
|
|
@@ -4,9 +4,9 @@ A **provider** is everything sous knows about one kind of repository host. It is
|
|
|
4
4
|
a host-specific fact is allowed to live, so every command above it (add, subscribe, build,
|
|
5
5
|
release, submit) talks about repositories in the same terms whatever host they live on.
|
|
6
6
|
|
|
7
|
-
Sous ships three
|
|
8
|
-
what a URL becomes once a provider has taken it apart, how private repositories authenticate,
|
|
9
|
-
what each provider can do when you propose a change, and what
|
|
7
|
+
Sous ships three providers, `github`, `gitlab` and `local`, and a sous plugin can add another. This
|
|
8
|
+
page covers how a provider is chosen for a URL, what a URL becomes once a provider has taken it apart, how private repositories authenticate,
|
|
9
|
+
what each provider can do when you propose a change, and what adding another one involves.
|
|
10
10
|
|
|
11
11
|
## What a provider answers
|
|
12
12
|
|
|
@@ -132,8 +132,8 @@ absolute directory, because that is what git is given when a recipe is fetched.
|
|
|
132
132
|
whose scheme is the provider's identifier: `github://sous-io/sous-recipes/workflow/sat@^1.1`. A
|
|
133
133
|
first segment containing a dot is read as the host, so `gitlab://gitlab.example.com/group/project/-/ns/recipe`
|
|
134
134
|
addresses a self-hosted instance; without one, the provider's public host is assumed. Where a
|
|
135
|
-
repository path ends, and what a browser URL's path looks like, is each provider's own rule
|
|
136
|
-
|
|
135
|
+
repository path ends, and what a browser URL's path looks like, is each provider's own rule, so a URL
|
|
136
|
+
copied from either host's file view works too. `local://` is refused,
|
|
137
137
|
because a path on your disk is not a published location. Every form is in
|
|
138
138
|
[Ref forms](repositories-file-formats.md#ref-forms).
|
|
139
139
|
|
|
@@ -141,37 +141,48 @@ because a path on your disk is not a published location. Every form is in
|
|
|
141
141
|
|
|
142
142
|
Sous reads a repository in two very different ways, and they authenticate differently.
|
|
143
143
|
|
|
144
|
-
**The index** is
|
|
144
|
+
**The index** is read by trying three ways in order, so reading works with whatever access you have.
|
|
145
|
+
Neither `gh` nor `glab` is ever required to read a repository; they are needed only for
|
|
146
|
+
`sous repo contribute` and `sous repo submit`.
|
|
147
|
+
|
|
148
|
+
```text
|
|
149
|
+
Reading sous.index.json from a repository
|
|
150
|
+
1. HTTP with a token if a token is found (see below)
|
|
151
|
+
2. HTTP with no token public repositories
|
|
152
|
+
3. git a shallow, sparse fetch of the one file, using your own git
|
|
153
|
+
credentials (SSH keys, credential helpers)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
For GitLab, the HTTP requests use the API address, with the whole project path encoded, so a nested
|
|
157
|
+
group's `/` becomes `%2F`:
|
|
145
158
|
|
|
146
159
|
```text
|
|
147
160
|
https://raw.githubusercontent.com/<owner>/<name>/HEAD/sous.index.json
|
|
148
|
-
https://<gitlab host
|
|
161
|
+
https://<gitlab host>/api/v4/projects/<owner>%2F<name>/repository/files/sous.index.json/raw?ref=HEAD
|
|
149
162
|
```
|
|
150
163
|
|
|
151
|
-
A token is looked for in
|
|
164
|
+
A token is looked for in these places, in this order, and a missing one is skipped:
|
|
152
165
|
|
|
153
166
|
1. the environment: `GITHUB_TOKEN` for GitHub, `GITLAB_TOKEN` for GitLab;
|
|
154
|
-
2.
|
|
155
|
-
|
|
167
|
+
2. `git credential fill`, the credential git already stores for `https://<host>`;
|
|
168
|
+
3. the host's own command line tool, only when it is installed: `gh` for GitHub, and
|
|
169
|
+
`glab config get token --host <host>` for GitLab.
|
|
156
170
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
error says which of the two situations you are in:
|
|
171
|
+
A command's output counts as a token only when the command exits `0` and prints exactly one non-empty
|
|
172
|
+
line holding no whitespace.
|
|
160
173
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
Either the repository publishes no sous index yet, or the URL names a repository that does
|
|
165
|
-
not exist.
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
A 401 or 403 says the repository is private or was not authorized, and points at the two sources:
|
|
174
|
+
Sous remembers, per repository, which way worked, in `$SOUS_HOME/cache/read-strategies.json`, and tries it
|
|
175
|
+
first next time; after a failure it forgets it and walks the whole list again. When every way fails, one
|
|
176
|
+
error lists each attempt and why it failed, then names the fixes:
|
|
169
177
|
|
|
170
178
|
```text
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
179
|
+
Error: could not read gitlab.com/acme/private-recipes.
|
|
180
|
+
HTTP with token no token found (GITLAB_TOKEN unset; git has no stored credential for gitlab.com)
|
|
181
|
+
HTTP without token 302 to sign-in page: the repository is private
|
|
182
|
+
git Permission denied (publickey)
|
|
183
|
+
Fix one of these:
|
|
184
|
+
export GITLAB_TOKEN=<a token with read_repository>
|
|
185
|
+
set up git access to gitlab.com (an SSH key, or a credential helper)
|
|
175
186
|
```
|
|
176
187
|
|
|
177
188
|
**A recipe's files** come from git itself: a shallow, blobless, sparse clone at the version's
|
|
@@ -180,9 +191,8 @@ apply, exactly as they would for a manual clone: credential helpers, the SSH age
|
|
|
180
191
|
`insteadOf` rewrites are all inherited from your git configuration, and sous adds nothing of its
|
|
181
192
|
own. Cloning a working copy with `sous repo link` works the same way.
|
|
182
193
|
|
|
183
|
-
?> For a private repository,
|
|
184
|
-
|
|
185
|
-
finds the index but cannot clone has only the second half missing.
|
|
194
|
+
?> For a private repository, git access (a credential helper or an SSH key) covers both the index
|
|
195
|
+
and the recipe files. A token in the environment makes reading the index faster.
|
|
186
196
|
|
|
187
197
|
## Proposing a change
|
|
188
198
|
|
|
@@ -238,12 +248,12 @@ provider once, on the repository entry:
|
|
|
238
248
|
}
|
|
239
249
|
```
|
|
240
250
|
|
|
241
|
-
That block goes at the top level of your primary config or of a `conf.d/`
|
|
242
|
-
writes its own entries to the `conf.d/500-repos.jsonc`
|
|
251
|
+
That block goes at the top level of your primary config or of a `conf.d/` file of your own; sous
|
|
252
|
+
writes its own entries to the `conf.d/500-repos.jsonc` file it manages. Every key is listed under
|
|
243
253
|
[configuration keys](repositories-file-formats.md#configuration-keys).
|
|
244
254
|
|
|
245
255
|
Everything downstream then works normally: the index is read from that host's own raw endpoint,
|
|
246
|
-
|
|
256
|
+
a token comes from the sources above, and the identity is
|
|
247
257
|
`git.example.com/platform/recipes`. Group paths of any depth are preserved, so
|
|
248
258
|
`group/subgroup/project` stays one repository rather than being mistaken for a namespace.
|
|
249
259
|
|
|
@@ -296,32 +306,13 @@ one repository's resolution at a working copy without changing what your project
|
|
|
296
306
|
|
|
297
307
|
## Adding a provider
|
|
298
308
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
The subclass supplies the rest:
|
|
308
|
-
|
|
309
|
-
- `id`, the identifier a repository entry and a locator scheme use;
|
|
310
|
-
- `features`, the ones it genuinely answers (`fetch`; `submit` only if all four write calls are
|
|
311
|
-
real; `proposals` only if `findProposal`, `proposalStatus` and `updateProposal` are);
|
|
312
|
-
- `matches(url)` and `canonicalize(url)`, the URL half;
|
|
313
|
-
- `fetchIndex(repo, options)` and `fetchRecipeTree(repo, recipePath, tag, destDir, options)`, the
|
|
314
|
-
read half;
|
|
315
|
-
- `cli` and `proposalNoun` when it submits, so messages can name the tool and call a proposal
|
|
316
|
-
what the host calls it;
|
|
317
|
-
- overrides of the four write-path calls when it submits, and of the three proposals calls when
|
|
318
|
-
it can follow a proposal up. Each answers with plain data (a proposal's id, address, state,
|
|
319
|
-
title, review and check counts), never with a host's own vocabulary.
|
|
320
|
-
|
|
321
|
-
Every call takes an options object carrying the testing seams (`cwd`, `env`, `fetchImpl`, `run`),
|
|
322
|
-
which is why no provider reaches for `spawn` or the global `fetch` directly and no test in this
|
|
323
|
-
layer touches the network. The last change is adding the class to the built-in provider list in
|
|
324
|
-
`providers/index.ts`; nothing above the provider layer learns its name.
|
|
309
|
+
A provider is a sous plugin. It holds everything specific to its host: recognizing and taking apart the
|
|
310
|
+
host's URLs, the ways it reads an index and where it finds a token, and, when it supports them, proposing
|
|
311
|
+
changes and the CI workflow `sous repo init` writes. Nothing else in sous knows a host's name. A plugin can
|
|
312
|
+
also add a way of reading to an existing provider, for example for a host with its own sign-in.
|
|
313
|
+
|
|
314
|
+
?> The exact interface a provider plugin implements is not published yet; it is settled as sous 1.0
|
|
315
|
+
lands. The plugin design is in [the engine specification](architecture/specifications/S1-engine.md).
|
|
325
316
|
|
|
326
317
|
## Where to go next
|
|
327
318
|
|
|
@@ -23,8 +23,9 @@ cd ~/projects/my-project
|
|
|
23
23
|
echo 'name: my-project' > .sous/sous.config.yaml
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Everything else has a default: skills compile into `<project root>/.claude/skills
|
|
27
|
-
|
|
26
|
+
Everything else has a default: skills compile into `<project root>/.claude/skills` (where the
|
|
27
|
+
Claude Code plugin built into sous puts them), and the lockfile, the state file and the `conf.d`
|
|
28
|
+
files sous writes land under `.sous/`. Outside a
|
|
28
29
|
walkthrough, `sous init` writes a fuller starting point (a commented config, a starter prompt,
|
|
29
30
|
the env files and the ignore block) and runs the first build for you; the one-line config is
|
|
30
31
|
used here so that each step shows one thing. `SOUS_HOME` puts
|