@ishlabs/cli 0.8.4 → 0.9.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.
package/dist/lib/docs.js CHANGED
@@ -18,7 +18,7 @@ Workspace (= product)
18
18
  ├── Tester Profiles ────── reusable audience personas (alias: tp-…)
19
19
  │ └── Sources ──────── transcripts/audio/images that seed generation
20
20
  ├── Study ──────────────── persistent research artifact (alias: s-…)
21
- │ ├── modality ──────── interactive | text | video | audio | image | document
21
+ │ ├── modality ──────── interactive | text | video | audio | image | document | chat
22
22
  │ ├── assignments ───── tasks the tester does
23
23
  │ ├── questionnaire ─── questions the tester answers
24
24
  │ └── Iterations ────── one configured run (URL or content) (alias: i-…)
@@ -47,7 +47,8 @@ Two top-level run verbs:
47
47
  and prints active workspace/study/ask. See \`concepts/active-context\`.
48
48
  - Running your first study? \`ish docs get-page guides/first-study\`.
49
49
  - Comparing study vs ask? \`ish docs get-page concepts/run-verbs\`.
50
- - Need machine-readable output? \`ish docs get-page reference/json-mode\`.
50
+ - **Output modes** (display vs capture vs chain — \`--human\`, \`--get\`,
51
+ \`--json\`)? \`ish docs get-page reference/json-mode\`.
51
52
  - Auth gated URL? \`ish docs get-page concepts/site-access\`.
52
53
 
53
54
  ## Install the skill into this project
@@ -74,6 +75,22 @@ A workspace carries:
74
75
  - Site-access credentials (encrypted at rest) — see \`concepts/site-access\`.
75
76
  - Tester profiles + sources visible to every study/ask in the workspace.
76
77
 
78
+ ## Selecting a workspace per command
79
+
80
+ \`--workspace <id>\` works at the **program root** as well as on each
81
+ subcommand — both forms are equivalent, and the subcommand-level flag
82
+ wins on conflict:
83
+
84
+ \`\`\`
85
+ ish --workspace w-6ec study list # program root
86
+ ish study list --workspace w-6ec # subcommand (same effect)
87
+ ish --workspace w-6ec study list --workspace w-other # w-other wins
88
+ \`\`\`
89
+
90
+ Use whichever is most natural for your scripting. Without either, the
91
+ CLI falls back to \`ISH_WORKSPACE\` (env var) and then the
92
+ \`workspace\` saved in \`~/.ish/config.json\`.
93
+
77
94
  ## Common commands
78
95
 
79
96
  \`\`\`
@@ -91,8 +108,9 @@ ish workspace site-access status
91
108
  const CONCEPT_STUDY = `# concept: study
92
109
 
93
110
  A **study** is the persistent research artifact. It defines:
94
- - \`modality\`: \`interactive\` (the tester drives a real browser) or one of
95
- \`text | video | audio | image | document\` (media reaction studies).
111
+ - \`modality\`: \`interactive\` (the tester drives a real browser), one of
112
+ \`text | video | audio | image | document\` (media reaction studies),
113
+ or \`chat\` (multi-turn probe against an external chatbot endpoint).
96
114
  - \`content_type\` (media studies only): \`email | social_post | ad | …\` —
97
115
  controls the framing the tester is given.
98
116
  - \`assignments\`: the tasks the tester performs. See \`concepts/assignment\`.
@@ -148,6 +166,21 @@ Every study response carries two status-shaped fields:
148
166
  The CLI also surfaces a \`status_inferred\` field + stderr warning when
149
167
  it detects raw-vs-derived inconsistencies. See \`reference/json-mode\`.
150
168
 
169
+ ## Deleting a study
170
+
171
+ \`ish study delete <id>\` requires explicit confirmation:
172
+
173
+ - **Interactive (TTY)**: prompts on stderr; type \`y\` to proceed.
174
+ - **Non-interactive** (\`--json\`, piped, or non-TTY stdin): pass
175
+ \`-y\` / \`--yes\` to confirm. Without it, the CLI exits with usage
176
+ code 2 rather than deleting silently.
177
+
178
+ \`\`\`
179
+ ish study delete s-b2c # interactive prompt
180
+ ish study delete s-b2c --yes # skip prompt
181
+ ish study delete s-b2c --json --yes # JSON consumers must be explicit
182
+ \`\`\`
183
+
151
184
  ## Generate vs create
152
185
 
153
186
  \`ish study generate --problem "..."\` runs an LLM-backed flow that
@@ -168,9 +201,9 @@ pick was wrong.
168
201
  const CONCEPT_ITERATION = `# concept: iteration
169
202
 
170
203
  An **iteration** is one configured run of a study. It carries the
171
- volatile bits — the URL (interactive) or the media (video/text/etc.)
172
- while the study carries the persistent shape (assignments, questionnaire,
173
- modality).
204
+ volatile bits — the URL (interactive), the media (video/text/etc.), or
205
+ the chatbot endpoint (chat) — while the study carries the persistent
206
+ shape (assignments, questionnaire, modality).
174
207
 
175
208
  - Alias prefix: \`i-\`
176
209
  - A study has 1..N iterations. \`ish study run\` defaults to the latest.
@@ -192,9 +225,19 @@ ish iteration create --study s-b2c --url https://example.com
192
225
  # Interactive on mobile screen format:
193
226
  ish iteration create --url https://example.com --screen-format mobile_portrait
194
227
 
228
+ # Figma interactive (file_key + start_node_id required):
229
+ ish iteration create --platform figma --url https://figma.com/proto \\
230
+ --screen-format mobile_portrait --file-key abc123 --start-node-id 0:1 \\
231
+ --flow-name "Onboarding A"
232
+
195
233
  # Text/email content from a file:
196
234
  ish iteration create --content-text @./email.html --title "Newsletter"
197
235
 
236
+ # Email iteration with sender + featured hero image:
237
+ ish iteration create --content-text @./email.txt --content-html @./email.html \\
238
+ --sender-name "Marketing" --sender-email "marketing@example.com" \\
239
+ --featured-image-url https://cdn.example.com/hero.png
240
+
198
241
  # Video (URL or local file):
199
242
  ish iteration create --content-url ./video.mp4
200
243
 
@@ -204,11 +247,113 @@ ish iteration create --image-urls "./a.png,./b.png"
204
247
  # Document (PDF):
205
248
  ish iteration create --content-url ./report.pdf
206
249
 
250
+ # Chat — probe a saved chatbot endpoint:
251
+ ish iteration create --chat-endpoint-id ce-... --max-turns 10 --early-termination
252
+
207
253
  # Inspect:
208
254
  ish iteration list --study s-b2c
209
255
  ish iteration get i-d4e
210
256
  \`\`\`
211
257
 
258
+ ## Segments and segment labels
259
+
260
+ For media iterations (video, audio, text, image, document), reactions
261
+ can be collected per **segment** instead of over the whole asset. A
262
+ segment is a contiguous slice of the iteration's content — a 30-second
263
+ window of a video, a paragraph range of an email, a section of a PDF.
264
+ Each segment can carry a human-readable **label** ("Intro", "Pricing
265
+ section", "Call to action") that surfaces in the tester UI and in
266
+ results.
267
+
268
+ Segments live inside the iteration's \`segmentation\` field — there is
269
+ no separate segments resource. Three discriminated shapes:
270
+
271
+ - **time_based** (video, audio): boundaries in seconds. Segment 0 runs
272
+ from \`intervals_seconds[0]\` to \`intervals_seconds[1]\`, etc.
273
+ Optional \`labels[]\` names each segment.
274
+
275
+ \`\`\`json
276
+ {
277
+ "type": "time_based",
278
+ "intervals_seconds": [0, 30, 60, 90],
279
+ "labels": ["Hook", "Feature 1", "Feature 2", "CTA"]
280
+ }
281
+ \`\`\`
282
+
283
+ - **section_based** (text, document, image copy): explicit list of
284
+ named sections, either marker-bounded or paragraph-bounded.
285
+
286
+ \`\`\`json
287
+ {
288
+ "type": "section_based",
289
+ "sections": [
290
+ { "name": "intro", "label": "Intro", "paragraph_start": 0, "paragraph_end": 1 },
291
+ { "name": "body", "label": "Body", "paragraph_start": 1, "paragraph_end": 4 },
292
+ { "name": "cta", "label": "Call to action", "paragraph_start": 4, "paragraph_end": 5 }
293
+ ]
294
+ }
295
+ \`\`\`
296
+
297
+ - **page_based** (document): pages are auto-derived from the document.
298
+ No additional fields.
299
+
300
+ Pass via \`--segmentation-json '<json>'\` on \`iteration create\`.
301
+
302
+ ### Default segmentation for text/image iterations
303
+
304
+ For text- and image-modality iterations created without
305
+ \`--segmentation-json\`, the worker synthesises a single whole-content
306
+ section so a minimal \`ish iteration create --content-text "..."\` runs
307
+ end-to-end. Author your own segmentation when you want section-level
308
+ reactions; otherwise the default just works.
309
+
310
+ ### content_config — early termination + selected segments
311
+
312
+ A sibling of \`segmentation\` that controls how the tester progresses
313
+ through segments:
314
+
315
+ - \`early_termination: true\` — stop the session once every selected
316
+ segment has been seen.
317
+ - \`selected_segment_indices: [0, 2]\` — only show these segment
318
+ indices; \`null\` (default) means all segments are active.
319
+
320
+ Pass via \`--content-config-json '<json>'\`.
321
+
322
+ ## HTML content (text + media captions)
323
+
324
+ - **Text modality**: pair plain \`--content-text\` with rich
325
+ \`--content-html\` to render emails / articles with formatting. The
326
+ plain text is what testers reason over; the HTML is what they see.
327
+ - **Media captions** (video, audio, image): \`--copy-text\` and
328
+ \`--copy-html\` attach a caption to the media — the social-post
329
+ pattern. Add \`--social-platform\` (instagram/tiktok/facebook/linkedin/x)
330
+ for platform-specific framing, and \`--copy-position before|after\`
331
+ for ordering relative to the media.
332
+
333
+ Captions can carry their own segmentation when you want
334
+ paragraph-by-paragraph reactions to a long caption. Use the
335
+ \`--details-json\` escape hatch to pass a nested
336
+ \`copy_content.segmentation\`.
337
+
338
+ ## Chat modality
339
+
340
+ Chat iterations probe an external chatbot endpoint by having a tester
341
+ hold a multi-turn conversation against it. Two ways to wire the
342
+ endpoint:
343
+
344
+ \`\`\`
345
+ # Reference a saved endpoint row (recommended — reproducible):
346
+ ish iteration create --chat-endpoint-id ce-...
347
+
348
+ # Inline endpoint config (one-off):
349
+ ish iteration create --chat-endpoint-json '{"url":"https://...","headers":{...}}'
350
+ \`\`\`
351
+
352
+ Tunables:
353
+ - \`--max-turns N\` — cap the conversation length (default 12, max 50).
354
+ - \`--early-termination\` — let the worker end the session early when
355
+ the tester signals the conversation is over.
356
+
212
357
  ## No more auto-empty iteration A
213
358
 
214
359
  \`ish study create\` and \`ish study generate\` **do not auto-create
@@ -229,16 +374,6 @@ then retry.
229
374
 
230
375
  Treat this as actionable, not transient — re-running won't change anything.
231
376
 
232
- ## Default segmentation for text/image iterations
233
-
234
- For text-modality iterations created with just \`--content-text\` (and
235
- similarly \`--image-urls\` for image), the worker now synthesises a
236
- single whole-content section if no \`segmentation\` was supplied. This
237
- means a minimal \`ish iteration create --study s-XYZ --content-text
238
- "..."\` actually runs end-to-end without you needing to author a
239
- SegmentationConfig manually. Author your own segmentation when you
240
- want section-level reactions; otherwise the default just works.
241
-
242
377
  ## Related
243
378
 
244
379
  - \`concepts/study\` — the parent artifact.
@@ -379,7 +514,12 @@ ish ask results a-6ec --json | jq '.rounds[0].aggregates'
379
514
 
380
515
  For \`--wants-pick\` / \`--wants-ratings\` rounds, \`ask results --json\`
381
516
  includes an \`aggregates\` field per round so you don't have to parse
382
- prose:
517
+ prose. Each individual pick also carries a **\`pick_confidence\`** score
518
+ (0..1) — the model's self-reported confidence in its variant choice.
519
+ Use it to break ties: when two variants are nominally close on count,
520
+ the variant with higher mean \`pick_confidence\` is the more decisive
521
+ choice. \`pick_confidence\` is only present on rounds run with
522
+ \`--wants-pick\`.
383
523
 
384
524
  \`\`\`json
385
525
  {
@@ -517,6 +657,24 @@ ish profile create --file profile.json
517
657
  Expected JSON: \`{ "name": "...", "type": "ai", "gender": "female",
518
658
  "country": "US", "occupation": "...", "bio": "..." }\`
519
659
 
660
+ ## Generation behavior to expect
661
+
662
+ - **Latency**: \`profile generate\` is LLM-backed and typically takes
663
+ 10–20s for 1–5 profiles. The CLI emits stderr progress lines
664
+ (\`generating N profiles…\` then \`generated N profiles\`) so you
665
+ know it's not stuck. Suppress with \`--quiet\`.
666
+ - **Brief fidelity**: bios reference domain-specific terms from your
667
+ description verbatim or as close paraphrase. If you mention
668
+ \`F-skatt\`, "manual Excel invoicing", "Stripe payouts", or similar
669
+ tools/jargon, expect those terms (or paraphrases) to appear in
670
+ each generated bio's daily-routine framing — not sanded down to
671
+ generic prose.
672
+ - **DOB diversity**: month-and-day are derived from a deterministic
673
+ per-profile hash so birthdays spread across the year (no more
674
+ every-profile-on-\`06-15\`). Year follows the requested age.
675
+ Re-generating the same name/country/occupation/age yields the
676
+ same DOB.
677
+
520
678
  ## Related
521
679
 
522
680
  - \`concepts/source\` — the inputs to \`profile generate\`.
@@ -577,6 +735,24 @@ flags. Two ways to select:
577
735
  The two modes are **mutually exclusive** — pass either \`--profile\` or
578
736
  the filter set, not both.
579
737
 
738
+ ## Empty-pool suggestions
739
+
740
+ When a filter combination matches zero profiles, the error message
741
+ includes the top three populated countries that satisfy your *other*
742
+ filters — so you can pivot to a country with actual coverage without a
743
+ second \`profile list\` round-trip:
744
+
745
+ \`\`\`
746
+ $ ish study run --country XX --min-age 35 --sample 5
747
+ Error: No simulatable AI tester profiles in workspace w-b32 match:
748
+ --country XX --min-age 35.
749
+ Populated countries with these other filters: SE (12), DE (8), NL (3).
750
+ Broaden your filters or run \`ish profile list\` to inspect the pool.
751
+ \`\`\`
752
+
753
+ The suggestion is best-effort — it never replaces the original error,
754
+ just augments it.
755
+
580
756
  ## Defaults
581
757
 
582
758
  - \`ish study run\` with no audience flags → reuses the iteration's
@@ -709,6 +885,13 @@ ish study cancel <tester_id> # cancel a running simulation
709
885
  \`<tester_id>\` accepts a tester alias (\`t-…\`) or a full UUID. The
710
886
  study-level \`poll\`/\`wait\` forms also exist (\`--study <id>\` /
711
887
  \`--iteration <id>\`) for whole-batch progress.
888
+
889
+ ## Related
890
+
891
+ - \`reference/json-mode\` — output modes (display vs capture vs chain).
892
+ Use \`--get tester_aliases\` to capture the run's testers without
893
+ piping through \`jq\`. \`--human\` forces table output even through
894
+ \`tee\`/redirection.
712
895
  `;
713
896
  const REFERENCE_ALIASES = `# reference: aliases
714
897
 
@@ -740,15 +923,84 @@ ish profile generate --source tps-3a4 --count 4
740
923
  The full UUID is also always accepted. Add \`--verbose\` to JSON output
741
924
  to see UUIDs alongside aliases.
742
925
  `;
743
- const REFERENCE_JSON_MODE = `# reference: JSON output for agents
926
+ const REFERENCE_JSON_MODE = `# reference: output modes for agents
927
+
928
+ \`ish\` distinguishes **three output modes** so agents don't have to
929
+ post-process CLI output with \`jq\` or \`python\` for routine tasks:
930
+
931
+ 1. **Display mode (human)** — readable tables and key/value blocks.
932
+ Default on a TTY. Force it anywhere with \`--human\` (e.g. \`ish
933
+ workspace list --human | tee /tmp/x.txt\` keeps the table layout
934
+ even though stdout is redirected).
935
+ 2. **Capture mode (single value)** — \`--get <field>\` extracts the
936
+ value at a dotted path and prints it bare (no JSON quotes, no
937
+ indentation). Use this to feed one CLI's output into another:
938
+ \`ASK=$(ish ask create … --get alias)\` instead of
939
+ \`ASK=$(ish ask create … --json | jq -r .alias)\`.
940
+ 3. **Chain mode (full JSON)** — \`--json\` (or auto-enabled when stdout
941
+ is piped). Returns structured payloads for downstream parsing.
942
+ Reach for this only when you actually need multiple fields or a
943
+ nested shape; for one value, \`--get\` is shorter.
944
+
945
+ ## Picking the right mode
946
+
947
+ | You want to… | Mode |
948
+ |-------------------------------------------|--------------------------------------------------|
949
+ | Show the user a list of workspaces | bare command (TTY) or \`--human\` if redirecting |
950
+ | Capture an alias for a follow-up command | \`--get alias\` |
951
+ | Inspect a specific nested field | \`--get tester_profile.name\` |
952
+ | Compare 2+ fields, or pipe into jq | \`--json\` (or auto-on when piped) |
953
+ | Force human output through \`tee\` | \`--human\` |
954
+ | Force JSON on a TTY | \`--json\` |
955
+
956
+ \`--get\` and \`--human\` are mutually exclusive — capture and display are
957
+ different intents; pick one. \`--get\` implies \`--json\` internally so the
958
+ renderer always has structured data to extract from; you don't need to
959
+ add \`--json\` yourself.
960
+
961
+ ### Worked example: display vs. capture
962
+
963
+ \`\`\`bash
964
+ # Display: bare command on a TTY → human table.
965
+ ish workspace list
966
+
967
+ # Capture: feed one alias into the next command, no jq required.
968
+ ASK=$(ish ask create --new --name demo \\
969
+ --prompt "Which?" --variant text:A --variant text:B \\
970
+ --sample 30 --get alias)
971
+ ish ask wait "$ASK" --timeout 600
972
+
973
+ # Capture across an entire list: one value per line.
974
+ ish workspace list --get alias
975
+ # w-6ec
976
+ # w-d02
977
+ # …
744
978
 
745
- Every command that produces output supports machine-readable JSON. JSON
746
- mode is **auto-enabled when stdout is piped**, so an agent rarely needs
747
- \`--json\` explicitly.
979
+ # Display preserved through tee:
980
+ ish ask results "$ASK" --human | tee /tmp/transcript.txt
981
+ \`\`\`
748
982
 
749
983
  ## Flags
750
984
 
751
- - \`--json\` — force JSON output even on a TTY.
985
+ - \`--human\` — force human-readable output regardless of TTY
986
+ state (overrides the auto-flip-to-JSON when
987
+ stdout is piped). Mutually exclusive with
988
+ \`--get\`.
989
+ - \`--get <field>\` — extract a single field from the JSON response
990
+ and print only its bare value. Supports dotted
991
+ paths (\`tester_profile.name\`). On a paginated
992
+ \`{items: [...]}\` response, the path
993
+ auto-descends into \`items\` so \`--get alias\`
994
+ on a list yields one value per line. Implies
995
+ \`--json\` internally; mutually exclusive with
996
+ \`--human\`. Strings/numbers/bools are printed
997
+ unquoted; \`null\` prints as an empty line;
998
+ arrays print one element per line; objects
999
+ print as compact one-line JSON. Missing field
1000
+ → exit 2 with a usage error.
1001
+ - \`--json\` — force JSON output even on a TTY. Auto-enabled
1002
+ when stdout is piped (unless \`--human\` is
1003
+ set).
752
1004
  - \`--fields a,b,c\` — keep only these fields in JSON output (e.g.
753
1005
  \`alias,name,status\`). Filters per item only;
754
1006
  list wrappers (\`{items, total, returned,
@@ -757,7 +1009,9 @@ mode is **auto-enabled when stdout is piped**, so an agent rarely needs
757
1009
  write paths) the full server payload instead
758
1010
  of the compact response.
759
1011
  - \`-q, --quiet\` — suppress progress messages on stderr (errors
760
- still go to stderr).
1012
+ still go to stderr). \`--get\` implies
1013
+ \`--quiet\` so the bare value is the only
1014
+ thing on stdout.
761
1015
 
762
1016
  ## Stable shape rules
763
1017
 
@@ -854,9 +1108,12 @@ The CLI guarantees these contracts so agents can chain safely:
854
1108
  in the \`testers[]\` array, and a "Failed testers" subsection in
855
1109
  human output. Empty when the tester succeeded.
856
1110
  - **\`profile list\` emits a stderr pagination hint** when
857
- \`has_more=true\` and stdout is human (TTY, not piped, not \`--quiet\`).
858
- Format: "showing N–M of TOTAL; pass --offset M --limit N for more."
859
- JSON consumers read \`has_more\` directly off the envelope.
1111
+ \`has_more=true\` and \`--quiet\` is not set. The hint goes to **stderr
1112
+ in every mode** including \`--json\` and piped stdout it never
1113
+ pollutes machine-readable stdout but is visible to any agent that
1114
+ reads stderr (which they should, for warnings and progress). Format:
1115
+ "showing N–M of TOTAL; pass --offset M --limit N for more."
1116
+ JSON consumers can also read \`has_more\` directly off the envelope.
860
1117
  - **\`ask results --json\` adds an \`aggregates\` field per round.** For
861
1118
  rounds with \`wants_pick\`/\`wants_ratings\`, the CLI computes the
862
1119
  verdict locally so agents don't have to parse comment prose:
@@ -938,25 +1195,43 @@ a structured error object on **stdout** and a human message on
938
1195
  ## Examples
939
1196
 
940
1197
  \`\`\`
941
- ish workspace list --json | jq '.[].alias'
942
- ish study get s-b2c --fields alias,name,status,iterations
1198
+ # Display (table on TTY, JSON when piped):
1199
+ ish workspace list
1200
+
1201
+ # Display preserved through tee/pipe (force human):
1202
+ ish ask results a-6ec --human | tee /tmp/results.txt
1203
+
1204
+ # Capture a single alias to feed into the next command:
1205
+ WS=$(ish workspace list --get alias | head -1)
1206
+
1207
+ # Inspect a nested field:
1208
+ ish study tester t-a17 --get tester_profile.name
1209
+
1210
+ # Chain (full JSON for jq when you need multiple fields):
1211
+ ish study get s-b2c --fields alias,name,status,iterations --json
943
1212
  ish ask results a-6ec --round 1 --json
944
- ish profile generate --description "..." --count 3 --json | jq '.[].alias'
945
1213
  \`\`\`
946
1214
 
947
1215
  ## Composing commands
948
1216
 
949
- JSON mode + alias resolution makes pipelines safe:
1217
+ \`--get\` removes most of the \`jq\` shims agents reach for. Capture in
1218
+ a script, then display the final result back to the user:
950
1219
 
951
1220
  \`\`\`
952
- ITER=$(ish iteration create --url https://example.com --json | jq -r .alias)
953
- TESTERS=$(ish study run --iteration "$ITER" --sample 5 --country SE \\
954
- --json | jq -r '.tester_aliases[]')
1221
+ # Capture bare values, no jq needed:
1222
+ ITER=$(ish iteration create --url https://example.com --get alias)
1223
+ TESTERS=$(ish study run --iteration "$ITER" --sample 5 --country SE --get tester_aliases)
955
1224
  for t in $TESTERS; do
956
1225
  ish study wait "$t" --timeout 600
957
1226
  done
958
- ish study results --json | jq .
1227
+
1228
+ # Display the final results to the user, even though we're in a script:
1229
+ ish study results --human
959
1230
  \`\`\`
1231
+
1232
+ When you genuinely need multiple fields in one parse pass, \`--json\` is
1233
+ still the right tool — \`--get\` is for single-value capture, not for
1234
+ reshaping output.
960
1235
  `;
961
1236
  const GUIDE_FIRST_STUDY = `# guide: your first study, end to end
962
1237
 
@@ -1098,7 +1373,9 @@ of scope: \`workspace\`, \`config\`, \`docs\`, \`init\`, \`login\`,
1098
1373
  ## Related
1099
1374
 
1100
1375
  - \`reference/aliases\` — the prefix scheme used by every entity.
1101
- - \`reference/json-mode\` — output contracts for piping \`ish status\`.
1376
+ - \`reference/json-mode\` — output modes (display vs capture vs chain),
1377
+ including \`--get workspace.alias\` to capture the active workspace
1378
+ without piping \`ish status --json\` through \`jq\`.
1102
1379
  `;
1103
1380
  const REFERENCE_BILLING_LIMITS = `# reference: billing tier limits
1104
1381
 
@@ -1201,7 +1478,7 @@ const PAGES = [
1201
1478
  {
1202
1479
  slug: "concepts/iteration",
1203
1480
  title: "concept: iteration",
1204
- description: "One configured run of a study (URL or media).",
1481
+ description: "One configured run of a study (URL, media, or chat). Covers segments, segment labels, and HTML content.",
1205
1482
  body: CONCEPT_ITERATION,
1206
1483
  },
1207
1484
  {
@@ -1272,8 +1549,8 @@ const PAGES = [
1272
1549
  },
1273
1550
  {
1274
1551
  slug: "reference/json-mode",
1275
- title: "reference: JSON output for agents",
1276
- description: "JSON, --fields, --verbose, exit codes, pipe behaviour.",
1552
+ title: "reference: output modes for agents (display, capture, chain)",
1553
+ description: "Display vs capture vs chain: --human, --get, --json, --fields, exit codes, pipe behavior.",
1277
1554
  body: REFERENCE_JSON_MODE,
1278
1555
  },
1279
1556
  {
@@ -9,6 +9,12 @@
9
9
  /** Set by withClient() based on global flags. */
10
10
  export declare function setVerbose(v: boolean): void;
11
11
  export declare function setFields(fields?: string[]): void;
12
+ /**
13
+ * Pattern Ω capture mode: when set, jsonOutput() returns the bare value at
14
+ * the dotted path instead of the full JSON. Cleared between command runs by
15
+ * each invocation of `applyGlobals()`.
16
+ */
17
+ export declare function setGetField(field?: string): void;
12
18
  /** Per-call output options for stable JSON contracts. */
13
19
  export interface OutputOptions {
14
20
  /**