@sous-io/sous 0.1.0 → 0.2.0

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 (206) hide show
  1. package/README.md +121 -35
  2. package/bin/run.js +10 -1
  3. package/docs/markdown/README.md +27 -0
  4. package/docs/markdown/_sidebar.md +18 -0
  5. package/docs/markdown/commands.md +308 -0
  6. package/docs/markdown/config-discovery.md +74 -0
  7. package/docs/markdown/config-inspection.md +69 -0
  8. package/docs/markdown/config-layers.md +92 -0
  9. package/docs/markdown/config-variables.md +79 -0
  10. package/docs/markdown/configuration.md +71 -0
  11. package/docs/markdown/design-principles.md +59 -0
  12. package/docs/markdown/repositories-authoring.md +408 -0
  13. package/docs/markdown/repositories-consuming.md +580 -0
  14. package/docs/markdown/repositories-file-formats.md +1084 -0
  15. package/docs/markdown/repositories-variables.md +387 -0
  16. package/docs/markdown/repositories.md +303 -0
  17. package/docs/markdown/skill-categories.md +58 -0
  18. package/package.json +73 -9
  19. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/SKILL.tpl.md +20 -20
  20. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/about-something.md +2 -2
  21. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/examples/do-something.md +1 -1
  22. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/advanced-patterns.md +6 -6
  23. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/commands.md +5 -5
  24. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/frontmatter.md +3 -3
  25. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/SKILL.tpl.md +40 -25
  26. package/recipes/core/sous-skills/skills/about-sous/SKILL.tpl.md +70 -0
  27. package/recipes/core/sous-skills/skills/about-sous-configuration/SKILL.tpl.md +75 -0
  28. package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/create-skill/SKILL.tpl.md +8 -9
  29. package/recipes/core/sous-skills/sous.recipe.yaml +45 -0
  30. package/sous.config.schema.json +337 -0
  31. package/src/base-command.ts +220 -67
  32. package/src/commands/build.ts +150 -73
  33. package/src/commands/clear.ts +23 -15
  34. package/src/commands/compile.ts +74 -16
  35. package/src/commands/config/get.ts +110 -0
  36. package/src/commands/config/show.ts +32 -0
  37. package/src/commands/config/validate.ts +53 -0
  38. package/src/commands/help.ts +46 -0
  39. package/src/commands/launch.ts +36 -14
  40. package/src/commands/lock/rebuild.ts +241 -0
  41. package/src/commands/lock/show.ts +115 -0
  42. package/src/commands/namespace/list.ts +117 -0
  43. package/src/commands/namespace/show.ts +110 -0
  44. package/src/commands/prune.ts +3 -11
  45. package/src/commands/recipe/list.ts +95 -0
  46. package/src/commands/recipe/show.ts +301 -0
  47. package/src/commands/repo/add.ts +145 -0
  48. package/src/commands/repo/gc.ts +172 -0
  49. package/src/commands/repo/init.ts +136 -0
  50. package/src/commands/repo/link.ts +500 -0
  51. package/src/commands/repo/list.ts +179 -0
  52. package/src/commands/repo/release.ts +619 -0
  53. package/src/commands/repo/remove.ts +193 -0
  54. package/src/commands/repo/search.ts +189 -0
  55. package/src/commands/repo/submit.ts +133 -0
  56. package/src/commands/repo/unlink.ts +147 -0
  57. package/src/commands/subscription/add.ts +285 -0
  58. package/src/commands/subscription/list.ts +129 -0
  59. package/src/commands/subscription/remove.ts +181 -0
  60. package/src/commands/vars/ask.ts +374 -0
  61. package/src/commands/vars/index.ts +79 -0
  62. package/src/commands/vars/list.ts +67 -0
  63. package/src/commands/vars/show.ts +77 -0
  64. package/src/config-command.ts +30 -0
  65. package/src/lib/build-service.ts +206 -54
  66. package/src/lib/config-discovery.ts +220 -27
  67. package/src/lib/config-inspect.ts +145 -0
  68. package/src/lib/config-kernel.mjs +377 -0
  69. package/src/lib/config-schema.ts +361 -0
  70. package/src/lib/env-file.ts +328 -0
  71. package/src/lib/env-local.ts +18 -1
  72. package/src/lib/errors.ts +32 -0
  73. package/src/lib/include-resolver.ts +108 -15
  74. package/src/lib/interactive.ts +165 -0
  75. package/src/lib/markdown-compiler.ts +118 -37
  76. package/src/lib/package-info.ts +25 -0
  77. package/src/lib/pid-service.ts +32 -21
  78. package/src/lib/refs/find.ts +589 -0
  79. package/src/lib/refs/index.ts +12 -0
  80. package/src/lib/refs/pick.ts +147 -0
  81. package/src/lib/refs/scopes.ts +61 -0
  82. package/src/lib/repos/catalog-display.ts +116 -0
  83. package/src/lib/repos/catalog-inputs.ts +160 -0
  84. package/src/lib/repos/catalog.ts +722 -0
  85. package/src/lib/repos/core-recipe.ts +105 -0
  86. package/src/lib/repos/defaults.ts +175 -0
  87. package/src/lib/repos/formats/common.ts +389 -0
  88. package/src/lib/repos/formats/index-file.ts +215 -0
  89. package/src/lib/repos/formats/links-map.ts +96 -0
  90. package/src/lib/repos/formats/lockfile.ts +167 -0
  91. package/src/lib/repos/formats/patterns.ts +57 -0
  92. package/src/lib/repos/formats/recipe-manifest.ts +395 -0
  93. package/src/lib/repos/formats/repo-manifest.ts +88 -0
  94. package/src/lib/repos/formats/store-entry.ts +84 -0
  95. package/src/lib/repos/freshness.ts +208 -0
  96. package/src/lib/repos/git-clone.ts +312 -0
  97. package/src/lib/repos/identity.ts +89 -0
  98. package/src/lib/repos/index.ts +58 -0
  99. package/src/lib/repos/links.ts +353 -0
  100. package/src/lib/repos/load-manifest.ts +236 -0
  101. package/src/lib/repos/lock-service.ts +453 -0
  102. package/src/lib/repos/locked-namespace-resolver.ts +90 -0
  103. package/src/lib/repos/locked-recipes.ts +254 -0
  104. package/src/lib/repos/managed-layer.ts +422 -0
  105. package/src/lib/repos/namespace-resolver.ts +370 -0
  106. package/src/lib/repos/providers/base.ts +206 -0
  107. package/src/lib/repos/providers/git.ts +233 -0
  108. package/src/lib/repos/providers/github.ts +294 -0
  109. package/src/lib/repos/providers/gitlab.ts +263 -0
  110. package/src/lib/repos/providers/http.ts +102 -0
  111. package/src/lib/repos/providers/index-cache.ts +382 -0
  112. package/src/lib/repos/providers/index.ts +106 -0
  113. package/src/lib/repos/providers/local.ts +391 -0
  114. package/src/lib/repos/providers/provider.ts +401 -0
  115. package/src/lib/repos/recipe-config-layers.ts +287 -0
  116. package/src/lib/repos/recipe-targets.ts +223 -0
  117. package/src/lib/repos/ref-search.ts +46 -0
  118. package/src/lib/repos/ref.ts +513 -0
  119. package/src/lib/repos/reference-report.ts +122 -0
  120. package/src/lib/repos/release/bump.ts +161 -0
  121. package/src/lib/repos/release/git-state.ts +305 -0
  122. package/src/lib/repos/release/index-builder.ts +635 -0
  123. package/src/lib/repos/release/index.ts +16 -0
  124. package/src/lib/repos/release/plan.ts +512 -0
  125. package/src/lib/repos/release/submit-service.ts +496 -0
  126. package/src/lib/repos/release/tags.ts +243 -0
  127. package/src/lib/repos/release/validate.ts +463 -0
  128. package/src/lib/repos/resolver.ts +789 -0
  129. package/src/lib/repos/scaffold/index.ts +238 -0
  130. package/src/lib/repos/scaffold/templates.ts +413 -0
  131. package/src/lib/repos/seed.ts +414 -0
  132. package/src/lib/repos/store/contract.ts +64 -0
  133. package/src/lib/repos/store/hash.ts +114 -0
  134. package/src/lib/repos/store/recipe-store.ts +599 -0
  135. package/src/lib/repos/store/settings.ts +58 -0
  136. package/src/lib/repos/subscription-service.ts +2678 -0
  137. package/src/lib/repos/trust.ts +447 -0
  138. package/src/lib/settings.ts +546 -189
  139. package/src/lib/sous-home.ts +104 -0
  140. package/src/lib/state.ts +52 -20
  141. package/src/lib/vars/ask.ts +1152 -0
  142. package/src/lib/vars/definition-source.ts +252 -0
  143. package/src/lib/vars/display.ts +233 -0
  144. package/src/lib/vars/index.ts +18 -0
  145. package/src/lib/vars/ladder.ts +282 -0
  146. package/src/lib/vars/mappings.ts +265 -0
  147. package/src/lib/vars/names.ts +94 -0
  148. package/src/lib/vars/preanswers.ts +395 -0
  149. package/src/lib/vars/question-plan.ts +218 -0
  150. package/src/lib/vars/report.ts +228 -0
  151. package/src/lib/vars/safe-regex.ts +235 -0
  152. package/src/lib/vars/validate.ts +312 -0
  153. package/src/lib/watch-loop.ts +148 -0
  154. package/src/templating/init-liquid-engine.ts +58 -16
  155. package/src/utils/choice-prompt.ts +143 -0
  156. package/src/utils/command-errors.ts +186 -0
  157. package/src/utils/command-help.ts +45 -0
  158. package/src/utils/confirm-prompt.ts +110 -0
  159. package/src/utils/flags.ts +153 -0
  160. package/src/utils/formatting.ts +540 -55
  161. package/src/utils/prompts.ts +35 -1
  162. package/src/utils/sous-directory.ts +245 -0
  163. package/src/utils/table.ts +603 -0
  164. package/src/utils/value-prompt.ts +119 -0
  165. package/bin/xcv +0 -5
  166. package/shared-prompts/_partials/resume-task.md +0 -51
  167. package/shared-prompts/_partials/sub-agent-delegation.md +0 -32
  168. package/shared-prompts/_partials/update-task-file.md +0 -52
  169. package/shared-prompts/memories/automated-browser-tasks/INDEX.tpl.md +0 -52
  170. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/SKILL.tpl.md +0 -102
  171. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/auth-failure-handling.mjs +0 -81
  172. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/chained-workflow.mjs +0 -126
  173. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/examples/simple-fetch.mjs +0 -92
  174. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/architecture.md +0 -61
  175. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/auth-and-sessions.md +0 -65
  176. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/ctx-api.md +0 -96
  177. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/installation.md +0 -104
  178. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/references/script-conventions.md +0 -243
  179. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/chrome-state.mjs +0 -148
  180. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.mjs +0 -383
  181. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/debug.spec.mjs +0 -267
  182. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/eslint.config.mjs +0 -56
  183. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/harness.mjs +0 -169
  184. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/keyring.mjs +0 -59
  185. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/logger.mjs +0 -25
  186. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/params.mjs +0 -140
  187. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/run.mjs +0 -140
  188. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/settings.tpl.mjs +0 -1
  189. package/shared-prompts/skills/automated-browser-tasks/about-automated-browser-tasks/scripts/utils.mjs +0 -185
  190. package/shared-prompts/skills/automated-browser-tasks/create-automated-browser-task/SKILL.tpl.md +0 -52
  191. package/shared-prompts/skills/automated-browser-tasks/running-automated-browser-tasks/SKILL.tpl.md +0 -59
  192. package/shared-prompts/skills/automated-browser-tasks/update-automated-browser-task/SKILL.tpl.md +0 -47
  193. package/shared-prompts/skills/control-flow/approve/SKILL.tpl.md +0 -26
  194. package/shared-prompts/skills/control-flow/opine/SKILL.tpl.md +0 -58
  195. package/shared-prompts/skills/control-flow/repeat/SKILL.tpl.md +0 -27
  196. package/shared-prompts/skills/control-flow/research/SKILL.tpl.md +0 -34
  197. package/shared-prompts/skills/sous-skills/about-sous/SKILL.tpl.md +0 -51
  198. package/shared-prompts/skills/task-files/about-task-files/SKILL.tpl.md +0 -122
  199. package/shared-prompts/skills/task-files/continue-task-in-new-branch/SKILL.tpl.md +0 -80
  200. package/shared-prompts/skills/task-files/go/SKILL.tpl.md +0 -14
  201. package/shared-prompts/skills/task-files/resume-task/SKILL.tpl.md +0 -13
  202. package/shared-prompts/skills/task-files/start-task/SKILL.tpl.md +0 -93
  203. package/shared-prompts/skills/task-files/update/SKILL.tpl.md +0 -14
  204. package/shared-prompts/skills/task-files/update-task-file/SKILL.tpl.md +0 -13
  205. /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-agent-skills/references/substitutions.md +0 -0
  206. /package/{shared-prompts/skills/sous-skills → recipes/core/sous-skills/skills}/about-liquid-templates/references/liquid-filters.md +0 -0
@@ -0,0 +1,387 @@
1
+ # Recipe Variables
2
+
3
+ A recipe that needs a value from your project publishes a **variable definition**: a
4
+ specification with a name, a type, a question and a set of constraints. You supply an **answer**.
5
+ A "question" is only the interactive moment; sous asks one only when a subscribed recipe needs a
6
+ variable and nothing in scope answers it, or when the answer in scope no longer fits.
7
+
8
+ ?> This page is about variables that recipes publish. Your project's own `${var}` configuration
9
+ variables are a different, older, deliberately ceremony-free system; see
10
+ [Variables](config-variables.md) for those. The two never mix.
11
+
12
+ ## Where answers live
13
+
14
+ Answers are stored in your project's env files, and nowhere else:
15
+
16
+ | File | Committed | Holds |
17
+ |------|-----------|-------|
18
+ | `.sous/.env` | yes | Shared answers (`scope: shared`), the team's defaults |
19
+ | `.sous/.env.local` | no, gitignored | Machine-specific answers (`scope: local`) and every secret |
20
+
21
+ Sous edits these files the way a careful person would. Exactly one value line is rewritten or
22
+ appended; comments, blank lines, ordering and quoting all survive untouched. A newly added entry
23
+ gets a short generated header comment above it saying where the value came from:
24
+
25
+ ```bash
26
+ # Set by sous for workflow/task-files: Where should task files live?
27
+ # One file per git branch is written here.
28
+ # Edit freely; sous only rewrites the value line.
29
+ SOUS_VAR_TASK_FILE_ROOT=.sous/tasks
30
+ ```
31
+
32
+ Those comments are output only. Sous never reads one back, so editing or deleting a comment
33
+ changes nothing, and editing the value line is a perfectly normal way to change an answer.
34
+
35
+ ## The ladder
36
+
37
+ For each variable, sous generates a list of environment variable names and tries them in order,
38
+ most specific first. The first name that holds a value wins.
39
+
40
+ | Rung | Name | Example | When it applies |
41
+ |------|------|---------|-----------------|
42
+ | 1. mapping record | whatever the record names | `TEAM_API_URL` | Only when a record exists for this variable |
43
+ | 2. recipe scope | `SOUS_VAR_<NAMESPACE>_<RECIPE>_<VARIABLE>` | `SOUS_VAR_WORKFLOW_TASK_FILES_API_URL` | Answers this one recipe's variable and nothing else |
44
+ | 3. namespace scope | `SOUS_VAR_<NAMESPACE>_<VARIABLE>` | `SOUS_VAR_WORKFLOW_API_URL` | Answers every recipe in the namespace at once |
45
+ | 4. shared scope | `SOUS_VAR_<VARIABLE>` | `SOUS_VAR_API_URL` | Answers every recipe that declares that variable name |
46
+ | 5. declared name | the definition's own `env` field | `GITHUB_TOKEN` | How a recipe binds a value the environment already carries |
47
+
48
+ Read from the bottom up, the ladder is a story about sharing. One `SOUS_VAR_API_URL` answers
49
+ every recipe that wants an `apiUrl`, which is what you want most of the time. When two recipes
50
+ want the same name and mean different things, move one answer up a rung to the namespace or the
51
+ recipe form, and the more specific name wins for that recipe alone. When even that is not enough,
52
+ a mapping record settles it.
53
+
54
+ !> Candidate names are only ever GENERATED and looked up, never parsed back into scopes. The
55
+ underscore is both the delimiter and a legal identifier character, so no parse of a name would be
56
+ trustworthy: `SOUS_VAR_TASK_FILES_ROOT` could be three different things. Sous therefore builds the
57
+ five candidates it knows are correct and asks the environment about each one.
58
+
59
+ ## The three sources, within a rung
60
+
61
+ Each rung is looked up in three places, in this order:
62
+
63
+ 1. **The real shell environment.** `SOUS_VAR_API_URL=... sous build` beats both files.
64
+ 2. **`.sous/.env.local`.** Gitignored; your machine, your secrets.
65
+ 3. **`.sous/.env`.** Committed; the team's shared defaults.
66
+
67
+ No load ever overwrites a value that is already set, so the first writer wins. This is the same
68
+ precedence the rest of sous uses for env files; see
69
+ [Discovery and overrides](config-discovery.md).
70
+
71
+ ## Mapping records
72
+
73
+ A mapping record binds one environment variable, of any name at all, to one fully qualified
74
+ variable. It is the top rung and the universal conflict resolver: two recipes wanting the same
75
+ name, or a name that already means something else in your environment.
76
+
77
+ ```json
78
+ {
79
+ "varMappings": {
80
+ "TEAM_API_URL": "sous-recipes:misc/stuff/apiUrl"
81
+ }
82
+ }
83
+ ```
84
+
85
+ A target is written `namespace/recipe/variableName`, optionally qualified as
86
+ `repo:namespace/recipe/variableName`. Records live under the top-level `varMappings` config key.
87
+ Sous writes the ones it creates into `.sous/conf.d/520-var-mappings.jsonc`, editing one record at
88
+ a time so each name has exactly one, and you may hand-write `varMappings` in your primary config
89
+ too; the two merge like any other config layer.
90
+
91
+ You rarely write one yourself, because sous offers one at the moment the conflict appears. When
92
+ the name an answer would use already holds a value that does not fit the definition, you are
93
+ asked where the answer should go:
94
+
95
+ ```text
96
+ SERVICE_TOKEN already holds a value that does not fit serviceToken. Where should this answer go?
97
+ SOUS_VAR_TOOLING_DEPLOY_SERVICE_TOKEN, with a mapping record (recommended)
98
+ SERVICE_TOKEN, replacing what is there
99
+ ```
100
+
101
+ Choosing the record writes both the answer under the scoped name and the record binding it, and
102
+ the run reports the pair. Where there is no terminal, the record is written, because overwriting
103
+ a value something else is already using would be the worse of the two guesses.
104
+
105
+ ## `sous vars list`
106
+
107
+ Lists every variable in play: its name, the recipe that published it, the environment variable
108
+ that answered it, the value, and where the value came from. A secret's value is hidden.
109
+
110
+ ```term
111
+ $ sous vars list
112
+ Variable Recipe Answered by Value Source
113
+ apiUrl workflow/task-files SOUS_VAR_API_URL https://api.example.com shared scope, the .env file
114
+ taskFileRoot workflow/task-files SOUS_VAR_TASK_... .sous/tasks shared scope, the .env file
115
+ serviceToken tooling/deploy nothing yet
116
+ ```
117
+
118
+ `--file <path>` reads definitions from a standalone definitions file instead of the project's
119
+ recipes. The file holds the same `variables:` array a recipe manifest carries, which is how a
120
+ project asks questions no recipe publishes yet.
121
+
122
+ ## `sous vars show <name>`
123
+
124
+ Shows one variable in full: its question, the publisher's description and example, the recipe and
125
+ version that published it, the value in scope and whether it fits, then the same labeled facts the
126
+ advanced view of a question prints, and finally every name on the ladder with the rung that
127
+ actually answered.
128
+
129
+ ```term
130
+ $ sous vars show apiUrl
131
+ Question : Which API should sous talk to?
132
+ About : Every request this recipe generates is sent to one deployment of
133
+ the API, and this setting says which one. The default points at
134
+ the public production host, but any deployment you can reach works.
135
+ For example: https://api.example.com
136
+ Recipe : workflow/task-files version 1.2.0 from sous-recipes
137
+ Stored in : .env
138
+ Value : https://api.example.com
139
+
140
+ example : https://api.example.com
141
+ required-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
142
+ defined-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
143
+ storage-path: /home/you/project/.sous/.env
144
+ stored-as : SOUS_VAR_API_URL
145
+ constraints : • must be a value of the type url (type: url)
146
+
147
+ Environment variable Rung Status
148
+ SOUS_VAR_WORKFLOW_TASK_FILES_API_URL recipe scope not set
149
+ SOUS_VAR_WORKFLOW_API_URL namespace scope not set
150
+ SOUS_VAR_API_URL shared scope answered it, from the .env file
151
+ ```
152
+
153
+ `required-by` and `defined-by` are the same links the advanced view of a question shows, so the
154
+ two views say the same thing in the same words.
155
+
156
+ The name may be the bare variable name or its full `namespace/recipe.name` key, which is what you
157
+ use when two recipes publish the same name.
158
+
159
+ ?> Three names cannot be reached by the `sous vars <name>` shorthand: `list`, `show` and `ask`,
160
+ because each of those is a subcommand. A variable with one of those names is reached the long
161
+ way, as `sous vars show ask`.
162
+
163
+ ## `sous vars ask`
164
+
165
+ Asks the questions the project's definitions imply and stores the answers.
166
+
167
+ | Invocation | What it does |
168
+ |------------|--------------|
169
+ | `sous vars ask` | Asks only what is unanswered, or what no longer fits its definition |
170
+ | `sous vars ask <name>` | Asks everything the name covers; see the forms below |
171
+ | `sous vars ask --repo <name>` | Asks every variable one repository publishes |
172
+ | `sous vars ask --namespace <name>` | Asks every variable one namespace publishes |
173
+ | `sous vars ask --var <name>` | Asks one variable; repeat it for each variable |
174
+ | `sous vars ask --accept-first` | When the name matches several things, takes the first one listed |
175
+ | `sous vars ask --all` | Asks every variable again, including the ones already answered |
176
+ | `sous vars ask --file <path>` | Reads definitions from a standalone definitions file |
177
+ | `sous vars ask --answer <name>=<value>` | Answers one question ahead of time; repeat it for each answer |
178
+ | `sous vars ask --answers-file <path>` | Reads answers from a YAML or JSON file of `name: value` pairs |
179
+ | `sous vars ask --dry-run` | Reports what would be asked and written, without writing anything |
180
+
181
+ ### What the name may be
182
+
183
+ The name is a reference, resolved the way every sous command resolves one. It may name a
184
+ variable, an environment variable that answers one, a recipe, a namespace or a repository, and
185
+ anything larger than a variable asks every question it publishes:
186
+
187
+ ```term
188
+ $ sous vars ask taskFileRoot
189
+ // one variable, by the name its recipe gave it
190
+ $ sous vars ask SOUS_VAR_TASK_FILE_ROOT
191
+ // the same variable, by an environment variable in use that answers it
192
+ $ sous vars ask workflow/task-files.taskFileRoot
193
+ // the same variable again, spelled out
194
+ $ sous vars ask task-files
195
+ // every question that one recipe asks
196
+ $ sous vars ask workflow
197
+ // every question every recipe in that namespace asks
198
+ $ sous vars ask sous-recipes
199
+ // every question that repository's recipes ask
200
+ ```
201
+
202
+ Every reference may be written at any level of qualification, up to the fully qualified
203
+ `repository:namespace/recipe.variable`, and matching is case-sensitive. An environment variable
204
+ name resolves when the definition declares it (a recipe may bind an existing variable such as
205
+ `GITHUB_TOKEN`) or when it is one of the generated ladder names that `.sous/.env` or
206
+ `.sous/.env.local` actually sets.
207
+
208
+ `--repo`, `--namespace` and `--var` say outright which kind of thing is meant, and narrow the
209
+ same way. Each one resolves against what the one before it left, so
210
+ `sous vars ask --namespace workflow apiUrl` asks about that namespace's `apiUrl` even when
211
+ another namespace publishes one too.
212
+
213
+ When a name matches more than one thing, sous lists what it could have meant and asks which one
214
+ you meant. `--accept-first` takes the first one listed, and a run with no terminal fails naming
215
+ that flag rather than guessing.
216
+
217
+ ### How the questions run
218
+
219
+ Every trust decision is settled first. A subscribe resolves the whole dependency closure and runs
220
+ the trust ceremony for each new repository before the first question is printed, so a question is
221
+ never interleaved with a decision about who you are trusting.
222
+
223
+ Questions then run one recipe at a time: the recipe you subscribed to first, then each recipe it
224
+ depends on, each opening with how many answers it needs. When the closure covers more than one
225
+ recipe, a single lead-in says so before anything is asked:
226
+
227
+ ```term
228
+ workflow/task-files needs 4 answers, and workflow/sub-agent-delegation, which it depends on, needs 2.
229
+ ```
230
+
231
+ Each question then prints its own view: the header, the publisher's description wrapped to your
232
+ terminal, and four labeled facts (the default, the example, and exactly where the answer will be
233
+ stored and under what name). The keys that do anything are named by the legend the question draws
234
+ under its own input line, in the style the stock prompts use. Those facts are drawn by the renderer
235
+ the advanced view uses, so the same label means the same thing and lines up the same way on both.
236
+
237
+ ```term
238
+ workflow/task-files needs 4 answers before it can be used.
239
+
240
+ Question 1 of 4: taskFileRoot
241
+
242
+ This recipe mandates the creation of task files that are stored locally and, in
243
+ general, should not be committed. This setting dictates the path in which agents
244
+ will store and search for your task files. The default value stores task files in
245
+ the project's .sous directory, but you can specify any local path, either relative
246
+ to the project root or absolute.
247
+
248
+ default : .sous/tasks
249
+ example : ~/my-task-files
250
+ stored-as : SOUS_VAR_TASK_FILE_ROOT
251
+ storage-path: /home/you/project/.sous/.env
252
+
253
+ ? Where should task files be stored? (.sous/tasks):
254
+ ⏎ accept default • ⇥ advanced
255
+ ```
256
+
257
+ Enter accepts what is typed, or the default when nothing is. A question with no default drops
258
+ the Enter half of the legend, since there is nothing for Enter alone to accept, and shows
259
+ `⇥ advanced` alone. A question answered from a list rather than typed names the arrow keys
260
+ instead:
261
+
262
+ ```term
263
+ ? Which ticket system do you use?
264
+ > github
265
+ jira
266
+ linear
267
+ ↑↓ navigate • ⏎ select • ⇥ advanced
268
+ ```
269
+
270
+ Tab opens the advanced view from every kind of question: a typed one, a pick-one list, and a
271
+ yes-or-no confirmation alike. The word is always "Advanced". Once an answer is stored, two lines
272
+ say what was stored and where:
273
+
274
+ ```term
275
+ Answer : SOUS_VAR_TASK_FILE_ROOT=.sous/tasks
276
+ Saved to: /home/you/project/.sous/.env
277
+ ```
278
+
279
+ An answer that was already in scope is never asked about again; it is reported with its scope and
280
+ its source instead.
281
+
282
+ ### The advanced view
283
+
284
+ Tab opens the advanced view of the same question: every fact about the variable, laid out by the
285
+ same renderer `sous vars show` uses, and a menu for changing where the answer goes.
286
+
287
+ ```term
288
+ [Advanced Variable Settings]
289
+
290
+ Question 1 of 4: taskFileRoot
291
+
292
+ This recipe mandates the creation of task files that are stored locally and, in
293
+ general, should not be committed. This setting dictates the path in which agents
294
+ will store and search for your task files. The default value stores task files in
295
+ the project's .sous directory, but you can specify any local path, either relative
296
+ to the project root or absolute.
297
+
298
+ default : .sous/tasks
299
+ example : ~/my-task-files
300
+ required-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
301
+ defined-by : workflow/task-files https://example.com/owner/recipes/workflow/task-files
302
+ storage-path: /home/you/project/.sous/.env
303
+ stored-as : SOUS_VAR_TASK_FILE_ROOT
304
+ constraints : • must be a value of the type path (type: path)
305
+ • must be at least 1 character long (minLength: 1)
306
+
307
+ ? What would you like to do?
308
+ Return to value entry
309
+ Change the storage file
310
+ Change the stored variable name
311
+ ```
312
+
313
+ `required-by` names the recipe you subscribed to whose closure pulled this variable in, and spells
314
+ out the chain when it arrived through a dependency; `defined-by` names the recipe that declares
315
+ the definition. Both carry the location beside the recipe key, in muted grey: a repository URL with
316
+ the recipe's folder for a hosted repository, and a filesystem path for one read from this machine.
317
+
318
+ Changing the stored name offers every rung the ladder looks up, with the one sous would use
319
+ already selected, plus a name of your own; a name the ladder would never look at is bound with a
320
+ mapping record, so resolution still finds it. Changing the storage file offers the committed
321
+ `.sous/.env` and the gitignored `.sous/.env.local`. Once anything has changed, the first menu item
322
+ becomes "Save changes and return to value entry" and a "Discard changes" item joins it.
323
+
324
+ A secret, or a variable the publisher declared machine-specific, may still be pointed at the
325
+ committed file. Sous does not prevent it; it says plainly that the value would enter your git
326
+ history and asks you to confirm, which is informed consent rather than a locked door. Returning to
327
+ the value question prints its view again, with the updated `stored-as` and `storage-path`
328
+ facts.
329
+
330
+ Every run ends with the same three-part report: what was inherited from an answer already in
331
+ scope, what was stored and under which name in which file, and what was left unanswered and why.
332
+
333
+ Subscribing runs the same machinery, so in normal use you rarely invoke `vars ask` by hand;
334
+ reach for it after editing an env file, after a recipe upgrade tightened a constraint, or when
335
+ you want to re-answer something deliberately with `--all`.
336
+
337
+ ### Answering ahead of the questions
338
+
339
+ `--answer <name>=<value>` answers a question before it is asked, and repeats for as many answers
340
+ as there are questions; `--answers-file <path>` reads the same pairs from a YAML or JSON file
341
+ (comments allowed), and an `--answer` wins over the same name in the file. Both flags work the
342
+ same way on `sous subscription add`, which is where a run with no terminal usually meets them;
343
+ [Consuming recipes](repositories-consuming.md#answering-questions-ahead-of-time) walks through
344
+ that flow, dry run first.
345
+
346
+ ```bash
347
+ sous vars ask --answer taskFileRoot=.sous/tasks --answer apiUrl=https://api.example.com
348
+ sous vars ask --answers-file ./answers.yaml
349
+ ```
350
+
351
+ The name is spelled exactly as the recipe declares it, in camelCase, or as its full
352
+ `namespace/recipe.name` key; everything after the first `=` is the answer. Every supplied answer
353
+ is checked against its definition before anything is written, so a value that does not fit fails
354
+ the run naming the constraint and the publisher's example, and a name no recipe declares fails
355
+ naming every variable that is in play. An answer for a variable that already has one replaces it,
356
+ where that answer lives, and the report says what it replaced. Whatever is left over is asked for
357
+ as usual.
358
+
359
+ ## Without a terminal
360
+
361
+ Sous never hangs waiting on a prompt it cannot show. A run with no terminal and an unanswered
362
+ required variable fails, and the failure names every environment variable that would satisfy it,
363
+ most specific first, which is the message a continuous integration log needs to be useful:
364
+
365
+ ```text
366
+ One variable still needs an answer, and there is no terminal to ask on.
367
+
368
+ Set one of the environment variables listed under each variable, or run
369
+ 'sous vars ask' from a terminal.
370
+
371
+ apiUrl (workflow/task-files): Where does the API live?
372
+ SOUS_VAR_WORKFLOW_TASK_FILES_API_URL (recipe scope)
373
+ SOUS_VAR_WORKFLOW_API_URL (namespace scope)
374
+ SOUS_VAR_API_URL (shared scope)
375
+ ```
376
+
377
+ Set one of those names as a secret or a variable in your pipeline and the build proceeds. For an
378
+ answer the whole team shares and nothing about it is sensitive, committing it to `.sous/.env` is
379
+ simpler still: a fresh clone then needs no pipeline configuration at all.
380
+
381
+ ## Where to go next
382
+
383
+ - [Consuming recipes](repositories-consuming.md): subscribing, building, and what lands where
384
+ - [Authoring a repository](repositories-authoring.md): declaring the definitions this page
385
+ resolves
386
+ - [Variable definitions](repositories-file-formats.md#variable-definitions): the full field table
387
+ - [Command reference](commands.md): every command and flag