faces-cli 1.8.1 → 1.8.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.
@@ -1372,7 +1372,7 @@
1372
1372
  "type": "boolean"
1373
1373
  },
1374
1374
  "medium": {
1375
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1375
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1376
1376
  "name": "medium",
1377
1377
  "hasDynamicHelp": false,
1378
1378
  "multiple": false,
@@ -1474,7 +1474,7 @@
1474
1474
  "type": "option"
1475
1475
  },
1476
1476
  "medium": {
1477
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1477
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1478
1478
  "name": "medium",
1479
1479
  "hasDynamicHelp": false,
1480
1480
  "multiple": false,
@@ -1568,7 +1568,7 @@
1568
1568
  "type": "boolean"
1569
1569
  },
1570
1570
  "medium": {
1571
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1571
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1572
1572
  "name": "medium",
1573
1573
  "hasDynamicHelp": false,
1574
1574
  "multiple": false,
@@ -1703,7 +1703,7 @@
1703
1703
  "type": "boolean"
1704
1704
  },
1705
1705
  "medium": {
1706
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1706
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
1707
1707
  "name": "medium",
1708
1708
  "hasDynamicHelp": false,
1709
1709
  "multiple": false,
@@ -1750,10 +1750,10 @@
1750
1750
  "thread.js"
1751
1751
  ]
1752
1752
  },
1753
- "config:clear": {
1753
+ "compile:all": {
1754
1754
  "aliases": [],
1755
1755
  "args": {},
1756
- "description": "Delete all saved credentials and config",
1756
+ "description": "Compile all uncompiled documents and threads across all faces",
1757
1757
  "flags": {
1758
1758
  "json": {
1759
1759
  "description": "Format output as json.",
@@ -1786,16 +1786,18 @@
1786
1786
  "multiple": false,
1787
1787
  "type": "option"
1788
1788
  },
1789
- "yes": {
1790
- "description": "Skip confirmation",
1791
- "name": "yes",
1792
- "allowNo": false,
1793
- "type": "boolean"
1789
+ "timeout": {
1790
+ "description": "Per-item compile timeout in seconds (default: 600)",
1791
+ "name": "timeout",
1792
+ "default": 600,
1793
+ "hasDynamicHelp": false,
1794
+ "multiple": false,
1795
+ "type": "option"
1794
1796
  }
1795
1797
  },
1796
1798
  "hasDynamicHelp": false,
1797
1799
  "hiddenAliases": [],
1798
- "id": "config:clear",
1800
+ "id": "compile:all",
1799
1801
  "pluginAlias": "faces-cli",
1800
1802
  "pluginName": "faces-cli",
1801
1803
  "pluginType": "core",
@@ -1805,25 +1807,20 @@
1805
1807
  "relativePath": [
1806
1808
  "dist",
1807
1809
  "commands",
1808
- "config",
1809
- "clear.js"
1810
+ "compile",
1811
+ "all.js"
1810
1812
  ]
1811
1813
  },
1812
- "config:set": {
1814
+ "compile:import": {
1813
1815
  "aliases": [],
1814
1816
  "args": {
1815
- "key": {
1816
- "description": "Config key",
1817
- "name": "key",
1818
- "required": true
1819
- },
1820
- "value": {
1821
- "description": "Config value",
1822
- "name": "value",
1817
+ "face_id": {
1818
+ "description": "Face alias",
1819
+ "name": "face_id",
1823
1820
  "required": true
1824
1821
  }
1825
1822
  },
1826
- "description": "Set a config value (e.g. base_url, api_key, token)",
1823
+ "description": "Import a YouTube video into a face via server-side download and transcription",
1827
1824
  "flags": {
1828
1825
  "json": {
1829
1826
  "description": "Format output as json.",
@@ -1855,64 +1852,56 @@
1855
1852
  "hasDynamicHelp": false,
1856
1853
  "multiple": false,
1857
1854
  "type": "option"
1858
- }
1859
- },
1860
- "hasDynamicHelp": false,
1861
- "hiddenAliases": [],
1862
- "id": "config:set",
1863
- "pluginAlias": "faces-cli",
1864
- "pluginName": "faces-cli",
1865
- "pluginType": "core",
1866
- "strict": true,
1867
- "enableJsonFlag": true,
1868
- "isESM": true,
1869
- "relativePath": [
1870
- "dist",
1871
- "commands",
1872
- "config",
1873
- "set.js"
1874
- ]
1875
- },
1876
- "config:show": {
1877
- "aliases": [],
1878
- "args": {},
1879
- "description": "Print current config (credentials are masked)",
1880
- "flags": {
1881
- "json": {
1882
- "description": "Format output as json.",
1883
- "helpGroup": "GLOBAL",
1884
- "name": "json",
1885
- "allowNo": false,
1886
- "type": "boolean"
1887
1855
  },
1888
- "base-url": {
1889
- "description": "API base URL",
1890
- "env": "FACES_BASE_URL",
1891
- "name": "base-url",
1856
+ "url": {
1857
+ "description": "YouTube URL (youtube.com/watch?v=... or youtu.be/...)",
1858
+ "name": "url",
1859
+ "required": true,
1892
1860
  "hasDynamicHelp": false,
1893
1861
  "multiple": false,
1894
1862
  "type": "option"
1895
1863
  },
1896
- "token": {
1897
- "description": "JWT bearer token",
1898
- "env": "FACES_TOKEN",
1899
- "name": "token",
1864
+ "type": {
1865
+ "description": "\"document\" for solo talks, lectures, monologues; \"thread\" for interviews or multi-speaker conversations",
1866
+ "name": "type",
1867
+ "default": "document",
1900
1868
  "hasDynamicHelp": false,
1901
1869
  "multiple": false,
1870
+ "options": [
1871
+ "document",
1872
+ "thread"
1873
+ ],
1902
1874
  "type": "option"
1903
1875
  },
1904
- "api-key": {
1905
- "description": "API key",
1906
- "env": "FACES_API_KEY",
1907
- "name": "api-key",
1876
+ "perspective": {
1877
+ "description": "\"first-person\" if the face is the speaker; \"third-person\" if the video is about the face",
1878
+ "name": "perspective",
1879
+ "default": "third-person",
1880
+ "hasDynamicHelp": false,
1881
+ "multiple": false,
1882
+ "options": [
1883
+ "first-person",
1884
+ "third-person"
1885
+ ],
1886
+ "type": "option"
1887
+ },
1888
+ "face-speaker": {
1889
+ "description": "For --type thread: AssemblyAI speaker label (e.g. \"A\") that corresponds to the face. Defaults to first detected speaker.",
1890
+ "name": "face-speaker",
1908
1891
  "hasDynamicHelp": false,
1909
1892
  "multiple": false,
1910
1893
  "type": "option"
1894
+ },
1895
+ "no-wait": {
1896
+ "description": "Return immediately after import starts (do not poll for transcription). Prints the ID for manual polling.",
1897
+ "name": "no-wait",
1898
+ "allowNo": false,
1899
+ "type": "boolean"
1911
1900
  }
1912
1901
  },
1913
1902
  "hasDynamicHelp": false,
1914
1903
  "hiddenAliases": [],
1915
- "id": "config:show",
1904
+ "id": "compile:import",
1916
1905
  "pluginAlias": "faces-cli",
1917
1906
  "pluginName": "faces-cli",
1918
1907
  "pluginType": "core",
@@ -1922,14 +1911,14 @@
1922
1911
  "relativePath": [
1923
1912
  "dist",
1924
1913
  "commands",
1925
- "config",
1926
- "show.js"
1914
+ "compile",
1915
+ "import.js"
1927
1916
  ]
1928
1917
  },
1929
- "face:attributes": {
1918
+ "compile:stats": {
1930
1919
  "aliases": [],
1931
1920
  "args": {},
1932
- "description": "List all supported attribute keys",
1921
+ "description": "Show compilation stats per face",
1933
1922
  "flags": {
1934
1923
  "json": {
1935
1924
  "description": "Format output as json.",
@@ -1965,7 +1954,7 @@
1965
1954
  },
1966
1955
  "hasDynamicHelp": false,
1967
1956
  "hiddenAliases": [],
1968
- "id": "face:attributes",
1957
+ "id": "compile:stats",
1969
1958
  "pluginAlias": "faces-cli",
1970
1959
  "pluginName": "faces-cli",
1971
1960
  "pluginType": "core",
@@ -1975,14 +1964,20 @@
1975
1964
  "relativePath": [
1976
1965
  "dist",
1977
1966
  "commands",
1978
- "face",
1979
- "attributes.js"
1967
+ "compile",
1968
+ "stats.js"
1980
1969
  ]
1981
1970
  },
1982
- "face:create": {
1971
+ "compile:upload": {
1983
1972
  "aliases": [],
1984
- "args": {},
1985
- "description": "Create a new face",
1973
+ "args": {
1974
+ "alias": {
1975
+ "description": "Face alias",
1976
+ "name": "alias",
1977
+ "required": true
1978
+ }
1979
+ },
1980
+ "description": "Upload a file (text/PDF/Word .docx/audio/video) to compile into a face",
1986
1981
  "flags": {
1987
1982
  "json": {
1988
1983
  "description": "Format output as json.",
@@ -2015,85 +2010,62 @@
2015
2010
  "multiple": false,
2016
2011
  "type": "option"
2017
2012
  },
2018
- "name": {
2019
- "description": "Display name",
2020
- "name": "name",
2021
- "required": true,
2022
- "hasDynamicHelp": false,
2023
- "multiple": false,
2024
- "type": "option"
2025
- },
2026
- "alias": {
2027
- "description": "Unique alias slug",
2028
- "name": "alias",
2013
+ "file": {
2014
+ "description": "File to upload",
2015
+ "name": "file",
2029
2016
  "required": true,
2030
2017
  "hasDynamicHelp": false,
2031
2018
  "multiple": false,
2032
2019
  "type": "option"
2033
2020
  },
2034
- "description": {
2035
- "description": "Plain-text description / bio (max 1500 chars)",
2036
- "name": "description",
2021
+ "kind": {
2022
+ "description": "Upload kind: document or thread",
2023
+ "name": "kind",
2024
+ "default": "document",
2037
2025
  "hasDynamicHelp": false,
2038
2026
  "multiple": false,
2027
+ "options": [
2028
+ "document",
2029
+ "thread"
2030
+ ],
2039
2031
  "type": "option"
2040
2032
  },
2041
- "tag": {
2042
- "description": "Tag label (repeatable, lowercase)",
2043
- "name": "tag",
2044
- "hasDynamicHelp": false,
2045
- "multiple": true,
2046
- "type": "option"
2047
- },
2048
- "default-model": {
2049
- "description": "Default LLM for chat (e.g. gpt-4o-mini, claude-sonnet-4-6)",
2050
- "name": "default-model",
2033
+ "perspective": {
2034
+ "description": "Perspective (document only)",
2035
+ "name": "perspective",
2036
+ "default": "third-person",
2051
2037
  "hasDynamicHelp": false,
2052
2038
  "multiple": false,
2039
+ "options": [
2040
+ "first-person",
2041
+ "third-person"
2042
+ ],
2053
2043
  "type": "option"
2054
2044
  },
2055
- "formula": {
2056
- "description": "Boolean formula over owned concrete face aliases (e.g. \"a | b\", \"(a | b) - c\"). Creates a composite face.",
2057
- "name": "formula",
2045
+ "medium": {
2046
+ "description": "What sort of writing this is e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not. Only valid with --kind document.",
2047
+ "name": "medium",
2058
2048
  "hasDynamicHelp": false,
2059
2049
  "multiple": false,
2060
2050
  "type": "option"
2061
2051
  },
2062
- "attr": {
2063
- "description": "Attribute KEY=VALUE (repeatable)",
2064
- "name": "attr",
2065
- "hasDynamicHelp": false,
2066
- "multiple": true,
2067
- "type": "option"
2068
- },
2069
- "tool": {
2070
- "description": "Tool name to enable (repeatable)",
2071
- "name": "tool",
2072
- "hasDynamicHelp": false,
2073
- "multiple": true,
2074
- "type": "option"
2075
- },
2076
- "profile-addendum": {
2077
- "description": "Per-face system prompt, injected after the persona profile and before any per-request system prompt (max 100,000 chars).",
2078
- "name": "profile-addendum",
2052
+ "face-speaker": {
2053
+ "description": "Speaker name to map to the face (thread only). If omitted, auto-detected from face name.",
2054
+ "name": "face-speaker",
2079
2055
  "hasDynamicHelp": false,
2080
2056
  "multiple": false,
2081
2057
  "type": "option"
2082
2058
  },
2083
- "profile-addendum-file": {
2084
- "description": "Read the per-face system prompt from a file (alternative to --profile-addendum).",
2085
- "exclusive": [
2086
- "profile-addendum"
2087
- ],
2088
- "name": "profile-addendum-file",
2089
- "hasDynamicHelp": false,
2090
- "multiple": false,
2091
- "type": "option"
2059
+ "no-wait": {
2060
+ "description": "Return immediately after upload (do not poll for transcription). Prints the ID for manual polling.",
2061
+ "name": "no-wait",
2062
+ "allowNo": false,
2063
+ "type": "boolean"
2092
2064
  }
2093
2065
  },
2094
2066
  "hasDynamicHelp": false,
2095
2067
  "hiddenAliases": [],
2096
- "id": "face:create",
2068
+ "id": "compile:upload",
2097
2069
  "pluginAlias": "faces-cli",
2098
2070
  "pluginName": "faces-cli",
2099
2071
  "pluginType": "core",
@@ -2103,20 +2075,14 @@
2103
2075
  "relativePath": [
2104
2076
  "dist",
2105
2077
  "commands",
2106
- "face",
2107
- "create.js"
2078
+ "compile",
2079
+ "upload.js"
2108
2080
  ]
2109
2081
  },
2110
- "face:delete": {
2082
+ "config:clear": {
2111
2083
  "aliases": [],
2112
- "args": {
2113
- "face_id": {
2114
- "description": "Face alias",
2115
- "name": "face_id",
2116
- "required": true
2117
- }
2118
- },
2119
- "description": "Delete a face permanently",
2084
+ "args": {},
2085
+ "description": "Delete all saved credentials and config",
2120
2086
  "flags": {
2121
2087
  "json": {
2122
2088
  "description": "Format output as json.",
@@ -2158,7 +2124,7 @@
2158
2124
  },
2159
2125
  "hasDynamicHelp": false,
2160
2126
  "hiddenAliases": [],
2161
- "id": "face:delete",
2127
+ "id": "config:clear",
2162
2128
  "pluginAlias": "faces-cli",
2163
2129
  "pluginName": "faces-cli",
2164
2130
  "pluginType": "core",
@@ -2168,21 +2134,32 @@
2168
2134
  "relativePath": [
2169
2135
  "dist",
2170
2136
  "commands",
2171
- "face",
2172
- "delete.js"
2137
+ "config",
2138
+ "clear.js"
2173
2139
  ]
2174
2140
  },
2175
- "face:diff": {
2141
+ "config:set": {
2176
2142
  "aliases": [],
2177
- "args": {},
2178
- "description": "Compare owned faces pairwise across all centroid components",
2179
- "flags": {
2180
- "json": {
2181
- "description": "Format output as json.",
2182
- "helpGroup": "GLOBAL",
2183
- "name": "json",
2184
- "allowNo": false,
2185
- "type": "boolean"
2143
+ "args": {
2144
+ "key": {
2145
+ "description": "Config key",
2146
+ "name": "key",
2147
+ "required": true
2148
+ },
2149
+ "value": {
2150
+ "description": "Config value",
2151
+ "name": "value",
2152
+ "required": true
2153
+ }
2154
+ },
2155
+ "description": "Set a config value (e.g. base_url, api_key, token)",
2156
+ "flags": {
2157
+ "json": {
2158
+ "description": "Format output as json.",
2159
+ "helpGroup": "GLOBAL",
2160
+ "name": "json",
2161
+ "allowNo": false,
2162
+ "type": "boolean"
2186
2163
  },
2187
2164
  "base-url": {
2188
2165
  "description": "API base URL",
@@ -2207,19 +2184,11 @@
2207
2184
  "hasDynamicHelp": false,
2208
2185
  "multiple": false,
2209
2186
  "type": "option"
2210
- },
2211
- "face": {
2212
- "description": "Face alias to include (repeatable, min 2)",
2213
- "name": "face",
2214
- "required": true,
2215
- "hasDynamicHelp": false,
2216
- "multiple": true,
2217
- "type": "option"
2218
2187
  }
2219
2188
  },
2220
2189
  "hasDynamicHelp": false,
2221
2190
  "hiddenAliases": [],
2222
- "id": "face:diff",
2191
+ "id": "config:set",
2223
2192
  "pluginAlias": "faces-cli",
2224
2193
  "pluginName": "faces-cli",
2225
2194
  "pluginType": "core",
@@ -2229,20 +2198,14 @@
2229
2198
  "relativePath": [
2230
2199
  "dist",
2231
2200
  "commands",
2232
- "face",
2233
- "diff.js"
2201
+ "config",
2202
+ "set.js"
2234
2203
  ]
2235
2204
  },
2236
- "face:edit": {
2205
+ "config:show": {
2237
2206
  "aliases": [],
2238
- "args": {
2239
- "face_id": {
2240
- "description": "Face alias",
2241
- "name": "face_id",
2242
- "required": true
2243
- }
2244
- },
2245
- "description": "Edit a face's metadata",
2207
+ "args": {},
2208
+ "description": "Print current config (credentials are masked)",
2246
2209
  "flags": {
2247
2210
  "json": {
2248
2211
  "description": "Format output as json.",
@@ -2274,87 +2237,159 @@
2274
2237
  "hasDynamicHelp": false,
2275
2238
  "multiple": false,
2276
2239
  "type": "option"
2240
+ }
2241
+ },
2242
+ "hasDynamicHelp": false,
2243
+ "hiddenAliases": [],
2244
+ "id": "config:show",
2245
+ "pluginAlias": "faces-cli",
2246
+ "pluginName": "faces-cli",
2247
+ "pluginType": "core",
2248
+ "strict": true,
2249
+ "enableJsonFlag": true,
2250
+ "isESM": true,
2251
+ "relativePath": [
2252
+ "dist",
2253
+ "commands",
2254
+ "config",
2255
+ "show.js"
2256
+ ]
2257
+ },
2258
+ "keys:create": {
2259
+ "aliases": [],
2260
+ "args": {},
2261
+ "description": "Create a new API key (JWT required). The new key is saved to ~/.faces/config.json as api_key by default; pass --no-save to skip.",
2262
+ "flags": {
2263
+ "json": {
2264
+ "description": "Format output as json.",
2265
+ "helpGroup": "GLOBAL",
2266
+ "name": "json",
2267
+ "allowNo": false,
2268
+ "type": "boolean"
2277
2269
  },
2278
- "name": {
2279
- "description": "New display name",
2280
- "name": "name",
2270
+ "base-url": {
2271
+ "description": "API base URL",
2272
+ "env": "FACES_BASE_URL",
2273
+ "name": "base-url",
2281
2274
  "hasDynamicHelp": false,
2282
2275
  "multiple": false,
2283
2276
  "type": "option"
2284
2277
  },
2285
- "description": {
2286
- "description": "Plain-text description / bio (max 1500 chars)",
2287
- "name": "description",
2278
+ "token": {
2279
+ "description": "JWT bearer token",
2280
+ "env": "FACES_TOKEN",
2281
+ "name": "token",
2288
2282
  "hasDynamicHelp": false,
2289
2283
  "multiple": false,
2290
2284
  "type": "option"
2291
2285
  },
2292
- "tag": {
2293
- "description": "Replace all tags (repeatable, lowercase)",
2294
- "name": "tag",
2286
+ "api-key": {
2287
+ "description": "API key",
2288
+ "env": "FACES_API_KEY",
2289
+ "name": "api-key",
2295
2290
  "hasDynamicHelp": false,
2296
- "multiple": true,
2291
+ "multiple": false,
2297
2292
  "type": "option"
2298
2293
  },
2299
- "default-model": {
2300
- "description": "Default LLM for chat (e.g. gpt-4o-mini, claude-sonnet-4-6)",
2301
- "name": "default-model",
2294
+ "name": {
2295
+ "description": "Key name/label",
2296
+ "name": "name",
2297
+ "required": true,
2302
2298
  "hasDynamicHelp": false,
2303
2299
  "multiple": false,
2304
2300
  "type": "option"
2305
2301
  },
2306
- "formula": {
2307
- "description": "New boolean formula (synthetic faces only)",
2308
- "name": "formula",
2302
+ "expires-days": {
2303
+ "description": "Expiry in days (omit for no expiry)",
2304
+ "name": "expires-days",
2309
2305
  "hasDynamicHelp": false,
2310
2306
  "multiple": false,
2311
2307
  "type": "option"
2312
2308
  },
2313
- "attr": {
2314
- "description": "Update attribute KEY=VALUE (repeatable)",
2315
- "name": "attr",
2309
+ "budget": {
2310
+ "description": "Spend budget in USD",
2311
+ "name": "budget",
2312
+ "hasDynamicHelp": false,
2313
+ "multiple": false,
2314
+ "type": "option"
2315
+ },
2316
+ "face": {
2317
+ "description": "Allowed face alias (repeatable)",
2318
+ "name": "face",
2316
2319
  "hasDynamicHelp": false,
2317
2320
  "multiple": true,
2318
2321
  "type": "option"
2319
2322
  },
2320
- "tool": {
2321
- "description": "Tool names to set (replaces list, repeatable)",
2322
- "name": "tool",
2323
+ "model": {
2324
+ "description": "Allowed model name (repeatable)",
2325
+ "name": "model",
2323
2326
  "hasDynamicHelp": false,
2324
2327
  "multiple": true,
2325
2328
  "type": "option"
2326
2329
  },
2327
- "profile-addendum": {
2328
- "description": "Replace the per-face system prompt (max 100,000 chars).",
2329
- "name": "profile-addendum",
2330
+ "save": {
2331
+ "description": "Save the new key to ~/.faces/config.json as api_key (default: true; use --no-save to skip)",
2332
+ "name": "save",
2333
+ "allowNo": true,
2334
+ "type": "boolean"
2335
+ }
2336
+ },
2337
+ "hasDynamicHelp": false,
2338
+ "hiddenAliases": [],
2339
+ "id": "keys:create",
2340
+ "pluginAlias": "faces-cli",
2341
+ "pluginName": "faces-cli",
2342
+ "pluginType": "core",
2343
+ "strict": true,
2344
+ "enableJsonFlag": true,
2345
+ "isESM": true,
2346
+ "relativePath": [
2347
+ "dist",
2348
+ "commands",
2349
+ "keys",
2350
+ "create.js"
2351
+ ]
2352
+ },
2353
+ "keys:list": {
2354
+ "aliases": [],
2355
+ "args": {},
2356
+ "description": "List all API keys (JWT required)",
2357
+ "flags": {
2358
+ "json": {
2359
+ "description": "Format output as json.",
2360
+ "helpGroup": "GLOBAL",
2361
+ "name": "json",
2362
+ "allowNo": false,
2363
+ "type": "boolean"
2364
+ },
2365
+ "base-url": {
2366
+ "description": "API base URL",
2367
+ "env": "FACES_BASE_URL",
2368
+ "name": "base-url",
2330
2369
  "hasDynamicHelp": false,
2331
2370
  "multiple": false,
2332
2371
  "type": "option"
2333
2372
  },
2334
- "profile-addendum-file": {
2335
- "description": "Replace the per-face system prompt from a file.",
2336
- "exclusive": [
2337
- "profile-addendum"
2338
- ],
2339
- "name": "profile-addendum-file",
2373
+ "token": {
2374
+ "description": "JWT bearer token",
2375
+ "env": "FACES_TOKEN",
2376
+ "name": "token",
2340
2377
  "hasDynamicHelp": false,
2341
2378
  "multiple": false,
2342
2379
  "type": "option"
2343
2380
  },
2344
- "clear-profile-addendum": {
2345
- "description": "Remove the per-face system prompt.",
2346
- "exclusive": [
2347
- "profile-addendum",
2348
- "profile-addendum-file"
2349
- ],
2350
- "name": "clear-profile-addendum",
2351
- "allowNo": false,
2352
- "type": "boolean"
2381
+ "api-key": {
2382
+ "description": "API key",
2383
+ "env": "FACES_API_KEY",
2384
+ "name": "api-key",
2385
+ "hasDynamicHelp": false,
2386
+ "multiple": false,
2387
+ "type": "option"
2353
2388
  }
2354
2389
  },
2355
2390
  "hasDynamicHelp": false,
2356
2391
  "hiddenAliases": [],
2357
- "id": "face:edit",
2392
+ "id": "keys:list",
2358
2393
  "pluginAlias": "faces-cli",
2359
2394
  "pluginName": "faces-cli",
2360
2395
  "pluginType": "core",
@@ -2364,20 +2399,20 @@
2364
2399
  "relativePath": [
2365
2400
  "dist",
2366
2401
  "commands",
2367
- "face",
2368
- "edit.js"
2402
+ "keys",
2403
+ "list.js"
2369
2404
  ]
2370
2405
  },
2371
- "face:get": {
2406
+ "keys:revoke": {
2372
2407
  "aliases": [],
2373
2408
  "args": {
2374
- "face_id": {
2375
- "description": "Face alias",
2376
- "name": "face_id",
2409
+ "key_id": {
2410
+ "description": "Key ID",
2411
+ "name": "key_id",
2377
2412
  "required": true
2378
2413
  }
2379
2414
  },
2380
- "description": "Get details for a face by alias",
2415
+ "description": "Revoke an API key (JWT required)",
2381
2416
  "flags": {
2382
2417
  "json": {
2383
2418
  "description": "Format output as json.",
@@ -2410,23 +2445,16 @@
2410
2445
  "multiple": false,
2411
2446
  "type": "option"
2412
2447
  },
2413
- "include": {
2414
- "description": "Include extra fields: tags, teams (comma-separated)",
2415
- "name": "include",
2416
- "hasDynamicHelp": false,
2417
- "multiple": false,
2418
- "type": "option"
2419
- },
2420
- "full": {
2421
- "description": "Print the full profile_addendum instead of a truncated preview",
2422
- "name": "full",
2448
+ "yes": {
2449
+ "description": "Skip confirmation",
2450
+ "name": "yes",
2423
2451
  "allowNo": false,
2424
2452
  "type": "boolean"
2425
2453
  }
2426
2454
  },
2427
2455
  "hasDynamicHelp": false,
2428
2456
  "hiddenAliases": [],
2429
- "id": "face:get",
2457
+ "id": "keys:revoke",
2430
2458
  "pluginAlias": "faces-cli",
2431
2459
  "pluginName": "faces-cli",
2432
2460
  "pluginType": "core",
@@ -2436,14 +2464,20 @@
2436
2464
  "relativePath": [
2437
2465
  "dist",
2438
2466
  "commands",
2439
- "face",
2440
- "get.js"
2467
+ "keys",
2468
+ "revoke.js"
2441
2469
  ]
2442
2470
  },
2443
- "face:list": {
2471
+ "keys:update": {
2444
2472
  "aliases": [],
2445
- "args": {},
2446
- "description": "List faces. By default lists owned faces; use --public to include published faces from other accounts.",
2473
+ "args": {
2474
+ "key_id": {
2475
+ "description": "Key ID",
2476
+ "name": "key_id",
2477
+ "required": true
2478
+ }
2479
+ },
2480
+ "description": "Update API key metadata (JWT required)",
2447
2481
  "flags": {
2448
2482
  "json": {
2449
2483
  "description": "Format output as json.",
@@ -2476,63 +2510,30 @@
2476
2510
  "multiple": false,
2477
2511
  "type": "option"
2478
2512
  },
2479
- "tag": {
2480
- "description": "Filter by tag (repeatable, AND logic)",
2481
- "name": "tag",
2482
- "hasDynamicHelp": false,
2483
- "multiple": true,
2484
- "type": "option"
2485
- },
2486
- "team": {
2487
- "description": "Filter by team ID (repeatable, OR logic)",
2488
- "name": "team",
2513
+ "name": {
2514
+ "description": "New key name",
2515
+ "name": "name",
2489
2516
  "hasDynamicHelp": false,
2490
- "multiple": true,
2517
+ "multiple": false,
2491
2518
  "type": "option"
2492
2519
  },
2493
- "include": {
2494
- "description": "Include extra fields: tags, teams (comma-separated)",
2495
- "name": "include",
2520
+ "budget": {
2521
+ "description": "New spend budget in USD",
2522
+ "name": "budget",
2496
2523
  "hasDynamicHelp": false,
2497
2524
  "multiple": false,
2498
2525
  "type": "option"
2499
2526
  },
2500
- "public": {
2501
- "description": "Include published faces from other accounts (open to everybody)",
2502
- "name": "public",
2503
- "allowNo": false,
2504
- "type": "boolean"
2505
- },
2506
- "shared": {
2507
- "description": "Include faces other accounts have shared with YOU in particular",
2508
- "name": "shared",
2509
- "allowNo": false,
2510
- "type": "boolean"
2511
- },
2512
- "system": {
2513
- "description": "Show only the curated system faces (published faces owned by 'head')",
2514
- "name": "system",
2527
+ "reset-spent": {
2528
+ "description": "Reset spent amount to zero",
2529
+ "name": "reset-spent",
2515
2530
  "allowNo": false,
2516
2531
  "type": "boolean"
2517
- },
2518
- "from-users": {
2519
- "description": "Only published faces from these owners (repeatable/comma-separated)",
2520
- "name": "from-users",
2521
- "hasDynamicHelp": false,
2522
- "multiple": true,
2523
- "type": "option"
2524
- },
2525
- "not-from-users": {
2526
- "description": "Exclude published faces from these owners (repeatable/comma-separated)",
2527
- "name": "not-from-users",
2528
- "hasDynamicHelp": false,
2529
- "multiple": true,
2530
- "type": "option"
2531
2532
  }
2532
2533
  },
2533
2534
  "hasDynamicHelp": false,
2534
2535
  "hiddenAliases": [],
2535
- "id": "face:list",
2536
+ "id": "keys:update",
2536
2537
  "pluginAlias": "faces-cli",
2537
2538
  "pluginName": "faces-cli",
2538
2539
  "pluginType": "core",
@@ -2542,22 +2543,23 @@
2542
2543
  "relativePath": [
2543
2544
  "dist",
2544
2545
  "commands",
2545
- "face",
2546
- "list.js"
2546
+ "keys",
2547
+ "update.js"
2547
2548
  ]
2548
2549
  },
2549
- "face:lock": {
2550
+ "style:delete": {
2550
2551
  "aliases": [],
2551
2552
  "args": {
2552
- "face_id": {
2553
+ "alias": {
2553
2554
  "description": "Face alias",
2554
- "name": "face_id",
2555
+ "name": "alias",
2555
2556
  "required": true
2556
2557
  }
2557
2558
  },
2558
- "description": "Lock a face (read-only). A locked face still reads and chats normally, but it and everything it owns (documents, threads, voiceprint) cannot be changed until unlocked.",
2559
+ "description": "Delete a face's captured style. The material it was learned from is kept, so the style can be captured again without re-uploading. This never deletes documents or threads: remove those with compile:doc:delete or compile:thread:delete.",
2559
2560
  "examples": [
2560
- "<%= config.bin %> <%= command.id %> socrates"
2561
+ "<%= config.bin %> <%= command.id %> alice",
2562
+ "<%= config.bin %> <%= command.id %> alice --yes"
2561
2563
  ],
2562
2564
  "flags": {
2563
2565
  "json": {
@@ -2590,11 +2592,17 @@
2590
2592
  "hasDynamicHelp": false,
2591
2593
  "multiple": false,
2592
2594
  "type": "option"
2595
+ },
2596
+ "yes": {
2597
+ "description": "Skip confirmation",
2598
+ "name": "yes",
2599
+ "allowNo": false,
2600
+ "type": "boolean"
2593
2601
  }
2594
2602
  },
2595
2603
  "hasDynamicHelp": false,
2596
2604
  "hiddenAliases": [],
2597
- "id": "face:lock",
2605
+ "id": "style:delete",
2598
2606
  "pluginAlias": "faces-cli",
2599
2607
  "pluginName": "faces-cli",
2600
2608
  "pluginType": "core",
@@ -2604,20 +2612,26 @@
2604
2612
  "relativePath": [
2605
2613
  "dist",
2606
2614
  "commands",
2607
- "face",
2608
- "lock.js"
2615
+ "style",
2616
+ "delete.js"
2609
2617
  ]
2610
2618
  },
2611
- "face:neighbors": {
2619
+ "style:make": {
2612
2620
  "aliases": [],
2613
2621
  "args": {
2614
- "face_id": {
2622
+ "alias": {
2615
2623
  "description": "Face alias",
2616
- "name": "face_id",
2624
+ "name": "alias",
2617
2625
  "required": true
2618
2626
  }
2619
2627
  },
2620
- "description": "Find the most similar or dissimilar owned faces to a given face",
2628
+ "description": "Capture how a face writes, from its own material, and install it. This is style, not knowledge: compile teaches a face what it knows, style teaches it how it sounds. Name the sources to learn from with --source, or take everything ready with --all.",
2629
+ "examples": [
2630
+ "<%= config.bin %> <%= command.id %> alice --all",
2631
+ "<%= config.bin %> <%= command.id %> alice --source 1a2b3c4d --source 5e6f7a8b",
2632
+ "<%= config.bin %> <%= command.id %> alice --source 1a2b3c4d:essay",
2633
+ "<%= config.bin %> <%= command.id %> alice --all --medium essay --no-wait"
2634
+ ],
2621
2635
  "flags": {
2622
2636
  "json": {
2623
2637
  "description": "Format output as json.",
@@ -2650,38 +2664,70 @@
2650
2664
  "multiple": false,
2651
2665
  "type": "option"
2652
2666
  },
2653
- "k": {
2654
- "description": "Number of results (1–20)",
2655
- "name": "k",
2656
- "default": 5,
2667
+ "source": {
2668
+ "description": "A document or thread to learn from, by id (repeatable). Append :<medium> to declare what it is, e.g. --source 1a2b3c4d:essay, when the source does not already say.",
2669
+ "name": "source",
2670
+ "hasDynamicHelp": false,
2671
+ "multiple": true,
2672
+ "type": "option"
2673
+ },
2674
+ "all": {
2675
+ "description": "Use every source on the face that is ready. Anything skipped is listed.",
2676
+ "name": "all",
2677
+ "allowNo": false,
2678
+ "type": "boolean"
2679
+ },
2680
+ "medium": {
2681
+ "description": "Medium for selected sources that do not already declare one. It does not override a source that does. Each medium is analysed on its own, so an essay never teaches a rule about email.",
2682
+ "name": "medium",
2657
2683
  "hasDynamicHelp": false,
2658
2684
  "multiple": false,
2659
2685
  "type": "option"
2660
2686
  },
2661
- "component": {
2662
- "description": "What to rank on: `face` for overall similarity, or a component position such as 1. Which positions are comparable varies; the API names them if you pick a wrong one.",
2663
- "name": "component",
2664
- "default": "face",
2687
+ "model": {
2688
+ "description": "Analyst model (default: gpt-5.6-terra)",
2689
+ "name": "model",
2665
2690
  "hasDynamicHelp": false,
2666
2691
  "multiple": false,
2667
2692
  "type": "option"
2668
2693
  },
2669
- "direction": {
2670
- "description": "nearest (most similar) or furthest (most dissimilar)",
2671
- "name": "direction",
2672
- "default": "nearest",
2694
+ "allow-paid": {
2695
+ "description": "Permit a build that bills. Without this a build is free or it does not run. Needed for any model outside the free tier, and to allow the paid route when a free quota is exhausted.",
2696
+ "name": "allow-paid",
2697
+ "allowNo": false,
2698
+ "type": "boolean"
2699
+ },
2700
+ "compile": {
2701
+ "description": "Compile any named source that is not compiled yet, before capturing style. On by default. --no-compile captures style from what is already compiled and never bills for compilation.",
2702
+ "name": "compile",
2703
+ "allowNo": true,
2704
+ "type": "boolean"
2705
+ },
2706
+ "best-of": {
2707
+ "description": "Generate N candidates and keep the best (1-5, default 1)",
2708
+ "name": "best-of",
2709
+ "hasDynamicHelp": false,
2710
+ "multiple": false,
2711
+ "type": "option"
2712
+ },
2713
+ "no-wait": {
2714
+ "description": "Start the build and return the job id without polling.",
2715
+ "name": "no-wait",
2716
+ "allowNo": false,
2717
+ "type": "boolean"
2718
+ },
2719
+ "timeout": {
2720
+ "description": "How long to wait, in seconds (default: 3600)",
2721
+ "name": "timeout",
2722
+ "default": 3600,
2673
2723
  "hasDynamicHelp": false,
2674
2724
  "multiple": false,
2675
- "options": [
2676
- "nearest",
2677
- "furthest"
2678
- ],
2679
2725
  "type": "option"
2680
2726
  }
2681
2727
  },
2682
2728
  "hasDynamicHelp": false,
2683
2729
  "hiddenAliases": [],
2684
- "id": "face:neighbors",
2730
+ "id": "style:make",
2685
2731
  "pluginAlias": "faces-cli",
2686
2732
  "pluginName": "faces-cli",
2687
2733
  "pluginType": "core",
@@ -2691,11 +2737,11 @@
2691
2737
  "relativePath": [
2692
2738
  "dist",
2693
2739
  "commands",
2694
- "face",
2695
- "neighbors.js"
2740
+ "style",
2741
+ "make.js"
2696
2742
  ]
2697
2743
  },
2698
- "face:publish": {
2744
+ "style:revert": {
2699
2745
  "aliases": [],
2700
2746
  "args": {
2701
2747
  "alias": {
@@ -2704,9 +2750,10 @@
2704
2750
  "required": true
2705
2751
  }
2706
2752
  },
2707
- "description": "Publish a face so EVERY account can chat with it. This is a global override: while it is on, everyone can reach the face regardless of who it is shared with. You still pay only to compile it; whoever chats pays for their own inference.",
2753
+ "description": "Go back to the style a face had before the last style:make. A face holds one style per medium, so name which one with --medium when it has more than one. Two versions are kept per medium, so this goes back exactly one step. It changes how the face writes immediately, so it asks first.",
2708
2754
  "examples": [
2709
- "<%= config.bin %> <%= command.id %> alice --yes"
2755
+ "<%= config.bin %> <%= command.id %> alice --yes",
2756
+ "<%= config.bin %> <%= command.id %> alice --medium email --yes"
2710
2757
  ],
2711
2758
  "flags": {
2712
2759
  "json": {
@@ -2740,6 +2787,13 @@
2740
2787
  "multiple": false,
2741
2788
  "type": "option"
2742
2789
  },
2790
+ "medium": {
2791
+ "description": "Which style to step back, when the face has more than one. See faces style:versions <alias>.",
2792
+ "name": "medium",
2793
+ "hasDynamicHelp": false,
2794
+ "multiple": false,
2795
+ "type": "option"
2796
+ },
2743
2797
  "yes": {
2744
2798
  "description": "Skip confirmation",
2745
2799
  "name": "yes",
@@ -2749,7 +2803,7 @@
2749
2803
  },
2750
2804
  "hasDynamicHelp": false,
2751
2805
  "hiddenAliases": [],
2752
- "id": "face:publish",
2806
+ "id": "style:revert",
2753
2807
  "pluginAlias": "faces-cli",
2754
2808
  "pluginName": "faces-cli",
2755
2809
  "pluginType": "core",
@@ -2759,25 +2813,24 @@
2759
2813
  "relativePath": [
2760
2814
  "dist",
2761
2815
  "commands",
2762
- "face",
2763
- "publish.js"
2816
+ "style",
2817
+ "revert.js"
2764
2818
  ]
2765
2819
  },
2766
- "face:share": {
2820
+ "style:status": {
2767
2821
  "aliases": [],
2768
2822
  "args": {
2769
- "alias": {
2770
- "description": "Face alias",
2771
- "name": "alias",
2772
- "required": true
2823
+ "job_id": {
2824
+ "description": "Build job id",
2825
+ "name": "job_id",
2826
+ "required": false
2773
2827
  }
2774
2828
  },
2775
- "description": "Share a face so named accounts can chat with it. Sharing grants chat and nothing else: no reading its documents, no compiling, no re-sharing, and never its profile addendum. --add keeps the current list; --with replaces it.",
2829
+ "description": "Read a style build. Give a job id for one build, or --face to list a face's recent builds. Listing is how you find a job id you no longer have.",
2776
2830
  "examples": [
2777
- "<%= config.bin %> <%= command.id %> alice --list",
2778
- "<%= config.bin %> <%= command.id %> alice --add dana",
2779
- "<%= config.bin %> <%= command.id %> alice --with dana --with sam@example.com",
2780
- "<%= config.bin %> <%= command.id %> alice --none --yes"
2831
+ "<%= config.bin %> <%= command.id %> 7a8b9c0d",
2832
+ "<%= config.bin %> <%= command.id %> --face alice",
2833
+ "<%= config.bin %> <%= command.id %> 7a8b9c0d --wait"
2781
2834
  ],
2782
2835
  "flags": {
2783
2836
  "json": {
@@ -2811,54 +2864,39 @@
2811
2864
  "multiple": false,
2812
2865
  "type": "option"
2813
2866
  },
2814
- "list": {
2815
- "description": "Show who the face is shared with, and change nothing",
2816
- "name": "list",
2817
- "allowNo": false,
2818
- "type": "boolean"
2819
- },
2820
- "add": {
2821
- "description": "Add an account, keeping everyone already on the list — username or email (repeatable)",
2822
- "exclusive": [
2823
- "with",
2824
- "none"
2825
- ],
2826
- "name": "add",
2867
+ "face": {
2868
+ "description": "List recent builds for this face instead of reading one job",
2869
+ "name": "face",
2827
2870
  "hasDynamicHelp": false,
2828
- "multiple": true,
2871
+ "multiple": false,
2829
2872
  "type": "option"
2830
2873
  },
2831
- "with": {
2832
- "description": "Set the list to exactly these accounts, dropping anyone else (repeatable)",
2833
- "exclusive": [
2834
- "add",
2835
- "none"
2836
- ],
2837
- "name": "with",
2874
+ "limit": {
2875
+ "description": "How many builds to list with --face (default: 10)",
2876
+ "name": "limit",
2877
+ "default": 10,
2838
2878
  "hasDynamicHelp": false,
2839
- "multiple": true,
2879
+ "multiple": false,
2840
2880
  "type": "option"
2841
2881
  },
2842
- "none": {
2843
- "description": "Revoke everyone",
2844
- "exclusive": [
2845
- "add",
2846
- "with"
2847
- ],
2848
- "name": "none",
2882
+ "wait": {
2883
+ "description": "Block until the job finishes",
2884
+ "name": "wait",
2849
2885
  "allowNo": false,
2850
2886
  "type": "boolean"
2851
2887
  },
2852
- "yes": {
2853
- "description": "Skip the confirmation shown when someone would lose access",
2854
- "name": "yes",
2855
- "allowNo": false,
2856
- "type": "boolean"
2888
+ "timeout": {
2889
+ "description": "How long to wait with --wait, in seconds (default: 3600)",
2890
+ "name": "timeout",
2891
+ "default": 3600,
2892
+ "hasDynamicHelp": false,
2893
+ "multiple": false,
2894
+ "type": "option"
2857
2895
  }
2858
2896
  },
2859
2897
  "hasDynamicHelp": false,
2860
2898
  "hiddenAliases": [],
2861
- "id": "face:share",
2899
+ "id": "style:status",
2862
2900
  "pluginAlias": "faces-cli",
2863
2901
  "pluginName": "faces-cli",
2864
2902
  "pluginType": "core",
@@ -2868,24 +2906,29 @@
2868
2906
  "relativePath": [
2869
2907
  "dist",
2870
2908
  "commands",
2871
- "face",
2872
- "share.js"
2909
+ "style",
2910
+ "status.js"
2873
2911
  ]
2874
2912
  },
2875
- "face:sources": {
2913
+ "style:upload": {
2876
2914
  "aliases": [],
2877
2915
  "args": {
2878
2916
  "alias": {
2879
2917
  "description": "Face alias",
2880
2918
  "name": "alias",
2881
2919
  "required": true
2920
+ },
2921
+ "file": {
2922
+ "description": "Corpus file",
2923
+ "name": "file",
2924
+ "required": true
2882
2925
  }
2883
2926
  },
2884
- "description": "List every source compiled into a face: documents and threads together, one row each. Exits 4 if the face does not exist, which is a different answer from a face that has no sources. Content is never printed; read a single source with compile:doc:get or compile:thread:get.",
2927
+ "description": "Load a corpus of a person's own writing (a mail export, a message archive) as source material for style capture. This only stores the material: nothing is compiled and nothing is billed. Capture the style afterwards with style:make.",
2885
2928
  "examples": [
2886
- "<%= config.bin %> <%= command.id %> alice",
2887
- "<%= config.bin %> <%= command.id %> alice --type thread",
2888
- "<%= config.bin %> <%= command.id %> alice --json"
2929
+ "<%= config.bin %> <%= command.id %> alice ./mail.jsonl",
2930
+ "<%= config.bin %> <%= command.id %> alice ./thread.json --type thread_json",
2931
+ "<%= config.bin %> <%= command.id %> alice ./mail.jsonl --messages-per-room 100 --strict"
2889
2932
  ],
2890
2933
  "flags": {
2891
2934
  "json": {
@@ -2920,20 +2963,35 @@
2920
2963
  "type": "option"
2921
2964
  },
2922
2965
  "type": {
2923
- "description": "Show only one kind of source",
2966
+ "description": "email_jsonl: one message per line, split across several rooms. thread_json: a JSON array that becomes a single room.",
2924
2967
  "name": "type",
2968
+ "default": "email_jsonl",
2925
2969
  "hasDynamicHelp": false,
2926
2970
  "multiple": false,
2927
2971
  "options": [
2928
- "doc",
2929
- "thread"
2972
+ "email_jsonl",
2973
+ "thread_json"
2930
2974
  ],
2931
2975
  "type": "option"
2976
+ },
2977
+ "messages-per-room": {
2978
+ "description": "How many messages per room when the type is email_jsonl (1-1000, default: 50)",
2979
+ "name": "messages-per-room",
2980
+ "default": 50,
2981
+ "hasDynamicHelp": false,
2982
+ "multiple": false,
2983
+ "type": "option"
2984
+ },
2985
+ "strict": {
2986
+ "description": "Reject the whole upload if any message is invalid. By default invalid messages are skipped and reported, because a corpus is statistical and a few bad lines are not worth losing the rest.",
2987
+ "name": "strict",
2988
+ "allowNo": false,
2989
+ "type": "boolean"
2932
2990
  }
2933
2991
  },
2934
2992
  "hasDynamicHelp": false,
2935
2993
  "hiddenAliases": [],
2936
- "id": "face:sources",
2994
+ "id": "style:upload",
2937
2995
  "pluginAlias": "faces-cli",
2938
2996
  "pluginName": "faces-cli",
2939
2997
  "pluginType": "core",
@@ -2943,14 +3001,24 @@
2943
3001
  "relativePath": [
2944
3002
  "dist",
2945
3003
  "commands",
2946
- "face",
2947
- "sources.js"
3004
+ "style",
3005
+ "upload.js"
2948
3006
  ]
2949
3007
  },
2950
- "face:stats": {
3008
+ "style:versions": {
2951
3009
  "aliases": [],
2952
- "args": {},
2953
- "description": "Compile and chat stats for all owned faces",
3010
+ "args": {
3011
+ "alias": {
3012
+ "description": "Face alias",
3013
+ "name": "alias",
3014
+ "required": true
3015
+ }
3016
+ },
3017
+ "description": "List the styles captured for a face, and which one it writes in now. A face holds one style per medium, so more than one can be in use at once: an email style and an essay style are separate and do not replace each other. Two versions are kept per medium, which is what style:revert has to go back to.",
3018
+ "examples": [
3019
+ "<%= config.bin %> <%= command.id %> alice",
3020
+ "<%= config.bin %> <%= command.id %> alice --json"
3021
+ ],
2954
3022
  "flags": {
2955
3023
  "json": {
2956
3024
  "description": "Format output as json.",
@@ -2986,7 +3054,7 @@
2986
3054
  },
2987
3055
  "hasDynamicHelp": false,
2988
3056
  "hiddenAliases": [],
2989
- "id": "face:stats",
3057
+ "id": "style:versions",
2990
3058
  "pluginAlias": "faces-cli",
2991
3059
  "pluginName": "faces-cli",
2992
3060
  "pluginType": "core",
@@ -2996,20 +3064,20 @@
2996
3064
  "relativePath": [
2997
3065
  "dist",
2998
3066
  "commands",
2999
- "face",
3000
- "stats.js"
3067
+ "style",
3068
+ "versions.js"
3001
3069
  ]
3002
3070
  },
3003
- "face:teams": {
3071
+ "team:add": {
3004
3072
  "aliases": [],
3005
3073
  "args": {
3006
- "alias": {
3007
- "description": "Face alias",
3008
- "name": "alias",
3074
+ "team_id": {
3075
+ "description": "Team ID",
3076
+ "name": "team_id",
3009
3077
  "required": true
3010
3078
  }
3011
3079
  },
3012
- "description": "Set a face's team memberships (replaces all)",
3080
+ "description": "Add face(s) to a team. A team may only contain faces this account owns: a published or shared face can be chatted with but cannot be a member.",
3013
3081
  "flags": {
3014
3082
  "json": {
3015
3083
  "description": "Format output as json.",
@@ -3042,9 +3110,9 @@
3042
3110
  "multiple": false,
3043
3111
  "type": "option"
3044
3112
  },
3045
- "team": {
3046
- "description": "Team ID (repeatable, replaces all memberships)",
3047
- "name": "team",
3113
+ "face": {
3114
+ "description": "Face alias to add (repeatable)",
3115
+ "name": "face",
3048
3116
  "required": true,
3049
3117
  "hasDynamicHelp": false,
3050
3118
  "multiple": true,
@@ -3053,7 +3121,7 @@
3053
3121
  },
3054
3122
  "hasDynamicHelp": false,
3055
3123
  "hiddenAliases": [],
3056
- "id": "face:teams",
3124
+ "id": "team:add",
3057
3125
  "pluginAlias": "faces-cli",
3058
3126
  "pluginName": "faces-cli",
3059
3127
  "pluginType": "core",
@@ -3063,23 +3131,14 @@
3063
3131
  "relativePath": [
3064
3132
  "dist",
3065
3133
  "commands",
3066
- "face",
3067
- "teams.js"
3134
+ "team",
3135
+ "add.js"
3068
3136
  ]
3069
3137
  },
3070
- "face:unlock": {
3138
+ "team:create": {
3071
3139
  "aliases": [],
3072
- "args": {
3073
- "face_id": {
3074
- "description": "Face alias",
3075
- "name": "face_id",
3076
- "required": true
3077
- }
3078
- },
3079
- "description": "Unlock a face (make it writable again). Thaws the face and everything it owns (documents, threads, voiceprint).",
3080
- "examples": [
3081
- "<%= config.bin %> <%= command.id %> socrates"
3082
- ],
3140
+ "args": {},
3141
+ "description": "Create a new team",
3083
3142
  "flags": {
3084
3143
  "json": {
3085
3144
  "description": "Format output as json.",
@@ -3111,11 +3170,47 @@
3111
3170
  "hasDynamicHelp": false,
3112
3171
  "multiple": false,
3113
3172
  "type": "option"
3173
+ },
3174
+ "name": {
3175
+ "description": "Team name",
3176
+ "name": "name",
3177
+ "required": true,
3178
+ "hasDynamicHelp": false,
3179
+ "multiple": false,
3180
+ "type": "option"
3181
+ },
3182
+ "description": {
3183
+ "description": "Plain-text team description (max 1500 chars)",
3184
+ "name": "description",
3185
+ "hasDynamicHelp": false,
3186
+ "multiple": false,
3187
+ "type": "option"
3188
+ },
3189
+ "protocol": {
3190
+ "description": "Protocol content (mermaid diagram or markdown, max 1000 words)",
3191
+ "name": "protocol",
3192
+ "hasDynamicHelp": false,
3193
+ "multiple": false,
3194
+ "type": "option"
3195
+ },
3196
+ "protocol-file": {
3197
+ "description": "Read protocol from file",
3198
+ "name": "protocol-file",
3199
+ "hasDynamicHelp": false,
3200
+ "multiple": false,
3201
+ "type": "option"
3202
+ },
3203
+ "tag": {
3204
+ "description": "Tag label (repeatable, lowercase)",
3205
+ "name": "tag",
3206
+ "hasDynamicHelp": false,
3207
+ "multiple": true,
3208
+ "type": "option"
3114
3209
  }
3115
3210
  },
3116
3211
  "hasDynamicHelp": false,
3117
3212
  "hiddenAliases": [],
3118
- "id": "face:unlock",
3213
+ "id": "team:create",
3119
3214
  "pluginAlias": "faces-cli",
3120
3215
  "pluginName": "faces-cli",
3121
3216
  "pluginType": "core",
@@ -3125,20 +3220,20 @@
3125
3220
  "relativePath": [
3126
3221
  "dist",
3127
3222
  "commands",
3128
- "face",
3129
- "unlock.js"
3223
+ "team",
3224
+ "create.js"
3130
3225
  ]
3131
3226
  },
3132
- "face:unpublish": {
3227
+ "team:delete": {
3133
3228
  "aliases": [],
3134
3229
  "args": {
3135
- "alias": {
3136
- "description": "Face alias",
3137
- "name": "alias",
3230
+ "team_id": {
3231
+ "description": "Team ID",
3232
+ "name": "team_id",
3138
3233
  "required": true
3139
3234
  }
3140
3235
  },
3141
- "description": "Stop publishing a face. Anyone it is individually shared with keeps their access — publishing is an override on top of sharing, not a replacement for it.",
3236
+ "description": "Delete a team",
3142
3237
  "flags": {
3143
3238
  "json": {
3144
3239
  "description": "Format output as json.",
@@ -3170,11 +3265,17 @@
3170
3265
  "hasDynamicHelp": false,
3171
3266
  "multiple": false,
3172
3267
  "type": "option"
3268
+ },
3269
+ "yes": {
3270
+ "description": "Skip confirmation",
3271
+ "name": "yes",
3272
+ "allowNo": false,
3273
+ "type": "boolean"
3173
3274
  }
3174
3275
  },
3175
3276
  "hasDynamicHelp": false,
3176
3277
  "hiddenAliases": [],
3177
- "id": "face:unpublish",
3278
+ "id": "team:delete",
3178
3279
  "pluginAlias": "faces-cli",
3179
3280
  "pluginName": "faces-cli",
3180
3281
  "pluginType": "core",
@@ -3184,24 +3285,20 @@
3184
3285
  "relativePath": [
3185
3286
  "dist",
3186
3287
  "commands",
3187
- "face",
3188
- "unpublish.js"
3288
+ "team",
3289
+ "delete.js"
3189
3290
  ]
3190
3291
  },
3191
- "face:unshare": {
3292
+ "team:edit": {
3192
3293
  "aliases": [],
3193
3294
  "args": {
3194
- "alias": {
3195
- "description": "Face alias",
3196
- "name": "alias",
3295
+ "team_id": {
3296
+ "description": "Team ID",
3297
+ "name": "team_id",
3197
3298
  "required": true
3198
3299
  }
3199
3300
  },
3200
- "description": "Revoke access to a shared face. Takes effect immediately — there is no grace period.",
3201
- "examples": [
3202
- "<%= config.bin %> <%= command.id %> alice --from dana --yes",
3203
- "<%= config.bin %> <%= command.id %> alice --all --yes"
3204
- ],
3301
+ "description": "Edit a team",
3205
3302
  "flags": {
3206
3303
  "json": {
3207
3304
  "description": "Format output as json.",
@@ -3234,35 +3331,38 @@
3234
3331
  "multiple": false,
3235
3332
  "type": "option"
3236
3333
  },
3237
- "from": {
3238
- "description": "Account to revoke (repeatable)",
3239
- "exclusive": [
3240
- "all"
3241
- ],
3242
- "name": "from",
3334
+ "name": {
3335
+ "description": "New team name",
3336
+ "name": "name",
3243
3337
  "hasDynamicHelp": false,
3244
- "multiple": true,
3338
+ "multiple": false,
3245
3339
  "type": "option"
3246
3340
  },
3247
- "all": {
3248
- "description": "Revoke everyone",
3249
- "exclusive": [
3250
- "from"
3251
- ],
3252
- "name": "all",
3253
- "allowNo": false,
3254
- "type": "boolean"
3341
+ "description": {
3342
+ "description": "New description (max 1500 chars)",
3343
+ "name": "description",
3344
+ "hasDynamicHelp": false,
3345
+ "multiple": false,
3346
+ "type": "option"
3255
3347
  },
3256
- "yes": {
3257
- "description": "Skip confirmation",
3258
- "name": "yes",
3259
- "allowNo": false,
3260
- "type": "boolean"
3348
+ "protocol": {
3349
+ "description": "New protocol content",
3350
+ "name": "protocol",
3351
+ "hasDynamicHelp": false,
3352
+ "multiple": false,
3353
+ "type": "option"
3354
+ },
3355
+ "protocol-file": {
3356
+ "description": "Read protocol from file",
3357
+ "name": "protocol-file",
3358
+ "hasDynamicHelp": false,
3359
+ "multiple": false,
3360
+ "type": "option"
3261
3361
  }
3262
3362
  },
3263
3363
  "hasDynamicHelp": false,
3264
3364
  "hiddenAliases": [],
3265
- "id": "face:unshare",
3365
+ "id": "team:edit",
3266
3366
  "pluginAlias": "faces-cli",
3267
3367
  "pluginName": "faces-cli",
3268
3368
  "pluginType": "core",
@@ -3272,14 +3372,20 @@
3272
3372
  "relativePath": [
3273
3373
  "dist",
3274
3374
  "commands",
3275
- "face",
3276
- "unshare.js"
3375
+ "team",
3376
+ "edit.js"
3277
3377
  ]
3278
3378
  },
3279
- "keys:create": {
3379
+ "team:get": {
3280
3380
  "aliases": [],
3281
- "args": {},
3282
- "description": "Create a new API key (JWT required). The new key is saved to ~/.faces/config.json as api_key by default; pass --no-save to skip.",
3381
+ "args": {
3382
+ "team_id": {
3383
+ "description": "Team ID",
3384
+ "name": "team_id",
3385
+ "required": true
3386
+ }
3387
+ },
3388
+ "description": "Get a team by ID",
3283
3389
  "flags": {
3284
3390
  "json": {
3285
3391
  "description": "Format output as json.",
@@ -3311,53 +3417,11 @@
3311
3417
  "hasDynamicHelp": false,
3312
3418
  "multiple": false,
3313
3419
  "type": "option"
3314
- },
3315
- "name": {
3316
- "description": "Key name/label",
3317
- "name": "name",
3318
- "required": true,
3319
- "hasDynamicHelp": false,
3320
- "multiple": false,
3321
- "type": "option"
3322
- },
3323
- "expires-days": {
3324
- "description": "Expiry in days (omit for no expiry)",
3325
- "name": "expires-days",
3326
- "hasDynamicHelp": false,
3327
- "multiple": false,
3328
- "type": "option"
3329
- },
3330
- "budget": {
3331
- "description": "Spend budget in USD",
3332
- "name": "budget",
3333
- "hasDynamicHelp": false,
3334
- "multiple": false,
3335
- "type": "option"
3336
- },
3337
- "face": {
3338
- "description": "Allowed face alias (repeatable)",
3339
- "name": "face",
3340
- "hasDynamicHelp": false,
3341
- "multiple": true,
3342
- "type": "option"
3343
- },
3344
- "model": {
3345
- "description": "Allowed model name (repeatable)",
3346
- "name": "model",
3347
- "hasDynamicHelp": false,
3348
- "multiple": true,
3349
- "type": "option"
3350
- },
3351
- "save": {
3352
- "description": "Save the new key to ~/.faces/config.json as api_key (default: true; use --no-save to skip)",
3353
- "name": "save",
3354
- "allowNo": true,
3355
- "type": "boolean"
3356
3420
  }
3357
3421
  },
3358
3422
  "hasDynamicHelp": false,
3359
3423
  "hiddenAliases": [],
3360
- "id": "keys:create",
3424
+ "id": "team:get",
3361
3425
  "pluginAlias": "faces-cli",
3362
3426
  "pluginName": "faces-cli",
3363
3427
  "pluginType": "core",
@@ -3367,14 +3431,14 @@
3367
3431
  "relativePath": [
3368
3432
  "dist",
3369
3433
  "commands",
3370
- "keys",
3371
- "create.js"
3434
+ "team",
3435
+ "get.js"
3372
3436
  ]
3373
3437
  },
3374
- "keys:list": {
3438
+ "team:list": {
3375
3439
  "aliases": [],
3376
3440
  "args": {},
3377
- "description": "List all API keys (JWT required)",
3441
+ "description": "List your teams",
3378
3442
  "flags": {
3379
3443
  "json": {
3380
3444
  "description": "Format output as json.",
@@ -3410,7 +3474,7 @@
3410
3474
  },
3411
3475
  "hasDynamicHelp": false,
3412
3476
  "hiddenAliases": [],
3413
- "id": "keys:list",
3477
+ "id": "team:list",
3414
3478
  "pluginAlias": "faces-cli",
3415
3479
  "pluginName": "faces-cli",
3416
3480
  "pluginType": "core",
@@ -3420,20 +3484,20 @@
3420
3484
  "relativePath": [
3421
3485
  "dist",
3422
3486
  "commands",
3423
- "keys",
3487
+ "team",
3424
3488
  "list.js"
3425
3489
  ]
3426
3490
  },
3427
- "keys:revoke": {
3491
+ "team:members": {
3428
3492
  "aliases": [],
3429
3493
  "args": {
3430
- "key_id": {
3431
- "description": "Key ID",
3432
- "name": "key_id",
3494
+ "team_id": {
3495
+ "description": "Team ID",
3496
+ "name": "team_id",
3433
3497
  "required": true
3434
3498
  }
3435
3499
  },
3436
- "description": "Revoke an API key (JWT required)",
3500
+ "description": "List members of a team",
3437
3501
  "flags": {
3438
3502
  "json": {
3439
3503
  "description": "Format output as json.",
@@ -3465,17 +3529,11 @@
3465
3529
  "hasDynamicHelp": false,
3466
3530
  "multiple": false,
3467
3531
  "type": "option"
3468
- },
3469
- "yes": {
3470
- "description": "Skip confirmation",
3471
- "name": "yes",
3472
- "allowNo": false,
3473
- "type": "boolean"
3474
3532
  }
3475
3533
  },
3476
3534
  "hasDynamicHelp": false,
3477
3535
  "hiddenAliases": [],
3478
- "id": "keys:revoke",
3536
+ "id": "team:members",
3479
3537
  "pluginAlias": "faces-cli",
3480
3538
  "pluginName": "faces-cli",
3481
3539
  "pluginType": "core",
@@ -3485,20 +3543,25 @@
3485
3543
  "relativePath": [
3486
3544
  "dist",
3487
3545
  "commands",
3488
- "keys",
3489
- "revoke.js"
3546
+ "team",
3547
+ "members.js"
3490
3548
  ]
3491
3549
  },
3492
- "keys:update": {
3550
+ "team:remove": {
3493
3551
  "aliases": [],
3494
3552
  "args": {
3495
- "key_id": {
3496
- "description": "Key ID",
3497
- "name": "key_id",
3553
+ "team_id": {
3554
+ "description": "Team ID",
3555
+ "name": "team_id",
3556
+ "required": true
3557
+ },
3558
+ "alias": {
3559
+ "description": "Face alias to remove",
3560
+ "name": "alias",
3498
3561
  "required": true
3499
3562
  }
3500
3563
  },
3501
- "description": "Update API key metadata (JWT required)",
3564
+ "description": "Remove a face from a team",
3502
3565
  "flags": {
3503
3566
  "json": {
3504
3567
  "description": "Format output as json.",
@@ -3530,31 +3593,11 @@
3530
3593
  "hasDynamicHelp": false,
3531
3594
  "multiple": false,
3532
3595
  "type": "option"
3533
- },
3534
- "name": {
3535
- "description": "New key name",
3536
- "name": "name",
3537
- "hasDynamicHelp": false,
3538
- "multiple": false,
3539
- "type": "option"
3540
- },
3541
- "budget": {
3542
- "description": "New spend budget in USD",
3543
- "name": "budget",
3544
- "hasDynamicHelp": false,
3545
- "multiple": false,
3546
- "type": "option"
3547
- },
3548
- "reset-spent": {
3549
- "description": "Reset spent amount to zero",
3550
- "name": "reset-spent",
3551
- "allowNo": false,
3552
- "type": "boolean"
3553
3596
  }
3554
3597
  },
3555
3598
  "hasDynamicHelp": false,
3556
3599
  "hiddenAliases": [],
3557
- "id": "keys:update",
3600
+ "id": "team:remove",
3558
3601
  "pluginAlias": "faces-cli",
3559
3602
  "pluginName": "faces-cli",
3560
3603
  "pluginType": "core",
@@ -3564,24 +3607,14 @@
3564
3607
  "relativePath": [
3565
3608
  "dist",
3566
3609
  "commands",
3567
- "keys",
3568
- "update.js"
3610
+ "team",
3611
+ "remove.js"
3569
3612
  ]
3570
3613
  },
3571
- "style:delete": {
3614
+ "face:attributes": {
3572
3615
  "aliases": [],
3573
- "args": {
3574
- "alias": {
3575
- "description": "Face alias",
3576
- "name": "alias",
3577
- "required": true
3578
- }
3579
- },
3580
- "description": "Delete a face's captured style. The material it was learned from is kept, so the style can be captured again without re-uploading. This never deletes documents or threads: remove those with compile:doc:delete or compile:thread:delete.",
3581
- "examples": [
3582
- "<%= config.bin %> <%= command.id %> alice",
3583
- "<%= config.bin %> <%= command.id %> alice --yes"
3584
- ],
3616
+ "args": {},
3617
+ "description": "List all supported attribute keys",
3585
3618
  "flags": {
3586
3619
  "json": {
3587
3620
  "description": "Format output as json.",
@@ -3613,17 +3646,11 @@
3613
3646
  "hasDynamicHelp": false,
3614
3647
  "multiple": false,
3615
3648
  "type": "option"
3616
- },
3617
- "yes": {
3618
- "description": "Skip confirmation",
3619
- "name": "yes",
3620
- "allowNo": false,
3621
- "type": "boolean"
3622
3649
  }
3623
3650
  },
3624
3651
  "hasDynamicHelp": false,
3625
3652
  "hiddenAliases": [],
3626
- "id": "style:delete",
3653
+ "id": "face:attributes",
3627
3654
  "pluginAlias": "faces-cli",
3628
3655
  "pluginName": "faces-cli",
3629
3656
  "pluginType": "core",
@@ -3633,26 +3660,14 @@
3633
3660
  "relativePath": [
3634
3661
  "dist",
3635
3662
  "commands",
3636
- "style",
3637
- "delete.js"
3663
+ "face",
3664
+ "attributes.js"
3638
3665
  ]
3639
3666
  },
3640
- "style:make": {
3667
+ "face:create": {
3641
3668
  "aliases": [],
3642
- "args": {
3643
- "alias": {
3644
- "description": "Face alias",
3645
- "name": "alias",
3646
- "required": true
3647
- }
3648
- },
3649
- "description": "Capture how a face writes, from its own material, and install it. This is style, not knowledge: compile teaches a face what it knows, style teaches it how it sounds. Name the sources to learn from with --source, or take everything ready with --all.",
3650
- "examples": [
3651
- "<%= config.bin %> <%= command.id %> alice --all",
3652
- "<%= config.bin %> <%= command.id %> alice --source 1a2b3c4d --source 5e6f7a8b",
3653
- "<%= config.bin %> <%= command.id %> alice --source 1a2b3c4d:essay",
3654
- "<%= config.bin %> <%= command.id %> alice --all --medium essay --no-wait"
3655
- ],
3669
+ "args": {},
3670
+ "description": "Create a new face",
3656
3671
  "flags": {
3657
3672
  "json": {
3658
3673
  "description": "Format output as json.",
@@ -3685,62 +3700,77 @@
3685
3700
  "multiple": false,
3686
3701
  "type": "option"
3687
3702
  },
3688
- "source": {
3689
- "description": "A document or thread to learn from, by id (repeatable). Append :<medium> to declare what it is, e.g. --source 1a2b3c4d:essay, when the source does not already say.",
3690
- "name": "source",
3703
+ "name": {
3704
+ "description": "Display name",
3705
+ "name": "name",
3706
+ "required": true,
3691
3707
  "hasDynamicHelp": false,
3692
- "multiple": true,
3708
+ "multiple": false,
3693
3709
  "type": "option"
3694
3710
  },
3695
- "all": {
3696
- "description": "Use every source on the face that is ready. Anything skipped is listed.",
3697
- "name": "all",
3698
- "allowNo": false,
3699
- "type": "boolean"
3700
- },
3701
- "medium": {
3702
- "description": "Medium for any selected source that does not declare one. Each medium is analysed on its own, so an essay never teaches a rule about email.",
3703
- "name": "medium",
3711
+ "alias": {
3712
+ "description": "Unique alias slug",
3713
+ "name": "alias",
3714
+ "required": true,
3704
3715
  "hasDynamicHelp": false,
3705
3716
  "multiple": false,
3706
3717
  "type": "option"
3707
3718
  },
3708
- "model": {
3709
- "description": "Analyst model (default: gpt-5.6-terra)",
3710
- "name": "model",
3719
+ "description": {
3720
+ "description": "Plain-text description / bio (max 1500 chars)",
3721
+ "name": "description",
3711
3722
  "hasDynamicHelp": false,
3712
3723
  "multiple": false,
3713
3724
  "type": "option"
3714
3725
  },
3715
- "allow-paid": {
3716
- "description": "Permit a build that bills. Without this a build is free or it does not run. Needed for any model outside the free tier, and to allow the paid route when a free quota is exhausted.",
3717
- "name": "allow-paid",
3718
- "allowNo": false,
3719
- "type": "boolean"
3726
+ "tag": {
3727
+ "description": "Tag label (repeatable, lowercase)",
3728
+ "name": "tag",
3729
+ "hasDynamicHelp": false,
3730
+ "multiple": true,
3731
+ "type": "option"
3720
3732
  },
3721
- "compile": {
3722
- "description": "Compile any named source that is not compiled yet, before capturing style. On by default. --no-compile captures style from what is already compiled and never bills for compilation.",
3723
- "name": "compile",
3724
- "allowNo": true,
3725
- "type": "boolean"
3733
+ "default-model": {
3734
+ "description": "Default LLM for chat (e.g. gpt-4o-mini, claude-sonnet-4-6)",
3735
+ "name": "default-model",
3736
+ "hasDynamicHelp": false,
3737
+ "multiple": false,
3738
+ "type": "option"
3726
3739
  },
3727
- "best-of": {
3728
- "description": "Generate N candidates and keep the best (1-5, default 1)",
3729
- "name": "best-of",
3740
+ "formula": {
3741
+ "description": "Boolean formula over owned concrete face aliases (e.g. \"a | b\", \"(a | b) - c\"). Creates a composite face.",
3742
+ "name": "formula",
3730
3743
  "hasDynamicHelp": false,
3731
3744
  "multiple": false,
3732
3745
  "type": "option"
3733
3746
  },
3734
- "no-wait": {
3735
- "description": "Start the build and return the job id without polling.",
3736
- "name": "no-wait",
3737
- "allowNo": false,
3738
- "type": "boolean"
3747
+ "attr": {
3748
+ "description": "Attribute KEY=VALUE (repeatable)",
3749
+ "name": "attr",
3750
+ "hasDynamicHelp": false,
3751
+ "multiple": true,
3752
+ "type": "option"
3739
3753
  },
3740
- "timeout": {
3741
- "description": "How long to wait, in seconds (default: 3600)",
3742
- "name": "timeout",
3743
- "default": 3600,
3754
+ "tool": {
3755
+ "description": "Tool name to enable (repeatable)",
3756
+ "name": "tool",
3757
+ "hasDynamicHelp": false,
3758
+ "multiple": true,
3759
+ "type": "option"
3760
+ },
3761
+ "profile-addendum": {
3762
+ "description": "Per-face system prompt, injected after the persona profile and before any per-request system prompt (max 100,000 chars).",
3763
+ "name": "profile-addendum",
3764
+ "hasDynamicHelp": false,
3765
+ "multiple": false,
3766
+ "type": "option"
3767
+ },
3768
+ "profile-addendum-file": {
3769
+ "description": "Read the per-face system prompt from a file (alternative to --profile-addendum).",
3770
+ "exclusive": [
3771
+ "profile-addendum"
3772
+ ],
3773
+ "name": "profile-addendum-file",
3744
3774
  "hasDynamicHelp": false,
3745
3775
  "multiple": false,
3746
3776
  "type": "option"
@@ -3748,7 +3778,7 @@
3748
3778
  },
3749
3779
  "hasDynamicHelp": false,
3750
3780
  "hiddenAliases": [],
3751
- "id": "style:make",
3781
+ "id": "face:create",
3752
3782
  "pluginAlias": "faces-cli",
3753
3783
  "pluginName": "faces-cli",
3754
3784
  "pluginType": "core",
@@ -3758,23 +3788,20 @@
3758
3788
  "relativePath": [
3759
3789
  "dist",
3760
3790
  "commands",
3761
- "style",
3762
- "make.js"
3791
+ "face",
3792
+ "create.js"
3763
3793
  ]
3764
3794
  },
3765
- "style:revert": {
3795
+ "face:delete": {
3766
3796
  "aliases": [],
3767
3797
  "args": {
3768
- "alias": {
3798
+ "face_id": {
3769
3799
  "description": "Face alias",
3770
- "name": "alias",
3800
+ "name": "face_id",
3771
3801
  "required": true
3772
3802
  }
3773
3803
  },
3774
- "description": "Go back to the style a face had before the last style:make. It steps backwards through the kept versions and there is no step forward, so the way to undo a revert is to capture the style again. It changes how the face writes immediately, so it asks first.",
3775
- "examples": [
3776
- "<%= config.bin %> <%= command.id %> alice --yes"
3777
- ],
3804
+ "description": "Delete a face permanently",
3778
3805
  "flags": {
3779
3806
  "json": {
3780
3807
  "description": "Format output as json.",
@@ -3816,7 +3843,7 @@
3816
3843
  },
3817
3844
  "hasDynamicHelp": false,
3818
3845
  "hiddenAliases": [],
3819
- "id": "style:revert",
3846
+ "id": "face:delete",
3820
3847
  "pluginAlias": "faces-cli",
3821
3848
  "pluginName": "faces-cli",
3822
3849
  "pluginType": "core",
@@ -3826,25 +3853,14 @@
3826
3853
  "relativePath": [
3827
3854
  "dist",
3828
3855
  "commands",
3829
- "style",
3830
- "revert.js"
3856
+ "face",
3857
+ "delete.js"
3831
3858
  ]
3832
3859
  },
3833
- "style:status": {
3860
+ "face:diff": {
3834
3861
  "aliases": [],
3835
- "args": {
3836
- "job_id": {
3837
- "description": "Build job id",
3838
- "name": "job_id",
3839
- "required": false
3840
- }
3841
- },
3842
- "description": "Read a style build. Give a job id for one build, or --face to list a face's recent builds. Listing is how you find a job id you no longer have.",
3843
- "examples": [
3844
- "<%= config.bin %> <%= command.id %> 7a8b9c0d",
3845
- "<%= config.bin %> <%= command.id %> --face alice",
3846
- "<%= config.bin %> <%= command.id %> 7a8b9c0d --wait"
3847
- ],
3862
+ "args": {},
3863
+ "description": "Compare owned faces pairwise across all centroid components",
3848
3864
  "flags": {
3849
3865
  "json": {
3850
3866
  "description": "Format output as json.",
@@ -3878,38 +3894,17 @@
3878
3894
  "type": "option"
3879
3895
  },
3880
3896
  "face": {
3881
- "description": "List recent builds for this face instead of reading one job",
3897
+ "description": "Face alias to include (repeatable, min 2)",
3882
3898
  "name": "face",
3899
+ "required": true,
3883
3900
  "hasDynamicHelp": false,
3884
- "multiple": false,
3885
- "type": "option"
3886
- },
3887
- "limit": {
3888
- "description": "How many builds to list with --face (default: 10)",
3889
- "name": "limit",
3890
- "default": 10,
3891
- "hasDynamicHelp": false,
3892
- "multiple": false,
3893
- "type": "option"
3894
- },
3895
- "wait": {
3896
- "description": "Block until the job finishes",
3897
- "name": "wait",
3898
- "allowNo": false,
3899
- "type": "boolean"
3900
- },
3901
- "timeout": {
3902
- "description": "How long to wait with --wait, in seconds (default: 3600)",
3903
- "name": "timeout",
3904
- "default": 3600,
3905
- "hasDynamicHelp": false,
3906
- "multiple": false,
3901
+ "multiple": true,
3907
3902
  "type": "option"
3908
3903
  }
3909
3904
  },
3910
3905
  "hasDynamicHelp": false,
3911
3906
  "hiddenAliases": [],
3912
- "id": "style:status",
3907
+ "id": "face:diff",
3913
3908
  "pluginAlias": "faces-cli",
3914
3909
  "pluginName": "faces-cli",
3915
3910
  "pluginType": "core",
@@ -3919,30 +3914,20 @@
3919
3914
  "relativePath": [
3920
3915
  "dist",
3921
3916
  "commands",
3922
- "style",
3923
- "status.js"
3917
+ "face",
3918
+ "diff.js"
3924
3919
  ]
3925
3920
  },
3926
- "style:upload": {
3921
+ "face:edit": {
3927
3922
  "aliases": [],
3928
3923
  "args": {
3929
- "alias": {
3924
+ "face_id": {
3930
3925
  "description": "Face alias",
3931
- "name": "alias",
3932
- "required": true
3933
- },
3934
- "file": {
3935
- "description": "Corpus file",
3936
- "name": "file",
3926
+ "name": "face_id",
3937
3927
  "required": true
3938
3928
  }
3939
3929
  },
3940
- "description": "Load a corpus of a person's own writing (a mail export, a message archive) as source material for style capture. This only stores the material: nothing is compiled and nothing is billed. Capture the style afterwards with style:make.",
3941
- "examples": [
3942
- "<%= config.bin %> <%= command.id %> alice ./mail.jsonl",
3943
- "<%= config.bin %> <%= command.id %> alice ./thread.json --type thread_json",
3944
- "<%= config.bin %> <%= command.id %> alice ./mail.jsonl --messages-per-room 100 --strict"
3945
- ],
3930
+ "description": "Edit a face's metadata",
3946
3931
  "flags": {
3947
3932
  "json": {
3948
3933
  "description": "Format output as json.",
@@ -3975,99 +3960,86 @@
3975
3960
  "multiple": false,
3976
3961
  "type": "option"
3977
3962
  },
3978
- "type": {
3979
- "description": "email_jsonl: one message per line, split across several rooms. thread_json: a JSON array that becomes a single room.",
3980
- "name": "type",
3981
- "default": "email_jsonl",
3963
+ "name": {
3964
+ "description": "New display name",
3965
+ "name": "name",
3982
3966
  "hasDynamicHelp": false,
3983
3967
  "multiple": false,
3984
- "options": [
3985
- "email_jsonl",
3986
- "thread_json"
3987
- ],
3988
3968
  "type": "option"
3989
3969
  },
3990
- "messages-per-room": {
3991
- "description": "How many messages per room when the type is email_jsonl (1-1000, default: 50)",
3992
- "name": "messages-per-room",
3993
- "default": 50,
3970
+ "description": {
3971
+ "description": "Plain-text description / bio (max 1500 chars)",
3972
+ "name": "description",
3994
3973
  "hasDynamicHelp": false,
3995
3974
  "multiple": false,
3996
3975
  "type": "option"
3997
3976
  },
3998
- "strict": {
3999
- "description": "Reject the whole upload if any message is invalid. By default invalid messages are skipped and reported, because a corpus is statistical and a few bad lines are not worth losing the rest.",
4000
- "name": "strict",
4001
- "allowNo": false,
4002
- "type": "boolean"
4003
- }
4004
- },
4005
- "hasDynamicHelp": false,
4006
- "hiddenAliases": [],
4007
- "id": "style:upload",
4008
- "pluginAlias": "faces-cli",
4009
- "pluginName": "faces-cli",
4010
- "pluginType": "core",
4011
- "strict": true,
4012
- "enableJsonFlag": true,
4013
- "isESM": true,
4014
- "relativePath": [
4015
- "dist",
4016
- "commands",
4017
- "style",
4018
- "upload.js"
4019
- ]
4020
- },
4021
- "style:versions": {
4022
- "aliases": [],
4023
- "args": {
4024
- "alias": {
4025
- "description": "Face alias",
4026
- "name": "alias",
4027
- "required": true
4028
- }
4029
- },
4030
- "description": "List the styles captured for a face, and which one it is writing in now. Each style:make keeps the previous one, so this is what style:revert has to go back to.",
4031
- "examples": [
4032
- "<%= config.bin %> <%= command.id %> alice",
4033
- "<%= config.bin %> <%= command.id %> alice --json"
4034
- ],
4035
- "flags": {
4036
- "json": {
4037
- "description": "Format output as json.",
4038
- "helpGroup": "GLOBAL",
4039
- "name": "json",
4040
- "allowNo": false,
4041
- "type": "boolean"
3977
+ "tag": {
3978
+ "description": "Replace all tags (repeatable, lowercase)",
3979
+ "name": "tag",
3980
+ "hasDynamicHelp": false,
3981
+ "multiple": true,
3982
+ "type": "option"
4042
3983
  },
4043
- "base-url": {
4044
- "description": "API base URL",
4045
- "env": "FACES_BASE_URL",
4046
- "name": "base-url",
3984
+ "default-model": {
3985
+ "description": "Default LLM for chat (e.g. gpt-4o-mini, claude-sonnet-4-6)",
3986
+ "name": "default-model",
3987
+ "hasDynamicHelp": false,
3988
+ "multiple": false,
3989
+ "type": "option"
3990
+ },
3991
+ "formula": {
3992
+ "description": "New boolean formula (synthetic faces only)",
3993
+ "name": "formula",
4047
3994
  "hasDynamicHelp": false,
4048
3995
  "multiple": false,
4049
3996
  "type": "option"
4050
3997
  },
4051
- "token": {
4052
- "description": "JWT bearer token",
4053
- "env": "FACES_TOKEN",
4054
- "name": "token",
3998
+ "attr": {
3999
+ "description": "Update attribute KEY=VALUE (repeatable)",
4000
+ "name": "attr",
4001
+ "hasDynamicHelp": false,
4002
+ "multiple": true,
4003
+ "type": "option"
4004
+ },
4005
+ "tool": {
4006
+ "description": "Tool names to set (replaces list, repeatable)",
4007
+ "name": "tool",
4008
+ "hasDynamicHelp": false,
4009
+ "multiple": true,
4010
+ "type": "option"
4011
+ },
4012
+ "profile-addendum": {
4013
+ "description": "Replace the per-face system prompt (max 100,000 chars).",
4014
+ "name": "profile-addendum",
4055
4015
  "hasDynamicHelp": false,
4056
4016
  "multiple": false,
4057
4017
  "type": "option"
4058
4018
  },
4059
- "api-key": {
4060
- "description": "API key",
4061
- "env": "FACES_API_KEY",
4062
- "name": "api-key",
4019
+ "profile-addendum-file": {
4020
+ "description": "Replace the per-face system prompt from a file.",
4021
+ "exclusive": [
4022
+ "profile-addendum"
4023
+ ],
4024
+ "name": "profile-addendum-file",
4063
4025
  "hasDynamicHelp": false,
4064
4026
  "multiple": false,
4065
4027
  "type": "option"
4028
+ },
4029
+ "clear-profile-addendum": {
4030
+ "description": "Remove the per-face system prompt.",
4031
+ "exclusive": [
4032
+ "profile-addendum",
4033
+ "profile-addendum-file"
4034
+ ],
4035
+ "name": "clear-profile-addendum",
4036
+ "allowNo": false,
4037
+ "type": "boolean"
4066
4038
  }
4067
4039
  },
4068
4040
  "hasDynamicHelp": false,
4069
4041
  "hiddenAliases": [],
4070
- "id": "style:versions",
4042
+ "id": "face:edit",
4071
4043
  "pluginAlias": "faces-cli",
4072
4044
  "pluginName": "faces-cli",
4073
4045
  "pluginType": "core",
@@ -4077,20 +4049,20 @@
4077
4049
  "relativePath": [
4078
4050
  "dist",
4079
4051
  "commands",
4080
- "style",
4081
- "versions.js"
4052
+ "face",
4053
+ "edit.js"
4082
4054
  ]
4083
4055
  },
4084
- "team:add": {
4056
+ "face:get": {
4085
4057
  "aliases": [],
4086
4058
  "args": {
4087
- "team_id": {
4088
- "description": "Team ID",
4089
- "name": "team_id",
4059
+ "face_id": {
4060
+ "description": "Face alias",
4061
+ "name": "face_id",
4090
4062
  "required": true
4091
4063
  }
4092
4064
  },
4093
- "description": "Add face(s) to a team",
4065
+ "description": "Get details for a face, by alias or owner:alias. A published or shared face is reachable under the same owner:alias address chat uses; it is shown with a note that you do not own it.",
4094
4066
  "flags": {
4095
4067
  "json": {
4096
4068
  "description": "Format output as json.",
@@ -4123,18 +4095,23 @@
4123
4095
  "multiple": false,
4124
4096
  "type": "option"
4125
4097
  },
4126
- "face": {
4127
- "description": "Face alias to add (repeatable)",
4128
- "name": "face",
4129
- "required": true,
4098
+ "include": {
4099
+ "description": "Include extra fields: tags, teams (comma-separated)",
4100
+ "name": "include",
4130
4101
  "hasDynamicHelp": false,
4131
- "multiple": true,
4102
+ "multiple": false,
4132
4103
  "type": "option"
4104
+ },
4105
+ "full": {
4106
+ "description": "Print the full profile_addendum instead of a truncated preview",
4107
+ "name": "full",
4108
+ "allowNo": false,
4109
+ "type": "boolean"
4133
4110
  }
4134
4111
  },
4135
4112
  "hasDynamicHelp": false,
4136
4113
  "hiddenAliases": [],
4137
- "id": "team:add",
4114
+ "id": "face:get",
4138
4115
  "pluginAlias": "faces-cli",
4139
4116
  "pluginName": "faces-cli",
4140
4117
  "pluginType": "core",
@@ -4144,14 +4121,14 @@
4144
4121
  "relativePath": [
4145
4122
  "dist",
4146
4123
  "commands",
4147
- "team",
4148
- "add.js"
4124
+ "face",
4125
+ "get.js"
4149
4126
  ]
4150
4127
  },
4151
- "team:create": {
4128
+ "face:list": {
4152
4129
  "aliases": [],
4153
4130
  "args": {},
4154
- "description": "Create a new team",
4131
+ "description": "List faces. By default lists owned faces; use --public to include published faces from other accounts.",
4155
4132
  "flags": {
4156
4133
  "json": {
4157
4134
  "description": "Format output as json.",
@@ -4184,38 +4161,55 @@
4184
4161
  "multiple": false,
4185
4162
  "type": "option"
4186
4163
  },
4187
- "name": {
4188
- "description": "Team name",
4189
- "name": "name",
4190
- "required": true,
4164
+ "tag": {
4165
+ "description": "Filter by tag (repeatable, AND logic)",
4166
+ "name": "tag",
4191
4167
  "hasDynamicHelp": false,
4192
- "multiple": false,
4168
+ "multiple": true,
4193
4169
  "type": "option"
4194
4170
  },
4195
- "description": {
4196
- "description": "Plain-text team description (max 1500 chars)",
4197
- "name": "description",
4171
+ "team": {
4172
+ "description": "Filter by team ID (repeatable, OR logic)",
4173
+ "name": "team",
4198
4174
  "hasDynamicHelp": false,
4199
- "multiple": false,
4175
+ "multiple": true,
4200
4176
  "type": "option"
4201
4177
  },
4202
- "protocol": {
4203
- "description": "Protocol content (mermaid diagram or markdown, max 1000 words)",
4204
- "name": "protocol",
4178
+ "include": {
4179
+ "description": "Include extra fields: tags, teams (comma-separated)",
4180
+ "name": "include",
4205
4181
  "hasDynamicHelp": false,
4206
4182
  "multiple": false,
4207
4183
  "type": "option"
4208
4184
  },
4209
- "protocol-file": {
4210
- "description": "Read protocol from file",
4211
- "name": "protocol-file",
4185
+ "public": {
4186
+ "description": "Include published faces from other accounts (open to everybody)",
4187
+ "name": "public",
4188
+ "allowNo": false,
4189
+ "type": "boolean"
4190
+ },
4191
+ "shared": {
4192
+ "description": "Include faces other accounts have shared with YOU in particular",
4193
+ "name": "shared",
4194
+ "allowNo": false,
4195
+ "type": "boolean"
4196
+ },
4197
+ "system": {
4198
+ "description": "Show only the curated system faces (published faces owned by 'head')",
4199
+ "name": "system",
4200
+ "allowNo": false,
4201
+ "type": "boolean"
4202
+ },
4203
+ "from-users": {
4204
+ "description": "Only published faces from these owners (repeatable/comma-separated)",
4205
+ "name": "from-users",
4212
4206
  "hasDynamicHelp": false,
4213
- "multiple": false,
4207
+ "multiple": true,
4214
4208
  "type": "option"
4215
4209
  },
4216
- "tag": {
4217
- "description": "Tag label (repeatable, lowercase)",
4218
- "name": "tag",
4210
+ "not-from-users": {
4211
+ "description": "Exclude published faces from these owners (repeatable/comma-separated)",
4212
+ "name": "not-from-users",
4219
4213
  "hasDynamicHelp": false,
4220
4214
  "multiple": true,
4221
4215
  "type": "option"
@@ -4223,7 +4217,7 @@
4223
4217
  },
4224
4218
  "hasDynamicHelp": false,
4225
4219
  "hiddenAliases": [],
4226
- "id": "team:create",
4220
+ "id": "face:list",
4227
4221
  "pluginAlias": "faces-cli",
4228
4222
  "pluginName": "faces-cli",
4229
4223
  "pluginType": "core",
@@ -4233,20 +4227,23 @@
4233
4227
  "relativePath": [
4234
4228
  "dist",
4235
4229
  "commands",
4236
- "team",
4237
- "create.js"
4230
+ "face",
4231
+ "list.js"
4238
4232
  ]
4239
4233
  },
4240
- "team:delete": {
4234
+ "face:lock": {
4241
4235
  "aliases": [],
4242
4236
  "args": {
4243
- "team_id": {
4244
- "description": "Team ID",
4245
- "name": "team_id",
4237
+ "face_id": {
4238
+ "description": "Face alias",
4239
+ "name": "face_id",
4246
4240
  "required": true
4247
4241
  }
4248
4242
  },
4249
- "description": "Delete a team",
4243
+ "description": "Lock a face (read-only). A locked face still reads and chats normally, but it — and everything it owns (documents, threads, voiceprint) — cannot be changed until unlocked.",
4244
+ "examples": [
4245
+ "<%= config.bin %> <%= command.id %> socrates"
4246
+ ],
4250
4247
  "flags": {
4251
4248
  "json": {
4252
4249
  "description": "Format output as json.",
@@ -4278,17 +4275,11 @@
4278
4275
  "hasDynamicHelp": false,
4279
4276
  "multiple": false,
4280
4277
  "type": "option"
4281
- },
4282
- "yes": {
4283
- "description": "Skip confirmation",
4284
- "name": "yes",
4285
- "allowNo": false,
4286
- "type": "boolean"
4287
4278
  }
4288
4279
  },
4289
4280
  "hasDynamicHelp": false,
4290
4281
  "hiddenAliases": [],
4291
- "id": "team:delete",
4282
+ "id": "face:lock",
4292
4283
  "pluginAlias": "faces-cli",
4293
4284
  "pluginName": "faces-cli",
4294
4285
  "pluginType": "core",
@@ -4298,20 +4289,20 @@
4298
4289
  "relativePath": [
4299
4290
  "dist",
4300
4291
  "commands",
4301
- "team",
4302
- "delete.js"
4292
+ "face",
4293
+ "lock.js"
4303
4294
  ]
4304
4295
  },
4305
- "team:edit": {
4296
+ "face:neighbors": {
4306
4297
  "aliases": [],
4307
4298
  "args": {
4308
- "team_id": {
4309
- "description": "Team ID",
4310
- "name": "team_id",
4299
+ "face_id": {
4300
+ "description": "Face alias",
4301
+ "name": "face_id",
4311
4302
  "required": true
4312
4303
  }
4313
4304
  },
4314
- "description": "Edit a team",
4305
+ "description": "Find the most similar or dissimilar owned faces to a given face",
4315
4306
  "flags": {
4316
4307
  "json": {
4317
4308
  "description": "Format output as json.",
@@ -4344,38 +4335,38 @@
4344
4335
  "multiple": false,
4345
4336
  "type": "option"
4346
4337
  },
4347
- "name": {
4348
- "description": "New team name",
4349
- "name": "name",
4350
- "hasDynamicHelp": false,
4351
- "multiple": false,
4352
- "type": "option"
4353
- },
4354
- "description": {
4355
- "description": "New description (max 1500 chars)",
4356
- "name": "description",
4338
+ "k": {
4339
+ "description": "Number of results (1–20)",
4340
+ "name": "k",
4341
+ "default": 5,
4357
4342
  "hasDynamicHelp": false,
4358
4343
  "multiple": false,
4359
4344
  "type": "option"
4360
4345
  },
4361
- "protocol": {
4362
- "description": "New protocol content",
4363
- "name": "protocol",
4346
+ "component": {
4347
+ "description": "What to rank on: `face` for overall similarity, or a component position such as 1. Which positions are comparable varies; the API names them if you pick a wrong one.",
4348
+ "name": "component",
4349
+ "default": "face",
4364
4350
  "hasDynamicHelp": false,
4365
4351
  "multiple": false,
4366
4352
  "type": "option"
4367
4353
  },
4368
- "protocol-file": {
4369
- "description": "Read protocol from file",
4370
- "name": "protocol-file",
4354
+ "direction": {
4355
+ "description": "nearest (most similar) or furthest (most dissimilar)",
4356
+ "name": "direction",
4357
+ "default": "nearest",
4371
4358
  "hasDynamicHelp": false,
4372
4359
  "multiple": false,
4360
+ "options": [
4361
+ "nearest",
4362
+ "furthest"
4363
+ ],
4373
4364
  "type": "option"
4374
4365
  }
4375
4366
  },
4376
4367
  "hasDynamicHelp": false,
4377
4368
  "hiddenAliases": [],
4378
- "id": "team:edit",
4369
+ "id": "face:neighbors",
4379
4370
  "pluginAlias": "faces-cli",
4380
4371
  "pluginName": "faces-cli",
4381
4372
  "pluginType": "core",
@@ -4385,20 +4376,23 @@
4385
4376
  "relativePath": [
4386
4377
  "dist",
4387
4378
  "commands",
4388
- "team",
4389
- "edit.js"
4379
+ "face",
4380
+ "neighbors.js"
4390
4381
  ]
4391
4382
  },
4392
- "team:get": {
4383
+ "face:publish": {
4393
4384
  "aliases": [],
4394
4385
  "args": {
4395
- "team_id": {
4396
- "description": "Team ID",
4397
- "name": "team_id",
4386
+ "alias": {
4387
+ "description": "Face alias",
4388
+ "name": "alias",
4398
4389
  "required": true
4399
4390
  }
4400
4391
  },
4401
- "description": "Get a team by ID",
4392
+ "description": "Publish a face so EVERY account can chat with it. This is a global override: while it is on, everyone can reach the face regardless of who it is shared with. You still pay only to compile it; whoever chats pays for their own inference.",
4393
+ "examples": [
4394
+ "<%= config.bin %> <%= command.id %> alice --yes"
4395
+ ],
4402
4396
  "flags": {
4403
4397
  "json": {
4404
4398
  "description": "Format output as json.",
@@ -4430,11 +4424,17 @@
4430
4424
  "hasDynamicHelp": false,
4431
4425
  "multiple": false,
4432
4426
  "type": "option"
4427
+ },
4428
+ "yes": {
4429
+ "description": "Skip confirmation",
4430
+ "name": "yes",
4431
+ "allowNo": false,
4432
+ "type": "boolean"
4433
4433
  }
4434
4434
  },
4435
4435
  "hasDynamicHelp": false,
4436
4436
  "hiddenAliases": [],
4437
- "id": "team:get",
4437
+ "id": "face:publish",
4438
4438
  "pluginAlias": "faces-cli",
4439
4439
  "pluginName": "faces-cli",
4440
4440
  "pluginType": "core",
@@ -4444,14 +4444,26 @@
4444
4444
  "relativePath": [
4445
4445
  "dist",
4446
4446
  "commands",
4447
- "team",
4448
- "get.js"
4447
+ "face",
4448
+ "publish.js"
4449
4449
  ]
4450
4450
  },
4451
- "team:list": {
4451
+ "face:share": {
4452
4452
  "aliases": [],
4453
- "args": {},
4454
- "description": "List your teams",
4453
+ "args": {
4454
+ "alias": {
4455
+ "description": "Face alias",
4456
+ "name": "alias",
4457
+ "required": true
4458
+ }
4459
+ },
4460
+ "description": "Share a face so named accounts can chat with it. Sharing grants chat and nothing else: no reading its documents, no compiling, no re-sharing, and never its profile addendum. --add keeps the current list; --with replaces it.",
4461
+ "examples": [
4462
+ "<%= config.bin %> <%= command.id %> alice --list",
4463
+ "<%= config.bin %> <%= command.id %> alice --add dana",
4464
+ "<%= config.bin %> <%= command.id %> alice --with dana --with sam@example.com",
4465
+ "<%= config.bin %> <%= command.id %> alice --none --yes"
4466
+ ],
4455
4467
  "flags": {
4456
4468
  "json": {
4457
4469
  "description": "Format output as json.",
@@ -4483,11 +4495,55 @@
4483
4495
  "hasDynamicHelp": false,
4484
4496
  "multiple": false,
4485
4497
  "type": "option"
4498
+ },
4499
+ "list": {
4500
+ "description": "Show who the face is shared with, and change nothing",
4501
+ "name": "list",
4502
+ "allowNo": false,
4503
+ "type": "boolean"
4504
+ },
4505
+ "add": {
4506
+ "description": "Add an account, keeping everyone already on the list — username or email (repeatable)",
4507
+ "exclusive": [
4508
+ "with",
4509
+ "none"
4510
+ ],
4511
+ "name": "add",
4512
+ "hasDynamicHelp": false,
4513
+ "multiple": true,
4514
+ "type": "option"
4515
+ },
4516
+ "with": {
4517
+ "description": "Set the list to exactly these accounts, dropping anyone else (repeatable)",
4518
+ "exclusive": [
4519
+ "add",
4520
+ "none"
4521
+ ],
4522
+ "name": "with",
4523
+ "hasDynamicHelp": false,
4524
+ "multiple": true,
4525
+ "type": "option"
4526
+ },
4527
+ "none": {
4528
+ "description": "Revoke everyone",
4529
+ "exclusive": [
4530
+ "add",
4531
+ "with"
4532
+ ],
4533
+ "name": "none",
4534
+ "allowNo": false,
4535
+ "type": "boolean"
4536
+ },
4537
+ "yes": {
4538
+ "description": "Skip the confirmation shown when someone would lose access",
4539
+ "name": "yes",
4540
+ "allowNo": false,
4541
+ "type": "boolean"
4486
4542
  }
4487
4543
  },
4488
4544
  "hasDynamicHelp": false,
4489
4545
  "hiddenAliases": [],
4490
- "id": "team:list",
4546
+ "id": "face:share",
4491
4547
  "pluginAlias": "faces-cli",
4492
4548
  "pluginName": "faces-cli",
4493
4549
  "pluginType": "core",
@@ -4497,20 +4553,25 @@
4497
4553
  "relativePath": [
4498
4554
  "dist",
4499
4555
  "commands",
4500
- "team",
4501
- "list.js"
4556
+ "face",
4557
+ "share.js"
4502
4558
  ]
4503
4559
  },
4504
- "team:members": {
4560
+ "face:sources": {
4505
4561
  "aliases": [],
4506
4562
  "args": {
4507
- "team_id": {
4508
- "description": "Team ID",
4509
- "name": "team_id",
4563
+ "alias": {
4564
+ "description": "Face alias",
4565
+ "name": "alias",
4510
4566
  "required": true
4511
4567
  }
4512
4568
  },
4513
- "description": "List members of a team",
4569
+ "description": "List every source compiled into a face: documents and threads together, one row each. Exits 4 if the face does not exist, which is a different answer from a face that has no sources. Content is never printed; read a single source with compile:doc:get or compile:thread:get.",
4570
+ "examples": [
4571
+ "<%= config.bin %> <%= command.id %> alice",
4572
+ "<%= config.bin %> <%= command.id %> alice --type thread",
4573
+ "<%= config.bin %> <%= command.id %> alice --json"
4574
+ ],
4514
4575
  "flags": {
4515
4576
  "json": {
4516
4577
  "description": "Format output as json.",
@@ -4542,11 +4603,22 @@
4542
4603
  "hasDynamicHelp": false,
4543
4604
  "multiple": false,
4544
4605
  "type": "option"
4606
+ },
4607
+ "type": {
4608
+ "description": "Show only one kind of source",
4609
+ "name": "type",
4610
+ "hasDynamicHelp": false,
4611
+ "multiple": false,
4612
+ "options": [
4613
+ "doc",
4614
+ "thread"
4615
+ ],
4616
+ "type": "option"
4545
4617
  }
4546
4618
  },
4547
4619
  "hasDynamicHelp": false,
4548
4620
  "hiddenAliases": [],
4549
- "id": "team:members",
4621
+ "id": "face:sources",
4550
4622
  "pluginAlias": "faces-cli",
4551
4623
  "pluginName": "faces-cli",
4552
4624
  "pluginType": "core",
@@ -4556,25 +4628,14 @@
4556
4628
  "relativePath": [
4557
4629
  "dist",
4558
4630
  "commands",
4559
- "team",
4560
- "members.js"
4631
+ "face",
4632
+ "sources.js"
4561
4633
  ]
4562
4634
  },
4563
- "team:remove": {
4635
+ "face:stats": {
4564
4636
  "aliases": [],
4565
- "args": {
4566
- "team_id": {
4567
- "description": "Team ID",
4568
- "name": "team_id",
4569
- "required": true
4570
- },
4571
- "alias": {
4572
- "description": "Face alias to remove",
4573
- "name": "alias",
4574
- "required": true
4575
- }
4576
- },
4577
- "description": "Remove a face from a team",
4637
+ "args": {},
4638
+ "description": "Compile and chat stats for all owned faces",
4578
4639
  "flags": {
4579
4640
  "json": {
4580
4641
  "description": "Format output as json.",
@@ -4610,7 +4671,7 @@
4610
4671
  },
4611
4672
  "hasDynamicHelp": false,
4612
4673
  "hiddenAliases": [],
4613
- "id": "team:remove",
4674
+ "id": "face:stats",
4614
4675
  "pluginAlias": "faces-cli",
4615
4676
  "pluginName": "faces-cli",
4616
4677
  "pluginType": "core",
@@ -4620,14 +4681,20 @@
4620
4681
  "relativePath": [
4621
4682
  "dist",
4622
4683
  "commands",
4623
- "team",
4624
- "remove.js"
4684
+ "face",
4685
+ "stats.js"
4625
4686
  ]
4626
4687
  },
4627
- "compile:all": {
4688
+ "face:teams": {
4628
4689
  "aliases": [],
4629
- "args": {},
4630
- "description": "Compile all uncompiled documents and threads across all faces",
4690
+ "args": {
4691
+ "alias": {
4692
+ "description": "Face alias",
4693
+ "name": "alias",
4694
+ "required": true
4695
+ }
4696
+ },
4697
+ "description": "Set a face's team memberships (replaces all)",
4631
4698
  "flags": {
4632
4699
  "json": {
4633
4700
  "description": "Format output as json.",
@@ -4660,18 +4727,18 @@
4660
4727
  "multiple": false,
4661
4728
  "type": "option"
4662
4729
  },
4663
- "timeout": {
4664
- "description": "Per-item compile timeout in seconds (default: 600)",
4665
- "name": "timeout",
4666
- "default": 600,
4730
+ "team": {
4731
+ "description": "Team ID (repeatable, replaces all memberships)",
4732
+ "name": "team",
4733
+ "required": true,
4667
4734
  "hasDynamicHelp": false,
4668
- "multiple": false,
4735
+ "multiple": true,
4669
4736
  "type": "option"
4670
4737
  }
4671
4738
  },
4672
4739
  "hasDynamicHelp": false,
4673
4740
  "hiddenAliases": [],
4674
- "id": "compile:all",
4741
+ "id": "face:teams",
4675
4742
  "pluginAlias": "faces-cli",
4676
4743
  "pluginName": "faces-cli",
4677
4744
  "pluginType": "core",
@@ -4681,11 +4748,11 @@
4681
4748
  "relativePath": [
4682
4749
  "dist",
4683
4750
  "commands",
4684
- "compile",
4685
- "all.js"
4751
+ "face",
4752
+ "teams.js"
4686
4753
  ]
4687
4754
  },
4688
- "compile:import": {
4755
+ "face:unlock": {
4689
4756
  "aliases": [],
4690
4757
  "args": {
4691
4758
  "face_id": {
@@ -4694,7 +4761,10 @@
4694
4761
  "required": true
4695
4762
  }
4696
4763
  },
4697
- "description": "Import a YouTube video into a face via server-side download and transcription",
4764
+ "description": "Unlock a face (make it writable again). Thaws the face and everything it owns (documents, threads, voiceprint).",
4765
+ "examples": [
4766
+ "<%= config.bin %> <%= command.id %> socrates"
4767
+ ],
4698
4768
  "flags": {
4699
4769
  "json": {
4700
4770
  "description": "Format output as json.",
@@ -4726,56 +4796,11 @@
4726
4796
  "hasDynamicHelp": false,
4727
4797
  "multiple": false,
4728
4798
  "type": "option"
4729
- },
4730
- "url": {
4731
- "description": "YouTube URL (youtube.com/watch?v=... or youtu.be/...)",
4732
- "name": "url",
4733
- "required": true,
4734
- "hasDynamicHelp": false,
4735
- "multiple": false,
4736
- "type": "option"
4737
- },
4738
- "type": {
4739
- "description": "\"document\" for solo talks, lectures, monologues; \"thread\" for interviews or multi-speaker conversations",
4740
- "name": "type",
4741
- "default": "document",
4742
- "hasDynamicHelp": false,
4743
- "multiple": false,
4744
- "options": [
4745
- "document",
4746
- "thread"
4747
- ],
4748
- "type": "option"
4749
- },
4750
- "perspective": {
4751
- "description": "\"first-person\" if the face is the speaker; \"third-person\" if the video is about the face",
4752
- "name": "perspective",
4753
- "default": "third-person",
4754
- "hasDynamicHelp": false,
4755
- "multiple": false,
4756
- "options": [
4757
- "first-person",
4758
- "third-person"
4759
- ],
4760
- "type": "option"
4761
- },
4762
- "face-speaker": {
4763
- "description": "For --type thread: AssemblyAI speaker label (e.g. \"A\") that corresponds to the face. Defaults to first detected speaker.",
4764
- "name": "face-speaker",
4765
- "hasDynamicHelp": false,
4766
- "multiple": false,
4767
- "type": "option"
4768
- },
4769
- "no-wait": {
4770
- "description": "Return immediately after import starts (do not poll for transcription). Prints the ID for manual polling.",
4771
- "name": "no-wait",
4772
- "allowNo": false,
4773
- "type": "boolean"
4774
4799
  }
4775
4800
  },
4776
4801
  "hasDynamicHelp": false,
4777
4802
  "hiddenAliases": [],
4778
- "id": "compile:import",
4803
+ "id": "face:unlock",
4779
4804
  "pluginAlias": "faces-cli",
4780
4805
  "pluginName": "faces-cli",
4781
4806
  "pluginType": "core",
@@ -4785,14 +4810,20 @@
4785
4810
  "relativePath": [
4786
4811
  "dist",
4787
4812
  "commands",
4788
- "compile",
4789
- "import.js"
4813
+ "face",
4814
+ "unlock.js"
4790
4815
  ]
4791
4816
  },
4792
- "compile:stats": {
4817
+ "face:unpublish": {
4793
4818
  "aliases": [],
4794
- "args": {},
4795
- "description": "Show compilation stats per face",
4819
+ "args": {
4820
+ "alias": {
4821
+ "description": "Face alias",
4822
+ "name": "alias",
4823
+ "required": true
4824
+ }
4825
+ },
4826
+ "description": "Stop publishing a face. Anyone it is individually shared with keeps their access — publishing is an override on top of sharing, not a replacement for it.",
4796
4827
  "flags": {
4797
4828
  "json": {
4798
4829
  "description": "Format output as json.",
@@ -4828,7 +4859,7 @@
4828
4859
  },
4829
4860
  "hasDynamicHelp": false,
4830
4861
  "hiddenAliases": [],
4831
- "id": "compile:stats",
4862
+ "id": "face:unpublish",
4832
4863
  "pluginAlias": "faces-cli",
4833
4864
  "pluginName": "faces-cli",
4834
4865
  "pluginType": "core",
@@ -4838,11 +4869,11 @@
4838
4869
  "relativePath": [
4839
4870
  "dist",
4840
4871
  "commands",
4841
- "compile",
4842
- "stats.js"
4872
+ "face",
4873
+ "unpublish.js"
4843
4874
  ]
4844
4875
  },
4845
- "compile:upload": {
4876
+ "face:unshare": {
4846
4877
  "aliases": [],
4847
4878
  "args": {
4848
4879
  "alias": {
@@ -4851,7 +4882,11 @@
4851
4882
  "required": true
4852
4883
  }
4853
4884
  },
4854
- "description": "Upload a file (text/PDF/Word .docx/audio/video) to compile into a face",
4885
+ "description": "Revoke access to a shared face. Takes effect immediately there is no grace period.",
4886
+ "examples": [
4887
+ "<%= config.bin %> <%= command.id %> alice --from dana --yes",
4888
+ "<%= config.bin %> <%= command.id %> alice --all --yes"
4889
+ ],
4855
4890
  "flags": {
4856
4891
  "json": {
4857
4892
  "description": "Format output as json.",
@@ -4860,86 +4895,59 @@
4860
4895
  "allowNo": false,
4861
4896
  "type": "boolean"
4862
4897
  },
4863
- "base-url": {
4864
- "description": "API base URL",
4865
- "env": "FACES_BASE_URL",
4866
- "name": "base-url",
4867
- "hasDynamicHelp": false,
4868
- "multiple": false,
4869
- "type": "option"
4870
- },
4871
- "token": {
4872
- "description": "JWT bearer token",
4873
- "env": "FACES_TOKEN",
4874
- "name": "token",
4875
- "hasDynamicHelp": false,
4876
- "multiple": false,
4877
- "type": "option"
4878
- },
4879
- "api-key": {
4880
- "description": "API key",
4881
- "env": "FACES_API_KEY",
4882
- "name": "api-key",
4883
- "hasDynamicHelp": false,
4884
- "multiple": false,
4885
- "type": "option"
4886
- },
4887
- "file": {
4888
- "description": "File to upload",
4889
- "name": "file",
4890
- "required": true,
4891
- "hasDynamicHelp": false,
4892
- "multiple": false,
4893
- "type": "option"
4894
- },
4895
- "kind": {
4896
- "description": "Upload kind: document or thread",
4897
- "name": "kind",
4898
- "default": "document",
4898
+ "base-url": {
4899
+ "description": "API base URL",
4900
+ "env": "FACES_BASE_URL",
4901
+ "name": "base-url",
4899
4902
  "hasDynamicHelp": false,
4900
4903
  "multiple": false,
4901
- "options": [
4902
- "document",
4903
- "thread"
4904
- ],
4905
4904
  "type": "option"
4906
4905
  },
4907
- "perspective": {
4908
- "description": "Perspective (document only)",
4909
- "name": "perspective",
4910
- "default": "third-person",
4906
+ "token": {
4907
+ "description": "JWT bearer token",
4908
+ "env": "FACES_TOKEN",
4909
+ "name": "token",
4911
4910
  "hasDynamicHelp": false,
4912
4911
  "multiple": false,
4913
- "options": [
4914
- "first-person",
4915
- "third-person"
4916
- ],
4917
4912
  "type": "option"
4918
4913
  },
4919
- "medium": {
4920
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not. Only valid with --kind document.",
4921
- "name": "medium",
4914
+ "api-key": {
4915
+ "description": "API key",
4916
+ "env": "FACES_API_KEY",
4917
+ "name": "api-key",
4922
4918
  "hasDynamicHelp": false,
4923
4919
  "multiple": false,
4924
4920
  "type": "option"
4925
4921
  },
4926
- "face-speaker": {
4927
- "description": "Speaker name to map to the face (thread only). If omitted, auto-detected from face name.",
4928
- "name": "face-speaker",
4922
+ "from": {
4923
+ "description": "Account to revoke (repeatable)",
4924
+ "exclusive": [
4925
+ "all"
4926
+ ],
4927
+ "name": "from",
4929
4928
  "hasDynamicHelp": false,
4930
- "multiple": false,
4929
+ "multiple": true,
4931
4930
  "type": "option"
4932
4931
  },
4933
- "no-wait": {
4934
- "description": "Return immediately after upload (do not poll for transcription). Prints the ID for manual polling.",
4935
- "name": "no-wait",
4932
+ "all": {
4933
+ "description": "Revoke everyone",
4934
+ "exclusive": [
4935
+ "from"
4936
+ ],
4937
+ "name": "all",
4938
+ "allowNo": false,
4939
+ "type": "boolean"
4940
+ },
4941
+ "yes": {
4942
+ "description": "Skip confirmation",
4943
+ "name": "yes",
4936
4944
  "allowNo": false,
4937
4945
  "type": "boolean"
4938
4946
  }
4939
4947
  },
4940
4948
  "hasDynamicHelp": false,
4941
4949
  "hiddenAliases": [],
4942
- "id": "compile:upload",
4950
+ "id": "face:unshare",
4943
4951
  "pluginAlias": "faces-cli",
4944
4952
  "pluginName": "faces-cli",
4945
4953
  "pluginType": "core",
@@ -4949,8 +4957,8 @@
4949
4957
  "relativePath": [
4950
4958
  "dist",
4951
4959
  "commands",
4952
- "compile",
4953
- "upload.js"
4960
+ "face",
4961
+ "unshare.js"
4954
4962
  ]
4955
4963
  },
4956
4964
  "billing:subscription:activate": {
@@ -5132,16 +5140,16 @@
5132
5140
  "index.js"
5133
5141
  ]
5134
5142
  },
5135
- "face:tag:add": {
5143
+ "compile:doc:create": {
5136
5144
  "aliases": [],
5137
5145
  "args": {
5138
- "alias": {
5146
+ "face_id": {
5139
5147
  "description": "Face alias",
5140
- "name": "alias",
5148
+ "name": "face_id",
5141
5149
  "required": true
5142
5150
  }
5143
5151
  },
5144
- "description": "Add tags to a face (appends, idempotent)",
5152
+ "description": "Submit a document to a face",
5145
5153
  "flags": {
5146
5154
  "json": {
5147
5155
  "description": "Format output as json.",
@@ -5174,18 +5182,50 @@
5174
5182
  "multiple": false,
5175
5183
  "type": "option"
5176
5184
  },
5177
- "tag": {
5178
- "description": "Tag to add (repeatable)",
5179
- "name": "tag",
5180
- "required": true,
5185
+ "label": {
5186
+ "description": "Document label/title",
5187
+ "name": "label",
5181
5188
  "hasDynamicHelp": false,
5182
- "multiple": true,
5189
+ "multiple": false,
5190
+ "type": "option"
5191
+ },
5192
+ "content": {
5193
+ "description": "Inline text content",
5194
+ "name": "content",
5195
+ "hasDynamicHelp": false,
5196
+ "multiple": false,
5197
+ "type": "option"
5198
+ },
5199
+ "file": {
5200
+ "description": "Read content from file",
5201
+ "name": "file",
5202
+ "hasDynamicHelp": false,
5203
+ "multiple": false,
5204
+ "type": "option"
5205
+ },
5206
+ "medium": {
5207
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5208
+ "name": "medium",
5209
+ "hasDynamicHelp": false,
5210
+ "multiple": false,
5211
+ "type": "option"
5212
+ },
5213
+ "perspective": {
5214
+ "description": "Perspective (first-person or third-person)",
5215
+ "name": "perspective",
5216
+ "default": "first-person",
5217
+ "hasDynamicHelp": false,
5218
+ "multiple": false,
5219
+ "options": [
5220
+ "first-person",
5221
+ "third-person"
5222
+ ],
5183
5223
  "type": "option"
5184
5224
  }
5185
5225
  },
5186
5226
  "hasDynamicHelp": false,
5187
5227
  "hiddenAliases": [],
5188
- "id": "face:tag:add",
5228
+ "id": "compile:doc:create",
5189
5229
  "pluginAlias": "faces-cli",
5190
5230
  "pluginName": "faces-cli",
5191
5231
  "pluginType": "core",
@@ -5195,15 +5235,21 @@
5195
5235
  "relativePath": [
5196
5236
  "dist",
5197
5237
  "commands",
5198
- "face",
5199
- "tag",
5200
- "add.js"
5238
+ "compile",
5239
+ "doc",
5240
+ "create.js"
5201
5241
  ]
5202
5242
  },
5203
- "face:tag:all": {
5243
+ "compile:doc:delete": {
5204
5244
  "aliases": [],
5205
- "args": {},
5206
- "description": "List all tags across all your faces",
5245
+ "args": {
5246
+ "doc_id": {
5247
+ "description": "Document ID",
5248
+ "name": "doc_id",
5249
+ "required": true
5250
+ }
5251
+ },
5252
+ "description": "Delete a document",
5207
5253
  "flags": {
5208
5254
  "json": {
5209
5255
  "description": "Format output as json.",
@@ -5239,7 +5285,7 @@
5239
5285
  },
5240
5286
  "hasDynamicHelp": false,
5241
5287
  "hiddenAliases": [],
5242
- "id": "face:tag:all",
5288
+ "id": "compile:doc:delete",
5243
5289
  "pluginAlias": "faces-cli",
5244
5290
  "pluginName": "faces-cli",
5245
5291
  "pluginType": "core",
@@ -5249,21 +5295,21 @@
5249
5295
  "relativePath": [
5250
5296
  "dist",
5251
5297
  "commands",
5252
- "face",
5253
- "tag",
5254
- "all.js"
5298
+ "compile",
5299
+ "doc",
5300
+ "delete.js"
5255
5301
  ]
5256
5302
  },
5257
- "face:tag:list": {
5303
+ "compile:doc:edit": {
5258
5304
  "aliases": [],
5259
5305
  "args": {
5260
- "alias": {
5261
- "description": "Face alias",
5262
- "name": "alias",
5306
+ "doc_id": {
5307
+ "description": "Document ID",
5308
+ "name": "doc_id",
5263
5309
  "required": true
5264
5310
  }
5265
5311
  },
5266
- "description": "List tags on a face",
5312
+ "description": "Edit a document (label, content, or perspective)",
5267
5313
  "flags": {
5268
5314
  "json": {
5269
5315
  "description": "Format output as json.",
@@ -5295,11 +5341,50 @@
5295
5341
  "hasDynamicHelp": false,
5296
5342
  "multiple": false,
5297
5343
  "type": "option"
5344
+ },
5345
+ "label": {
5346
+ "description": "New label/title",
5347
+ "name": "label",
5348
+ "hasDynamicHelp": false,
5349
+ "multiple": false,
5350
+ "type": "option"
5351
+ },
5352
+ "content": {
5353
+ "description": "New inline text content",
5354
+ "name": "content",
5355
+ "hasDynamicHelp": false,
5356
+ "multiple": false,
5357
+ "type": "option"
5358
+ },
5359
+ "file": {
5360
+ "description": "Read new content from file",
5361
+ "name": "file",
5362
+ "hasDynamicHelp": false,
5363
+ "multiple": false,
5364
+ "type": "option"
5365
+ },
5366
+ "medium": {
5367
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5368
+ "name": "medium",
5369
+ "hasDynamicHelp": false,
5370
+ "multiple": false,
5371
+ "type": "option"
5372
+ },
5373
+ "perspective": {
5374
+ "description": "Perspective (first-person or third-person)",
5375
+ "name": "perspective",
5376
+ "hasDynamicHelp": false,
5377
+ "multiple": false,
5378
+ "options": [
5379
+ "first-person",
5380
+ "third-person"
5381
+ ],
5382
+ "type": "option"
5298
5383
  }
5299
5384
  },
5300
5385
  "hasDynamicHelp": false,
5301
5386
  "hiddenAliases": [],
5302
- "id": "face:tag:list",
5387
+ "id": "compile:doc:edit",
5303
5388
  "pluginAlias": "faces-cli",
5304
5389
  "pluginName": "faces-cli",
5305
5390
  "pluginType": "core",
@@ -5309,26 +5394,21 @@
5309
5394
  "relativePath": [
5310
5395
  "dist",
5311
5396
  "commands",
5312
- "face",
5313
- "tag",
5314
- "list.js"
5397
+ "compile",
5398
+ "doc",
5399
+ "edit.js"
5315
5400
  ]
5316
5401
  },
5317
- "face:tag:remove": {
5402
+ "compile:doc:get": {
5318
5403
  "aliases": [],
5319
5404
  "args": {
5320
- "alias": {
5321
- "description": "Face alias",
5322
- "name": "alias",
5323
- "required": true
5324
- },
5325
- "tag": {
5326
- "description": "Tag to remove",
5327
- "name": "tag",
5405
+ "doc_id": {
5406
+ "description": "Document ID",
5407
+ "name": "doc_id",
5328
5408
  "required": true
5329
5409
  }
5330
5410
  },
5331
- "description": "Remove a tag from a face",
5411
+ "description": "Get a document by ID",
5332
5412
  "flags": {
5333
5413
  "json": {
5334
5414
  "description": "Format output as json.",
@@ -5364,7 +5444,7 @@
5364
5444
  },
5365
5445
  "hasDynamicHelp": false,
5366
5446
  "hiddenAliases": [],
5367
- "id": "face:tag:remove",
5447
+ "id": "compile:doc:get",
5368
5448
  "pluginAlias": "faces-cli",
5369
5449
  "pluginName": "faces-cli",
5370
5450
  "pluginType": "core",
@@ -5374,21 +5454,25 @@
5374
5454
  "relativePath": [
5375
5455
  "dist",
5376
5456
  "commands",
5377
- "face",
5378
- "tag",
5379
- "remove.js"
5457
+ "compile",
5458
+ "doc",
5459
+ "get.js"
5380
5460
  ]
5381
5461
  },
5382
- "face:tag:set": {
5462
+ "compile:doc": {
5383
5463
  "aliases": [],
5384
5464
  "args": {
5385
- "alias": {
5465
+ "face_id": {
5386
5466
  "description": "Face alias",
5387
- "name": "alias",
5467
+ "name": "face_id",
5388
5468
  "required": true
5389
5469
  }
5390
5470
  },
5391
- "description": "Replace all tags on a face",
5471
+ "description": "Compile one or more documents into a face (create → make in one step). Repeat --file to submit several documents in a single command; each file becomes its own document rather than being concatenated.",
5472
+ "examples": [
5473
+ "<%= config.bin %> <%= command.id %> alice --file notes.txt",
5474
+ "<%= config.bin %> <%= command.id %> alice --file a.txt --file b.txt --file c.txt --no-wait --json"
5475
+ ],
5392
5476
  "flags": {
5393
5477
  "json": {
5394
5478
  "description": "Format output as json.",
@@ -5405,34 +5489,83 @@
5405
5489
  "multiple": false,
5406
5490
  "type": "option"
5407
5491
  },
5408
- "token": {
5409
- "description": "JWT bearer token",
5410
- "env": "FACES_TOKEN",
5411
- "name": "token",
5492
+ "token": {
5493
+ "description": "JWT bearer token",
5494
+ "env": "FACES_TOKEN",
5495
+ "name": "token",
5496
+ "hasDynamicHelp": false,
5497
+ "multiple": false,
5498
+ "type": "option"
5499
+ },
5500
+ "api-key": {
5501
+ "description": "API key",
5502
+ "env": "FACES_API_KEY",
5503
+ "name": "api-key",
5504
+ "hasDynamicHelp": false,
5505
+ "multiple": false,
5506
+ "type": "option"
5507
+ },
5508
+ "label": {
5509
+ "description": "Document label/title (single document only; with several files each is labelled by its filename)",
5510
+ "name": "label",
5511
+ "hasDynamicHelp": false,
5512
+ "multiple": false,
5513
+ "type": "option"
5514
+ },
5515
+ "content": {
5516
+ "description": "Inline text content",
5517
+ "exclusive": [
5518
+ "file"
5519
+ ],
5520
+ "name": "content",
5521
+ "hasDynamicHelp": false,
5522
+ "multiple": false,
5523
+ "type": "option"
5524
+ },
5525
+ "file": {
5526
+ "description": "Read content from file (repeatable — each file becomes its own document)",
5527
+ "name": "file",
5528
+ "hasDynamicHelp": false,
5529
+ "multiple": true,
5530
+ "type": "option"
5531
+ },
5532
+ "medium": {
5533
+ "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (dialogue: transcripts, interviews, calls), lecture (sustained speech nobody interrupts: talks, sermons, keynotes). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5534
+ "name": "medium",
5412
5535
  "hasDynamicHelp": false,
5413
5536
  "multiple": false,
5414
5537
  "type": "option"
5415
5538
  },
5416
- "api-key": {
5417
- "description": "API key",
5418
- "env": "FACES_API_KEY",
5419
- "name": "api-key",
5539
+ "perspective": {
5540
+ "description": "Perspective",
5541
+ "name": "perspective",
5542
+ "default": "first-person",
5420
5543
  "hasDynamicHelp": false,
5421
5544
  "multiple": false,
5545
+ "options": [
5546
+ "first-person",
5547
+ "third-person"
5548
+ ],
5422
5549
  "type": "option"
5423
5550
  },
5424
- "tag": {
5425
- "description": "Tag to set (repeatable, replaces all)",
5426
- "name": "tag",
5427
- "required": true,
5551
+ "timeout": {
5552
+ "description": "Compile timeout in seconds, per document (default: 600)",
5553
+ "name": "timeout",
5554
+ "default": 600,
5428
5555
  "hasDynamicHelp": false,
5429
- "multiple": true,
5556
+ "multiple": false,
5430
5557
  "type": "option"
5558
+ },
5559
+ "no-wait": {
5560
+ "description": "Create and trigger compilation, then return immediately without polling.",
5561
+ "name": "no-wait",
5562
+ "allowNo": false,
5563
+ "type": "boolean"
5431
5564
  }
5432
5565
  },
5433
5566
  "hasDynamicHelp": false,
5434
5567
  "hiddenAliases": [],
5435
- "id": "face:tag:set",
5568
+ "id": "compile:doc",
5436
5569
  "pluginAlias": "faces-cli",
5437
5570
  "pluginName": "faces-cli",
5438
5571
  "pluginType": "core",
@@ -5442,21 +5575,21 @@
5442
5575
  "relativePath": [
5443
5576
  "dist",
5444
5577
  "commands",
5445
- "face",
5446
- "tag",
5447
- "set.js"
5578
+ "compile",
5579
+ "doc",
5580
+ "index.js"
5448
5581
  ]
5449
5582
  },
5450
- "team:tag:add": {
5583
+ "compile:doc:list": {
5451
5584
  "aliases": [],
5452
5585
  "args": {
5453
- "team_id": {
5454
- "description": "Team ID",
5455
- "name": "team_id",
5586
+ "face_id": {
5587
+ "description": "Face alias",
5588
+ "name": "face_id",
5456
5589
  "required": true
5457
5590
  }
5458
5591
  },
5459
- "description": "Add tags to a team (appends, idempotent)",
5592
+ "description": "List documents for a face. Each document's full text is omitted unless --verbose, so a face with a real corpus stays readable. For a table of every source, documents and threads together, use face:sources.",
5460
5593
  "flags": {
5461
5594
  "json": {
5462
5595
  "description": "Format output as json.",
@@ -5489,18 +5622,16 @@
5489
5622
  "multiple": false,
5490
5623
  "type": "option"
5491
5624
  },
5492
- "tag": {
5493
- "description": "Tag to add (repeatable)",
5494
- "name": "tag",
5495
- "required": true,
5496
- "hasDynamicHelp": false,
5497
- "multiple": true,
5498
- "type": "option"
5625
+ "verbose": {
5626
+ "description": "Include each document's full text",
5627
+ "name": "verbose",
5628
+ "allowNo": false,
5629
+ "type": "boolean"
5499
5630
  }
5500
5631
  },
5501
5632
  "hasDynamicHelp": false,
5502
5633
  "hiddenAliases": [],
5503
- "id": "team:tag:add",
5634
+ "id": "compile:doc:list",
5504
5635
  "pluginAlias": "faces-cli",
5505
5636
  "pluginName": "faces-cli",
5506
5637
  "pluginType": "core",
@@ -5510,21 +5641,21 @@
5510
5641
  "relativePath": [
5511
5642
  "dist",
5512
5643
  "commands",
5513
- "team",
5514
- "tag",
5515
- "add.js"
5644
+ "compile",
5645
+ "doc",
5646
+ "list.js"
5516
5647
  ]
5517
5648
  },
5518
- "team:tag:list": {
5649
+ "compile:doc:make": {
5519
5650
  "aliases": [],
5520
5651
  "args": {
5521
- "team_id": {
5522
- "description": "Team ID",
5523
- "name": "team_id",
5652
+ "doc_id": {
5653
+ "description": "Document ID",
5654
+ "name": "doc_id",
5524
5655
  "required": true
5525
5656
  }
5526
5657
  },
5527
- "description": "List tags on a team",
5658
+ "description": "Compile an existing document (prepare + sync in one step)",
5528
5659
  "flags": {
5529
5660
  "json": {
5530
5661
  "description": "Format output as json.",
@@ -5556,11 +5687,25 @@
5556
5687
  "hasDynamicHelp": false,
5557
5688
  "multiple": false,
5558
5689
  "type": "option"
5690
+ },
5691
+ "timeout": {
5692
+ "description": "Compile timeout in seconds (default: 600)",
5693
+ "name": "timeout",
5694
+ "default": 600,
5695
+ "hasDynamicHelp": false,
5696
+ "multiple": false,
5697
+ "type": "option"
5698
+ },
5699
+ "no-wait": {
5700
+ "description": "Return immediately after triggering compilation. Prints the document ID for manual polling.",
5701
+ "name": "no-wait",
5702
+ "allowNo": false,
5703
+ "type": "boolean"
5559
5704
  }
5560
5705
  },
5561
5706
  "hasDynamicHelp": false,
5562
5707
  "hiddenAliases": [],
5563
- "id": "team:tag:list",
5708
+ "id": "compile:doc:make",
5564
5709
  "pluginAlias": "faces-cli",
5565
5710
  "pluginName": "faces-cli",
5566
5711
  "pluginType": "core",
@@ -5570,26 +5715,21 @@
5570
5715
  "relativePath": [
5571
5716
  "dist",
5572
5717
  "commands",
5573
- "team",
5574
- "tag",
5575
- "list.js"
5718
+ "compile",
5719
+ "doc",
5720
+ "make.js"
5576
5721
  ]
5577
5722
  },
5578
- "team:tag:remove": {
5723
+ "compile:doc:pause": {
5579
5724
  "aliases": [],
5580
5725
  "args": {
5581
- "team_id": {
5582
- "description": "Team ID",
5583
- "name": "team_id",
5584
- "required": true
5585
- },
5586
- "tag": {
5587
- "description": "Tag to remove",
5588
- "name": "tag",
5726
+ "doc_id": {
5727
+ "description": "Document ID",
5728
+ "name": "doc_id",
5589
5729
  "required": true
5590
5730
  }
5591
5731
  },
5592
- "description": "Remove a tag from a team",
5732
+ "description": "Ask a running document compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
5593
5733
  "flags": {
5594
5734
  "json": {
5595
5735
  "description": "Format output as json.",
@@ -5621,11 +5761,25 @@
5621
5761
  "hasDynamicHelp": false,
5622
5762
  "multiple": false,
5623
5763
  "type": "option"
5764
+ },
5765
+ "no-wait": {
5766
+ "description": "Return as soon as the pause is accepted, without waiting for the compile to stop.",
5767
+ "name": "no-wait",
5768
+ "allowNo": false,
5769
+ "type": "boolean"
5770
+ },
5771
+ "timeout": {
5772
+ "description": "Seconds to wait for the compile to stop (default: 60)",
5773
+ "name": "timeout",
5774
+ "default": 60,
5775
+ "hasDynamicHelp": false,
5776
+ "multiple": false,
5777
+ "type": "option"
5624
5778
  }
5625
5779
  },
5626
5780
  "hasDynamicHelp": false,
5627
5781
  "hiddenAliases": [],
5628
- "id": "team:tag:remove",
5782
+ "id": "compile:doc:pause",
5629
5783
  "pluginAlias": "faces-cli",
5630
5784
  "pluginName": "faces-cli",
5631
5785
  "pluginType": "core",
@@ -5635,21 +5789,21 @@
5635
5789
  "relativePath": [
5636
5790
  "dist",
5637
5791
  "commands",
5638
- "team",
5639
- "tag",
5640
- "remove.js"
5792
+ "compile",
5793
+ "doc",
5794
+ "pause.js"
5641
5795
  ]
5642
5796
  },
5643
- "team:tag:set": {
5797
+ "compile:doc:reset": {
5644
5798
  "aliases": [],
5645
5799
  "args": {
5646
- "team_id": {
5647
- "description": "Team ID",
5648
- "name": "team_id",
5800
+ "doc_id": {
5801
+ "description": "Document ID",
5802
+ "name": "doc_id",
5649
5803
  "required": true
5650
5804
  }
5651
5805
  },
5652
- "description": "Replace all tags on a team",
5806
+ "description": "Reset document compilation progress (wipe extraction, keep content)",
5653
5807
  "flags": {
5654
5808
  "json": {
5655
5809
  "description": "Format output as json.",
@@ -5682,18 +5836,16 @@
5682
5836
  "multiple": false,
5683
5837
  "type": "option"
5684
5838
  },
5685
- "tag": {
5686
- "description": "Tag to set (repeatable, replaces all)",
5687
- "name": "tag",
5688
- "required": true,
5689
- "hasDynamicHelp": false,
5690
- "multiple": true,
5691
- "type": "option"
5839
+ "yes": {
5840
+ "description": "Skip confirmation",
5841
+ "name": "yes",
5842
+ "allowNo": false,
5843
+ "type": "boolean"
5692
5844
  }
5693
5845
  },
5694
5846
  "hasDynamicHelp": false,
5695
5847
  "hiddenAliases": [],
5696
- "id": "team:tag:set",
5848
+ "id": "compile:doc:reset",
5697
5849
  "pluginAlias": "faces-cli",
5698
5850
  "pluginName": "faces-cli",
5699
5851
  "pluginType": "core",
@@ -5703,12 +5855,12 @@
5703
5855
  "relativePath": [
5704
5856
  "dist",
5705
5857
  "commands",
5706
- "team",
5707
- "tag",
5708
- "set.js"
5858
+ "compile",
5859
+ "doc",
5860
+ "reset.js"
5709
5861
  ]
5710
5862
  },
5711
- "compile:doc:create": {
5863
+ "compile:thread:create": {
5712
5864
  "aliases": [],
5713
5865
  "args": {
5714
5866
  "face_id": {
@@ -5717,7 +5869,7 @@
5717
5869
  "required": true
5718
5870
  }
5719
5871
  },
5720
- "description": "Submit a document to a face",
5872
+ "description": "Start a new thread for a face",
5721
5873
  "flags": {
5722
5874
  "json": {
5723
5875
  "description": "Format output as json.",
@@ -5751,49 +5903,22 @@
5751
5903
  "type": "option"
5752
5904
  },
5753
5905
  "label": {
5754
- "description": "Document label/title",
5906
+ "description": "Thread label",
5755
5907
  "name": "label",
5756
5908
  "hasDynamicHelp": false,
5757
5909
  "multiple": false,
5758
5910
  "type": "option"
5759
5911
  },
5760
- "content": {
5761
- "description": "Inline text content",
5762
- "name": "content",
5763
- "hasDynamicHelp": false,
5764
- "multiple": false,
5765
- "type": "option"
5766
- },
5767
- "file": {
5768
- "description": "Read content from file",
5769
- "name": "file",
5770
- "hasDynamicHelp": false,
5771
- "multiple": false,
5772
- "type": "option"
5773
- },
5774
- "medium": {
5775
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5776
- "name": "medium",
5777
- "hasDynamicHelp": false,
5778
- "multiple": false,
5779
- "type": "option"
5780
- },
5781
- "perspective": {
5782
- "description": "Perspective (first-person or third-person)",
5783
- "name": "perspective",
5784
- "default": "first-person",
5785
- "hasDynamicHelp": false,
5786
- "multiple": false,
5787
- "options": [
5788
- "first-person",
5789
- "third-person"
5790
- ],
5791
- "type": "option"
5912
+ "oauth-only": {
5913
+ "description": "Prevent fallback to paid system key (use OAuth only)",
5914
+ "name": "oauth-only",
5915
+ "allowNo": false,
5916
+ "type": "boolean"
5792
5917
  }
5793
5918
  },
5794
5919
  "hasDynamicHelp": false,
5795
5920
  "hiddenAliases": [],
5796
- "id": "compile:doc:create",
5921
+ "id": "compile:thread:create",
5797
5922
  "pluginAlias": "faces-cli",
5798
5923
  "pluginName": "faces-cli",
5799
5924
  "pluginType": "core",
@@ -5804,20 +5929,20 @@
5804
5929
  "dist",
5805
5930
  "commands",
5806
5931
  "compile",
5807
- "doc",
5932
+ "thread",
5808
5933
  "create.js"
5809
5934
  ]
5810
5935
  },
5811
- "compile:doc:delete": {
5936
+ "compile:thread:delete": {
5812
5937
  "aliases": [],
5813
5938
  "args": {
5814
- "doc_id": {
5815
- "description": "Document ID",
5816
- "name": "doc_id",
5939
+ "thread_id": {
5940
+ "description": "Thread ID",
5941
+ "name": "thread_id",
5817
5942
  "required": true
5818
5943
  }
5819
5944
  },
5820
- "description": "Delete a document",
5945
+ "description": "Delete a thread",
5821
5946
  "flags": {
5822
5947
  "json": {
5823
5948
  "description": "Format output as json.",
@@ -5849,11 +5974,17 @@
5849
5974
  "hasDynamicHelp": false,
5850
5975
  "multiple": false,
5851
5976
  "type": "option"
5977
+ },
5978
+ "yes": {
5979
+ "description": "Skip confirmation",
5980
+ "name": "yes",
5981
+ "allowNo": false,
5982
+ "type": "boolean"
5852
5983
  }
5853
5984
  },
5854
5985
  "hasDynamicHelp": false,
5855
5986
  "hiddenAliases": [],
5856
- "id": "compile:doc:delete",
5987
+ "id": "compile:thread:delete",
5857
5988
  "pluginAlias": "faces-cli",
5858
5989
  "pluginName": "faces-cli",
5859
5990
  "pluginType": "core",
@@ -5864,20 +5995,20 @@
5864
5995
  "dist",
5865
5996
  "commands",
5866
5997
  "compile",
5867
- "doc",
5998
+ "thread",
5868
5999
  "delete.js"
5869
6000
  ]
5870
6001
  },
5871
- "compile:doc:edit": {
6002
+ "compile:thread:edit": {
5872
6003
  "aliases": [],
5873
6004
  "args": {
5874
- "doc_id": {
5875
- "description": "Document ID",
5876
- "name": "doc_id",
6005
+ "thread_id": {
6006
+ "description": "Thread ID",
6007
+ "name": "thread_id",
5877
6008
  "required": true
5878
6009
  }
5879
6010
  },
5880
- "description": "Edit a document (label, content, or perspective)",
6011
+ "description": "Edit a thread (label and/or reassign face speaker)",
5881
6012
  "flags": {
5882
6013
  "json": {
5883
6014
  "description": "Format output as json.",
@@ -5911,48 +6042,23 @@
5911
6042
  "type": "option"
5912
6043
  },
5913
6044
  "label": {
5914
- "description": "New label/title",
6045
+ "description": "New thread label",
5915
6046
  "name": "label",
5916
6047
  "hasDynamicHelp": false,
5917
6048
  "multiple": false,
5918
6049
  "type": "option"
5919
6050
  },
5920
- "content": {
5921
- "description": "New inline text content",
5922
- "name": "content",
5923
- "hasDynamicHelp": false,
5924
- "multiple": false,
5925
- "type": "option"
5926
- },
5927
- "file": {
5928
- "description": "Read new content from file",
5929
- "name": "file",
5930
- "hasDynamicHelp": false,
5931
- "multiple": false,
5932
- "type": "option"
5933
- },
5934
- "medium": {
5935
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
5936
- "name": "medium",
5937
- "hasDynamicHelp": false,
5938
- "multiple": false,
5939
- "type": "option"
5940
- },
5941
- "perspective": {
5942
- "description": "Perspective (first-person or third-person)",
5943
- "name": "perspective",
6051
+ "face-speaker": {
6052
+ "description": "Reassign face speaker: set this speaker to role=user, all others to role=assistant",
6053
+ "name": "face-speaker",
5944
6054
  "hasDynamicHelp": false,
5945
6055
  "multiple": false,
5946
- "options": [
5947
- "first-person",
5948
- "third-person"
5949
- ],
5950
6056
  "type": "option"
5951
6057
  }
5952
6058
  },
5953
6059
  "hasDynamicHelp": false,
5954
6060
  "hiddenAliases": [],
5955
- "id": "compile:doc:edit",
6061
+ "id": "compile:thread:edit",
5956
6062
  "pluginAlias": "faces-cli",
5957
6063
  "pluginName": "faces-cli",
5958
6064
  "pluginType": "core",
@@ -5963,20 +6069,20 @@
5963
6069
  "dist",
5964
6070
  "commands",
5965
6071
  "compile",
5966
- "doc",
6072
+ "thread",
5967
6073
  "edit.js"
5968
6074
  ]
5969
6075
  },
5970
- "compile:doc:get": {
6076
+ "compile:thread:get": {
5971
6077
  "aliases": [],
5972
6078
  "args": {
5973
- "doc_id": {
5974
- "description": "Document ID",
5975
- "name": "doc_id",
6079
+ "thread_id": {
6080
+ "description": "Thread ID",
6081
+ "name": "thread_id",
5976
6082
  "required": true
5977
6083
  }
5978
6084
  },
5979
- "description": "Get a document by ID",
6085
+ "description": "Get a thread by ID",
5980
6086
  "flags": {
5981
6087
  "json": {
5982
6088
  "description": "Format output as json.",
@@ -6012,7 +6118,7 @@
6012
6118
  },
6013
6119
  "hasDynamicHelp": false,
6014
6120
  "hiddenAliases": [],
6015
- "id": "compile:doc:get",
6121
+ "id": "compile:thread:get",
6016
6122
  "pluginAlias": "faces-cli",
6017
6123
  "pluginName": "faces-cli",
6018
6124
  "pluginType": "core",
@@ -6023,11 +6129,11 @@
6023
6129
  "dist",
6024
6130
  "commands",
6025
6131
  "compile",
6026
- "doc",
6132
+ "thread",
6027
6133
  "get.js"
6028
6134
  ]
6029
6135
  },
6030
- "compile:doc": {
6136
+ "compile:thread:list": {
6031
6137
  "aliases": [],
6032
6138
  "args": {
6033
6139
  "face_id": {
@@ -6036,11 +6142,7 @@
6036
6142
  "required": true
6037
6143
  }
6038
6144
  },
6039
- "description": "Compile one or more documents into a face (create → make in one step). Repeat --file to submit several documents in a single command; each file becomes its own document rather than being concatenated.",
6040
- "examples": [
6041
- "<%= config.bin %> <%= command.id %> alice --file notes.txt",
6042
- "<%= config.bin %> <%= command.id %> alice --file a.txt --file b.txt --file c.txt --no-wait --json"
6043
- ],
6145
+ "description": "List threads for a face",
6044
6146
  "flags": {
6045
6147
  "json": {
6046
6148
  "description": "Format output as json.",
@@ -6072,68 +6174,11 @@
6072
6174
  "hasDynamicHelp": false,
6073
6175
  "multiple": false,
6074
6176
  "type": "option"
6075
- },
6076
- "label": {
6077
- "description": "Document label/title (single document only; with several files each is labelled by its filename)",
6078
- "name": "label",
6079
- "hasDynamicHelp": false,
6080
- "multiple": false,
6081
- "type": "option"
6082
- },
6083
- "content": {
6084
- "description": "Inline text content",
6085
- "exclusive": [
6086
- "file"
6087
- ],
6088
- "name": "content",
6089
- "hasDynamicHelp": false,
6090
- "multiple": false,
6091
- "type": "option"
6092
- },
6093
- "file": {
6094
- "description": "Read content from file (repeatable — each file becomes its own document)",
6095
- "name": "file",
6096
- "hasDynamicHelp": false,
6097
- "multiple": true,
6098
- "type": "option"
6099
- },
6100
- "medium": {
6101
- "description": "What sort of writing this is — e.g. email, text message, social post, essay, academic paper, blog post, legal document, thread reply, conversation (covers speech: transcripts, interviews, calls). Common synonyms fold automatically. Omit it if you do not know: a wrong declaration is worse than none, because a declaration is trusted and an absence is not.",
6102
- "name": "medium",
6103
- "hasDynamicHelp": false,
6104
- "multiple": false,
6105
- "type": "option"
6106
- },
6107
- "perspective": {
6108
- "description": "Perspective",
6109
- "name": "perspective",
6110
- "default": "first-person",
6111
- "hasDynamicHelp": false,
6112
- "multiple": false,
6113
- "options": [
6114
- "first-person",
6115
- "third-person"
6116
- ],
6117
- "type": "option"
6118
- },
6119
- "timeout": {
6120
- "description": "Compile timeout in seconds, per document (default: 600)",
6121
- "name": "timeout",
6122
- "default": 600,
6123
- "hasDynamicHelp": false,
6124
- "multiple": false,
6125
- "type": "option"
6126
- },
6127
- "no-wait": {
6128
- "description": "Create and trigger compilation, then return immediately without polling.",
6129
- "name": "no-wait",
6130
- "allowNo": false,
6131
- "type": "boolean"
6132
6177
  }
6133
6178
  },
6134
6179
  "hasDynamicHelp": false,
6135
6180
  "hiddenAliases": [],
6136
- "id": "compile:doc",
6181
+ "id": "compile:thread:list",
6137
6182
  "pluginAlias": "faces-cli",
6138
6183
  "pluginName": "faces-cli",
6139
6184
  "pluginType": "core",
@@ -6144,20 +6189,20 @@
6144
6189
  "dist",
6145
6190
  "commands",
6146
6191
  "compile",
6147
- "doc",
6148
- "index.js"
6192
+ "thread",
6193
+ "list.js"
6149
6194
  ]
6150
6195
  },
6151
- "compile:doc:list": {
6196
+ "compile:thread:make": {
6152
6197
  "aliases": [],
6153
6198
  "args": {
6154
- "face_id": {
6155
- "description": "Face alias",
6156
- "name": "face_id",
6199
+ "thread_id": {
6200
+ "description": "Thread ID",
6201
+ "name": "thread_id",
6157
6202
  "required": true
6158
6203
  }
6159
6204
  },
6160
- "description": "List documents for a face. Each document's full text is omitted unless --verbose, so a face with a real corpus stays readable. For a table of every source, documents and threads together, use face:sources.",
6205
+ "description": "Compile an existing thread (prepare + sync in one step)",
6161
6206
  "flags": {
6162
6207
  "json": {
6163
6208
  "description": "Format output as json.",
@@ -6190,16 +6235,24 @@
6190
6235
  "multiple": false,
6191
6236
  "type": "option"
6192
6237
  },
6193
- "verbose": {
6194
- "description": "Include each document's full text",
6195
- "name": "verbose",
6238
+ "timeout": {
6239
+ "description": "Compile timeout in seconds (default: 600)",
6240
+ "name": "timeout",
6241
+ "default": 600,
6242
+ "hasDynamicHelp": false,
6243
+ "multiple": false,
6244
+ "type": "option"
6245
+ },
6246
+ "no-wait": {
6247
+ "description": "Return immediately after triggering compilation. Prints the thread ID for manual polling.",
6248
+ "name": "no-wait",
6196
6249
  "allowNo": false,
6197
6250
  "type": "boolean"
6198
6251
  }
6199
6252
  },
6200
6253
  "hasDynamicHelp": false,
6201
6254
  "hiddenAliases": [],
6202
- "id": "compile:doc:list",
6255
+ "id": "compile:thread:make",
6203
6256
  "pluginAlias": "faces-cli",
6204
6257
  "pluginName": "faces-cli",
6205
6258
  "pluginType": "core",
@@ -6210,20 +6263,20 @@
6210
6263
  "dist",
6211
6264
  "commands",
6212
6265
  "compile",
6213
- "doc",
6214
- "list.js"
6266
+ "thread",
6267
+ "make.js"
6215
6268
  ]
6216
6269
  },
6217
- "compile:doc:make": {
6270
+ "compile:thread:message": {
6218
6271
  "aliases": [],
6219
6272
  "args": {
6220
- "doc_id": {
6221
- "description": "Document ID",
6222
- "name": "doc_id",
6273
+ "thread_id": {
6274
+ "description": "Thread ID",
6275
+ "name": "thread_id",
6223
6276
  "required": true
6224
6277
  }
6225
6278
  },
6226
- "description": "Compile an existing document (prepare + sync in one step)",
6279
+ "description": "Send a user message to a thread",
6227
6280
  "flags": {
6228
6281
  "json": {
6229
6282
  "description": "Format output as json.",
@@ -6256,24 +6309,25 @@
6256
6309
  "multiple": false,
6257
6310
  "type": "option"
6258
6311
  },
6259
- "timeout": {
6260
- "description": "Compile timeout in seconds (default: 600)",
6261
- "name": "timeout",
6262
- "default": 600,
6312
+ "message": {
6313
+ "char": "m",
6314
+ "description": "User message to append",
6315
+ "name": "message",
6316
+ "required": true,
6263
6317
  "hasDynamicHelp": false,
6264
6318
  "multiple": false,
6265
6319
  "type": "option"
6266
6320
  },
6267
- "no-wait": {
6268
- "description": "Return immediately after triggering compilation. Prints the document ID for manual polling.",
6269
- "name": "no-wait",
6321
+ "oauth-only": {
6322
+ "description": "Prevent fallback to paid system key (use OAuth only)",
6323
+ "name": "oauth-only",
6270
6324
  "allowNo": false,
6271
6325
  "type": "boolean"
6272
6326
  }
6273
6327
  },
6274
6328
  "hasDynamicHelp": false,
6275
6329
  "hiddenAliases": [],
6276
- "id": "compile:doc:make",
6330
+ "id": "compile:thread:message",
6277
6331
  "pluginAlias": "faces-cli",
6278
6332
  "pluginName": "faces-cli",
6279
6333
  "pluginType": "core",
@@ -6284,20 +6338,20 @@
6284
6338
  "dist",
6285
6339
  "commands",
6286
6340
  "compile",
6287
- "doc",
6288
- "make.js"
6341
+ "thread",
6342
+ "message.js"
6289
6343
  ]
6290
6344
  },
6291
- "compile:doc:pause": {
6345
+ "compile:thread:pause": {
6292
6346
  "aliases": [],
6293
6347
  "args": {
6294
- "doc_id": {
6295
- "description": "Document ID",
6296
- "name": "doc_id",
6348
+ "thread_id": {
6349
+ "description": "Thread ID",
6350
+ "name": "thread_id",
6297
6351
  "required": true
6298
6352
  }
6299
6353
  },
6300
- "description": "Ask a running document compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
6354
+ "description": "Ask a running thread compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
6301
6355
  "flags": {
6302
6356
  "json": {
6303
6357
  "description": "Format output as json.",
@@ -6347,7 +6401,7 @@
6347
6401
  },
6348
6402
  "hasDynamicHelp": false,
6349
6403
  "hiddenAliases": [],
6350
- "id": "compile:doc:pause",
6404
+ "id": "compile:thread:pause",
6351
6405
  "pluginAlias": "faces-cli",
6352
6406
  "pluginName": "faces-cli",
6353
6407
  "pluginType": "core",
@@ -6358,20 +6412,20 @@
6358
6412
  "dist",
6359
6413
  "commands",
6360
6414
  "compile",
6361
- "doc",
6415
+ "thread",
6362
6416
  "pause.js"
6363
6417
  ]
6364
6418
  },
6365
- "compile:doc:reset": {
6419
+ "compile:thread:reset": {
6366
6420
  "aliases": [],
6367
6421
  "args": {
6368
- "doc_id": {
6369
- "description": "Document ID",
6370
- "name": "doc_id",
6422
+ "thread_id": {
6423
+ "description": "Thread ID",
6424
+ "name": "thread_id",
6371
6425
  "required": true
6372
6426
  }
6373
6427
  },
6374
- "description": "Reset document compilation progress (wipe extraction, keep content)",
6428
+ "description": "Reset thread compilation progress (wipe extraction, keep source messages)",
6375
6429
  "flags": {
6376
6430
  "json": {
6377
6431
  "description": "Format output as json.",
@@ -6413,7 +6467,7 @@
6413
6467
  },
6414
6468
  "hasDynamicHelp": false,
6415
6469
  "hiddenAliases": [],
6416
- "id": "compile:doc:reset",
6470
+ "id": "compile:thread:reset",
6417
6471
  "pluginAlias": "faces-cli",
6418
6472
  "pluginName": "faces-cli",
6419
6473
  "pluginType": "core",
@@ -6424,20 +6478,20 @@
6424
6478
  "dist",
6425
6479
  "commands",
6426
6480
  "compile",
6427
- "doc",
6481
+ "thread",
6428
6482
  "reset.js"
6429
6483
  ]
6430
6484
  },
6431
- "compile:thread:create": {
6485
+ "compile:thread:sync": {
6432
6486
  "aliases": [],
6433
6487
  "args": {
6434
- "face_id": {
6435
- "description": "Face alias",
6436
- "name": "face_id",
6488
+ "thread_id": {
6489
+ "description": "Thread ID",
6490
+ "name": "thread_id",
6437
6491
  "required": true
6438
6492
  }
6439
6493
  },
6440
- "description": "Start a new thread for a face",
6494
+ "description": "Archive and sync a thread into a face",
6441
6495
  "flags": {
6442
6496
  "json": {
6443
6497
  "description": "Format output as json.",
@@ -6469,24 +6523,11 @@
6469
6523
  "hasDynamicHelp": false,
6470
6524
  "multiple": false,
6471
6525
  "type": "option"
6472
- },
6473
- "label": {
6474
- "description": "Thread label",
6475
- "name": "label",
6476
- "hasDynamicHelp": false,
6477
- "multiple": false,
6478
- "type": "option"
6479
- },
6480
- "oauth-only": {
6481
- "description": "Prevent fallback to paid system key (use OAuth only)",
6482
- "name": "oauth-only",
6483
- "allowNo": false,
6484
- "type": "boolean"
6485
6526
  }
6486
6527
  },
6487
6528
  "hasDynamicHelp": false,
6488
6529
  "hiddenAliases": [],
6489
- "id": "compile:thread:create",
6530
+ "id": "compile:thread:sync",
6490
6531
  "pluginAlias": "faces-cli",
6491
6532
  "pluginName": "faces-cli",
6492
6533
  "pluginType": "core",
@@ -6498,19 +6539,19 @@
6498
6539
  "commands",
6499
6540
  "compile",
6500
6541
  "thread",
6501
- "create.js"
6542
+ "sync.js"
6502
6543
  ]
6503
6544
  },
6504
- "compile:thread:delete": {
6545
+ "team:tag:add": {
6505
6546
  "aliases": [],
6506
6547
  "args": {
6507
- "thread_id": {
6508
- "description": "Thread ID",
6509
- "name": "thread_id",
6548
+ "team_id": {
6549
+ "description": "Team ID",
6550
+ "name": "team_id",
6510
6551
  "required": true
6511
6552
  }
6512
6553
  },
6513
- "description": "Delete a thread",
6554
+ "description": "Add tags to a team (appends, idempotent)",
6514
6555
  "flags": {
6515
6556
  "json": {
6516
6557
  "description": "Format output as json.",
@@ -6540,19 +6581,21 @@
6540
6581
  "env": "FACES_API_KEY",
6541
6582
  "name": "api-key",
6542
6583
  "hasDynamicHelp": false,
6543
- "multiple": false,
6584
+ "multiple": false,
6585
+ "type": "option"
6586
+ },
6587
+ "tag": {
6588
+ "description": "Tag to add (repeatable)",
6589
+ "name": "tag",
6590
+ "required": true,
6591
+ "hasDynamicHelp": false,
6592
+ "multiple": true,
6544
6593
  "type": "option"
6545
- },
6546
- "yes": {
6547
- "description": "Skip confirmation",
6548
- "name": "yes",
6549
- "allowNo": false,
6550
- "type": "boolean"
6551
6594
  }
6552
6595
  },
6553
6596
  "hasDynamicHelp": false,
6554
6597
  "hiddenAliases": [],
6555
- "id": "compile:thread:delete",
6598
+ "id": "team:tag:add",
6556
6599
  "pluginAlias": "faces-cli",
6557
6600
  "pluginName": "faces-cli",
6558
6601
  "pluginType": "core",
@@ -6562,21 +6605,21 @@
6562
6605
  "relativePath": [
6563
6606
  "dist",
6564
6607
  "commands",
6565
- "compile",
6566
- "thread",
6567
- "delete.js"
6608
+ "team",
6609
+ "tag",
6610
+ "add.js"
6568
6611
  ]
6569
6612
  },
6570
- "compile:thread:edit": {
6613
+ "team:tag:list": {
6571
6614
  "aliases": [],
6572
6615
  "args": {
6573
- "thread_id": {
6574
- "description": "Thread ID",
6575
- "name": "thread_id",
6616
+ "team_id": {
6617
+ "description": "Team ID",
6618
+ "name": "team_id",
6576
6619
  "required": true
6577
6620
  }
6578
6621
  },
6579
- "description": "Edit a thread (label and/or reassign face speaker)",
6622
+ "description": "List tags on a team",
6580
6623
  "flags": {
6581
6624
  "json": {
6582
6625
  "description": "Format output as json.",
@@ -6608,25 +6651,11 @@
6608
6651
  "hasDynamicHelp": false,
6609
6652
  "multiple": false,
6610
6653
  "type": "option"
6611
- },
6612
- "label": {
6613
- "description": "New thread label",
6614
- "name": "label",
6615
- "hasDynamicHelp": false,
6616
- "multiple": false,
6617
- "type": "option"
6618
- },
6619
- "face-speaker": {
6620
- "description": "Reassign face speaker: set this speaker to role=user, all others to role=assistant",
6621
- "name": "face-speaker",
6622
- "hasDynamicHelp": false,
6623
- "multiple": false,
6624
- "type": "option"
6625
6654
  }
6626
6655
  },
6627
6656
  "hasDynamicHelp": false,
6628
6657
  "hiddenAliases": [],
6629
- "id": "compile:thread:edit",
6658
+ "id": "team:tag:list",
6630
6659
  "pluginAlias": "faces-cli",
6631
6660
  "pluginName": "faces-cli",
6632
6661
  "pluginType": "core",
@@ -6636,21 +6665,26 @@
6636
6665
  "relativePath": [
6637
6666
  "dist",
6638
6667
  "commands",
6639
- "compile",
6640
- "thread",
6641
- "edit.js"
6668
+ "team",
6669
+ "tag",
6670
+ "list.js"
6642
6671
  ]
6643
6672
  },
6644
- "compile:thread:get": {
6673
+ "team:tag:remove": {
6645
6674
  "aliases": [],
6646
6675
  "args": {
6647
- "thread_id": {
6648
- "description": "Thread ID",
6649
- "name": "thread_id",
6676
+ "team_id": {
6677
+ "description": "Team ID",
6678
+ "name": "team_id",
6679
+ "required": true
6680
+ },
6681
+ "tag": {
6682
+ "description": "Tag to remove",
6683
+ "name": "tag",
6650
6684
  "required": true
6651
6685
  }
6652
6686
  },
6653
- "description": "Get a thread by ID",
6687
+ "description": "Remove a tag from a team",
6654
6688
  "flags": {
6655
6689
  "json": {
6656
6690
  "description": "Format output as json.",
@@ -6686,7 +6720,7 @@
6686
6720
  },
6687
6721
  "hasDynamicHelp": false,
6688
6722
  "hiddenAliases": [],
6689
- "id": "compile:thread:get",
6723
+ "id": "team:tag:remove",
6690
6724
  "pluginAlias": "faces-cli",
6691
6725
  "pluginName": "faces-cli",
6692
6726
  "pluginType": "core",
@@ -6696,21 +6730,21 @@
6696
6730
  "relativePath": [
6697
6731
  "dist",
6698
6732
  "commands",
6699
- "compile",
6700
- "thread",
6701
- "get.js"
6733
+ "team",
6734
+ "tag",
6735
+ "remove.js"
6702
6736
  ]
6703
6737
  },
6704
- "compile:thread:list": {
6738
+ "team:tag:set": {
6705
6739
  "aliases": [],
6706
6740
  "args": {
6707
- "face_id": {
6708
- "description": "Face alias",
6709
- "name": "face_id",
6741
+ "team_id": {
6742
+ "description": "Team ID",
6743
+ "name": "team_id",
6710
6744
  "required": true
6711
6745
  }
6712
6746
  },
6713
- "description": "List threads for a face",
6747
+ "description": "Replace all tags on a team",
6714
6748
  "flags": {
6715
6749
  "json": {
6716
6750
  "description": "Format output as json.",
@@ -6742,11 +6776,19 @@
6742
6776
  "hasDynamicHelp": false,
6743
6777
  "multiple": false,
6744
6778
  "type": "option"
6779
+ },
6780
+ "tag": {
6781
+ "description": "Tag to set (repeatable, replaces all)",
6782
+ "name": "tag",
6783
+ "required": true,
6784
+ "hasDynamicHelp": false,
6785
+ "multiple": true,
6786
+ "type": "option"
6745
6787
  }
6746
6788
  },
6747
6789
  "hasDynamicHelp": false,
6748
6790
  "hiddenAliases": [],
6749
- "id": "compile:thread:list",
6791
+ "id": "team:tag:set",
6750
6792
  "pluginAlias": "faces-cli",
6751
6793
  "pluginName": "faces-cli",
6752
6794
  "pluginType": "core",
@@ -6756,21 +6798,21 @@
6756
6798
  "relativePath": [
6757
6799
  "dist",
6758
6800
  "commands",
6759
- "compile",
6760
- "thread",
6761
- "list.js"
6801
+ "team",
6802
+ "tag",
6803
+ "set.js"
6762
6804
  ]
6763
6805
  },
6764
- "compile:thread:make": {
6806
+ "face:tag:add": {
6765
6807
  "aliases": [],
6766
6808
  "args": {
6767
- "thread_id": {
6768
- "description": "Thread ID",
6769
- "name": "thread_id",
6809
+ "alias": {
6810
+ "description": "Face alias",
6811
+ "name": "alias",
6770
6812
  "required": true
6771
6813
  }
6772
6814
  },
6773
- "description": "Compile an existing thread (prepare + sync in one step)",
6815
+ "description": "Add tags to a face (appends, idempotent)",
6774
6816
  "flags": {
6775
6817
  "json": {
6776
6818
  "description": "Format output as json.",
@@ -6803,24 +6845,18 @@
6803
6845
  "multiple": false,
6804
6846
  "type": "option"
6805
6847
  },
6806
- "timeout": {
6807
- "description": "Compile timeout in seconds (default: 600)",
6808
- "name": "timeout",
6809
- "default": 600,
6848
+ "tag": {
6849
+ "description": "Tag to add (repeatable)",
6850
+ "name": "tag",
6851
+ "required": true,
6810
6852
  "hasDynamicHelp": false,
6811
- "multiple": false,
6853
+ "multiple": true,
6812
6854
  "type": "option"
6813
- },
6814
- "no-wait": {
6815
- "description": "Return immediately after triggering compilation. Prints the thread ID for manual polling.",
6816
- "name": "no-wait",
6817
- "allowNo": false,
6818
- "type": "boolean"
6819
6855
  }
6820
6856
  },
6821
6857
  "hasDynamicHelp": false,
6822
6858
  "hiddenAliases": [],
6823
- "id": "compile:thread:make",
6859
+ "id": "face:tag:add",
6824
6860
  "pluginAlias": "faces-cli",
6825
6861
  "pluginName": "faces-cli",
6826
6862
  "pluginType": "core",
@@ -6830,21 +6866,15 @@
6830
6866
  "relativePath": [
6831
6867
  "dist",
6832
6868
  "commands",
6833
- "compile",
6834
- "thread",
6835
- "make.js"
6869
+ "face",
6870
+ "tag",
6871
+ "add.js"
6836
6872
  ]
6837
6873
  },
6838
- "compile:thread:message": {
6874
+ "face:tag:all": {
6839
6875
  "aliases": [],
6840
- "args": {
6841
- "thread_id": {
6842
- "description": "Thread ID",
6843
- "name": "thread_id",
6844
- "required": true
6845
- }
6846
- },
6847
- "description": "Send a user message to a thread",
6876
+ "args": {},
6877
+ "description": "List all tags across all your faces",
6848
6878
  "flags": {
6849
6879
  "json": {
6850
6880
  "description": "Format output as json.",
@@ -6876,26 +6906,11 @@
6876
6906
  "hasDynamicHelp": false,
6877
6907
  "multiple": false,
6878
6908
  "type": "option"
6879
- },
6880
- "message": {
6881
- "char": "m",
6882
- "description": "User message to append",
6883
- "name": "message",
6884
- "required": true,
6885
- "hasDynamicHelp": false,
6886
- "multiple": false,
6887
- "type": "option"
6888
- },
6889
- "oauth-only": {
6890
- "description": "Prevent fallback to paid system key (use OAuth only)",
6891
- "name": "oauth-only",
6892
- "allowNo": false,
6893
- "type": "boolean"
6894
6909
  }
6895
6910
  },
6896
6911
  "hasDynamicHelp": false,
6897
6912
  "hiddenAliases": [],
6898
- "id": "compile:thread:message",
6913
+ "id": "face:tag:all",
6899
6914
  "pluginAlias": "faces-cli",
6900
6915
  "pluginName": "faces-cli",
6901
6916
  "pluginType": "core",
@@ -6905,21 +6920,21 @@
6905
6920
  "relativePath": [
6906
6921
  "dist",
6907
6922
  "commands",
6908
- "compile",
6909
- "thread",
6910
- "message.js"
6923
+ "face",
6924
+ "tag",
6925
+ "all.js"
6911
6926
  ]
6912
6927
  },
6913
- "compile:thread:pause": {
6928
+ "face:tag:list": {
6914
6929
  "aliases": [],
6915
6930
  "args": {
6916
- "thread_id": {
6917
- "description": "Thread ID",
6918
- "name": "thread_id",
6931
+ "alias": {
6932
+ "description": "Face alias",
6933
+ "name": "alias",
6919
6934
  "required": true
6920
6935
  }
6921
6936
  },
6922
- "description": "Ask a running thread compilation to stop (preserves progress, resume with make). The compile stops at the next chunk boundary; this waits for it unless --no-wait.",
6937
+ "description": "List tags on a face",
6923
6938
  "flags": {
6924
6939
  "json": {
6925
6940
  "description": "Format output as json.",
@@ -6951,25 +6966,11 @@
6951
6966
  "hasDynamicHelp": false,
6952
6967
  "multiple": false,
6953
6968
  "type": "option"
6954
- },
6955
- "no-wait": {
6956
- "description": "Return as soon as the pause is accepted, without waiting for the compile to stop.",
6957
- "name": "no-wait",
6958
- "allowNo": false,
6959
- "type": "boolean"
6960
- },
6961
- "timeout": {
6962
- "description": "Seconds to wait for the compile to stop (default: 60)",
6963
- "name": "timeout",
6964
- "default": 60,
6965
- "hasDynamicHelp": false,
6966
- "multiple": false,
6967
- "type": "option"
6968
6969
  }
6969
6970
  },
6970
6971
  "hasDynamicHelp": false,
6971
6972
  "hiddenAliases": [],
6972
- "id": "compile:thread:pause",
6973
+ "id": "face:tag:list",
6973
6974
  "pluginAlias": "faces-cli",
6974
6975
  "pluginName": "faces-cli",
6975
6976
  "pluginType": "core",
@@ -6979,21 +6980,26 @@
6979
6980
  "relativePath": [
6980
6981
  "dist",
6981
6982
  "commands",
6982
- "compile",
6983
- "thread",
6984
- "pause.js"
6983
+ "face",
6984
+ "tag",
6985
+ "list.js"
6985
6986
  ]
6986
6987
  },
6987
- "compile:thread:reset": {
6988
+ "face:tag:remove": {
6988
6989
  "aliases": [],
6989
6990
  "args": {
6990
- "thread_id": {
6991
- "description": "Thread ID",
6992
- "name": "thread_id",
6991
+ "alias": {
6992
+ "description": "Face alias",
6993
+ "name": "alias",
6994
+ "required": true
6995
+ },
6996
+ "tag": {
6997
+ "description": "Tag to remove",
6998
+ "name": "tag",
6993
6999
  "required": true
6994
7000
  }
6995
7001
  },
6996
- "description": "Reset thread compilation progress (wipe extraction, keep source messages)",
7002
+ "description": "Remove a tag from a face",
6997
7003
  "flags": {
6998
7004
  "json": {
6999
7005
  "description": "Format output as json.",
@@ -7025,17 +7031,11 @@
7025
7031
  "hasDynamicHelp": false,
7026
7032
  "multiple": false,
7027
7033
  "type": "option"
7028
- },
7029
- "yes": {
7030
- "description": "Skip confirmation",
7031
- "name": "yes",
7032
- "allowNo": false,
7033
- "type": "boolean"
7034
7034
  }
7035
7035
  },
7036
7036
  "hasDynamicHelp": false,
7037
7037
  "hiddenAliases": [],
7038
- "id": "compile:thread:reset",
7038
+ "id": "face:tag:remove",
7039
7039
  "pluginAlias": "faces-cli",
7040
7040
  "pluginName": "faces-cli",
7041
7041
  "pluginType": "core",
@@ -7045,21 +7045,21 @@
7045
7045
  "relativePath": [
7046
7046
  "dist",
7047
7047
  "commands",
7048
- "compile",
7049
- "thread",
7050
- "reset.js"
7048
+ "face",
7049
+ "tag",
7050
+ "remove.js"
7051
7051
  ]
7052
7052
  },
7053
- "compile:thread:sync": {
7053
+ "face:tag:set": {
7054
7054
  "aliases": [],
7055
7055
  "args": {
7056
- "thread_id": {
7057
- "description": "Thread ID",
7058
- "name": "thread_id",
7056
+ "alias": {
7057
+ "description": "Face alias",
7058
+ "name": "alias",
7059
7059
  "required": true
7060
7060
  }
7061
7061
  },
7062
- "description": "Archive and sync a thread into a face",
7062
+ "description": "Replace all tags on a face",
7063
7063
  "flags": {
7064
7064
  "json": {
7065
7065
  "description": "Format output as json.",
@@ -7091,11 +7091,19 @@
7091
7091
  "hasDynamicHelp": false,
7092
7092
  "multiple": false,
7093
7093
  "type": "option"
7094
+ },
7095
+ "tag": {
7096
+ "description": "Tag to set (repeatable, replaces all)",
7097
+ "name": "tag",
7098
+ "required": true,
7099
+ "hasDynamicHelp": false,
7100
+ "multiple": true,
7101
+ "type": "option"
7094
7102
  }
7095
7103
  },
7096
7104
  "hasDynamicHelp": false,
7097
7105
  "hiddenAliases": [],
7098
- "id": "compile:thread:sync",
7106
+ "id": "face:tag:set",
7099
7107
  "pluginAlias": "faces-cli",
7100
7108
  "pluginName": "faces-cli",
7101
7109
  "pluginType": "core",
@@ -7105,11 +7113,11 @@
7105
7113
  "relativePath": [
7106
7114
  "dist",
7107
7115
  "commands",
7108
- "compile",
7109
- "thread",
7110
- "sync.js"
7116
+ "face",
7117
+ "tag",
7118
+ "set.js"
7111
7119
  ]
7112
7120
  }
7113
7121
  },
7114
- "version": "1.8.1"
7122
+ "version": "1.8.2"
7115
7123
  }