@swttch/extend-kit 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ko.md CHANGED
@@ -393,9 +393,32 @@ ccb oauth profile
393
393
  ### 옵션
394
394
 
395
395
  - `--json`: JSON 형식으로 출력
396
+ - `--env=NAME=VALUE`: 이번 실행에만 환경변수 하나를 강제로 지정 (여러 번 사용 가능)
396
397
  - `-h, --help`: 도움말 표시
397
398
  - `-v, --version`: 버전 정보 표시
398
399
 
400
+ ### 환경변수
401
+
402
+ `ccb`는 Claude Code의 설정 파일을 직접 읽어 `env` 블록을 적용합니다. `claude` 명령과 같은 동작이라,
403
+ `~/.claude/settings.json`에만 적어 둔 프록시나 `CLAUDE_CODE_OAUTH_TOKEN` 값이 `ccb`에도 닿습니다.
404
+ 네 개 파일을 겹쳐 읽으며 뒤에 오는 파일이 앞의 파일을 덮습니다.
405
+
406
+ ```
407
+ ~/.claude/settings.json
408
+ ~/.claude/settings.local.json
409
+ <프로젝트>/.claude/settings.json # <프로젝트>는 실행한 작업 디렉토리
410
+ <프로젝트>/.claude/settings.local.json
411
+ ```
412
+
413
+ 우선순위는 다음과 같습니다. 위에 있는 것이 이깁니다.
414
+
415
+ 1. 명령줄의 `--env=NAME=VALUE`
416
+ 2. 위 설정 파일들의 `env` 블록
417
+ 3. `ccb`가 실행될 때 물려받은 환경변수
418
+
419
+ `CLAUDE_CONFIG_DIR` 하나만은 설정 파일에서 읽지 않습니다. 그 값이 설정 파일의 위치를 정하기 때문이며,
420
+ 환경변수로 지정해야 합니다.
421
+
399
422
  ```bash
400
423
  ccb oauth usage --json
401
424
  ccb oauth profile --json
package/README.md CHANGED
@@ -401,9 +401,32 @@ ccb oauth profile
401
401
  ### Options
402
402
 
403
403
  - `--json`: Output in JSON format
404
+ - `--env=NAME=VALUE`: Force one environment variable for this run (repeatable)
404
405
  - `-h, --help`: Show help
405
406
  - `-v, --version`: Show version information
406
407
 
408
+ ### Environment
409
+
410
+ `ccb` reads Claude Code's own settings files and applies their `env` block, the same way the
411
+ `claude` CLI does — so a proxy or a `CLAUDE_CODE_OAUTH_TOKEN` written only into
412
+ `~/.claude/settings.json` reaches `ccb` too. Four files are layered, later winning over earlier:
413
+
414
+ ```
415
+ ~/.claude/settings.json
416
+ ~/.claude/settings.local.json
417
+ <project>/.claude/settings.json # <project> is the working directory
418
+ <project>/.claude/settings.local.json
419
+ ```
420
+
421
+ Resolution order, highest first:
422
+
423
+ 1. `--env=NAME=VALUE` on the command line
424
+ 2. the `env` block of the settings files above
425
+ 3. the environment `ccb` was started with
426
+
427
+ `CLAUDE_CONFIG_DIR` is the one variable never read from a settings file, since it decides where
428
+ those files are; set it in the environment instead.
429
+
407
430
  ```bash
408
431
  ccb oauth usage --json
409
432
  ccb oauth profile --json
@@ -4,7 +4,42 @@ import { CcbError } from '../errors.js';
4
4
  export function isApiKeyAuth(auth) {
5
5
  return typeof auth === 'object' && 'apiKey' in auth;
6
6
  }
7
+ /**
8
+ * A token handed to us through the environment, wrapped as credentials.
9
+ *
10
+ * `claude setup-token` issues a long-lived token for people who cannot run an interactive
11
+ * login — CI, containers, a workstation where the browser flow is blocked — and the way to
12
+ * use it is `CLAUDE_CODE_OAUTH_TOKEN`. The `claude` CLI reads that variable BEFORE it looks
13
+ * at the keychain: on a machine with a perfectly good login in the keychain, one bad value
14
+ * in that variable makes `claude` fail with 401, which is only possible if the variable is
15
+ * consulted first. So it is consulted first here too.
16
+ *
17
+ * The fields beside the token are filled with blanks because the variable carries a token and
18
+ * nothing else. That is honest rather than lossy: `accessToken` is the only field any caller
19
+ * in this package reads.
20
+ *
21
+ * `expiresAt` is the one that needs saying out loud. A token handed over this way comes with
22
+ * no expiry, and there is no refresh token to renew it with, so treating it as expired would
23
+ * make the feature unusable while treating it as fresh costs nothing: an expired one is
24
+ * refused by the server, which is the same answer, arriving from the side that actually knows.
25
+ */
26
+ function environmentCredentials(token) {
27
+ return {
28
+ claudeAiOauth: {
29
+ accessToken: token,
30
+ refreshToken: '',
31
+ expiresAt: Number.MAX_SAFE_INTEGER,
32
+ scopes: [],
33
+ subscriptionType: '',
34
+ rateLimitTier: '',
35
+ },
36
+ organizationUuid: '',
37
+ };
38
+ }
7
39
  export async function getCredentials() {
40
+ const envToken = process.env['CLAUDE_CODE_OAUTH_TOKEN'];
41
+ if (envToken)
42
+ return environmentCredentials(envToken);
8
43
  const platform = process.platform;
9
44
  if (platform === 'darwin') {
10
45
  return readKeychainCredentials();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/battery/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAElC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,uBAAuB,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjD,OAAO,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,IAAI,QAAQ,CAAC,yBAAyB,QAAQ,GAAG,EAAE,sBAAsB,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/battery/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,QAAQ,IAAI,IAAI,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,sBAAsB,CAAC,KAAa;IAC3C,OAAO;QACL,aAAa,EAAE;YACb,WAAW,EAAE,KAAK;YAClB,YAAY,EAAE,EAAE;YAChB,SAAS,EAAE,MAAM,CAAC,gBAAgB;YAClC,MAAM,EAAE,EAAE;YACV,gBAAgB,EAAE,EAAE;YACpB,aAAa,EAAE,EAAE;SAClB;QACD,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACxD,IAAI,QAAQ;QAAE,OAAO,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAElC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,uBAAuB,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjD,OAAO,mBAAmB,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,IAAI,QAAQ,CAAC,yBAAyB,QAAQ,GAAG,EAAE,sBAAsB,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,WAA8B;IAC3D,OAAO,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC,aAAa,CAAC,SAAS,CAAC;AAC3D,CAAC"}
package/dist/cli/index.js CHANGED
@@ -2,8 +2,10 @@
2
2
  import { getCredentials, getAccessToken } from '../battery/auth/index.js';
3
3
  import { ClaudeCodeClient } from '../battery/api/index.js';
4
4
  import { oauthCommand } from './oauth.js';
5
+ import { sttCommand } from './stt.js';
5
6
  import { getAccountCredentials } from './account-credentials.js';
6
7
  import { CcbError } from '../battery/errors.js';
8
+ import { applySettingsEnv } from '../settings-env.js';
7
9
  import { readFileSync } from 'node:fs';
8
10
  import { fileURLToPath } from 'node:url';
9
11
  import { dirname, resolve } from 'node:path';
@@ -15,15 +17,50 @@ const command = args.filter((a) => !a.startsWith('-'));
15
17
  const flags = new Set(args.filter((a) => a.startsWith('-')));
16
18
  const jsonOutput = flags.has('--json');
17
19
  const accountFile = args.find(arg => arg.startsWith('--account-file='))?.slice('--account-file='.length);
20
+ /**
21
+ * `--env NAME=VALUE`, repeatable: a variable the caller is forcing for this run.
22
+ *
23
+ * An assignment written in front of a command (`FOO=bar ccb ...`) cannot be told apart from
24
+ * one exported in a startup file — both arrive as plain entries in the environment, carrying
25
+ * no record of how they got there. So a caller who means "use THIS one, whatever the settings
26
+ * files say" has no way to say it through the environment, and says it through this flag
27
+ * instead. Values given here outrank the settings files; nothing outranks them.
28
+ */
29
+ function forcedEnv() {
30
+ return args
31
+ .filter(arg => arg.startsWith('--env='))
32
+ .map(arg => arg.slice('--env='.length))
33
+ .map((assignment) => {
34
+ const eq = assignment.indexOf('=');
35
+ // A value may itself contain "=" (a proxy URL with a query string does), so only the
36
+ // FIRST separator splits. A name may not be empty; a value may.
37
+ if (eq <= 0)
38
+ return null;
39
+ return [assignment.slice(0, eq), assignment.slice(eq + 1)];
40
+ })
41
+ .filter((pair) => pair !== null);
42
+ }
18
43
  async function createClient() {
19
44
  const credentials = accountFile ? await getAccountCredentials(accountFile) : await getCredentials();
20
45
  const token = getAccessToken(credentials);
21
46
  return new ClaudeCodeClient(token);
22
47
  }
23
48
  async function run() {
49
+ // Before anything reads the environment. `claude` applies its settings files' `env` block
50
+ // to itself this way, and every read below — the proxy, the OAuth token, the config dir —
51
+ // has to see the same environment `claude` would see on this machine.
52
+ //
53
+ // The project whose settings apply is the directory this process was started in, which is
54
+ // how the spawning plugin names one: it sets the child's working directory.
55
+ await applySettingsEnv();
56
+ for (const [name, value] of forcedEnv())
57
+ process.env[name] = value;
24
58
  const [module, ...subcommand] = command;
25
59
  if (flags.has('--capabilities')) {
26
- console.log(JSON.stringify({ capabilities: ['oauth.usage.account-file'] }));
60
+ // A caller checks this before using a command: the plugin has to know
61
+ // whether the kit on this machine is new enough to stream dictation, since
62
+ // the only alternative it once had (importing the module) is gone.
63
+ console.log(JSON.stringify({ capabilities: ['oauth.usage.account-file', 'stt.stream'] }));
27
64
  return;
28
65
  }
29
66
  if (args.some(arg => arg.startsWith('--account-file')) && (!accountFile || module !== 'oauth' || subcommand[0] !== 'usage')) {
@@ -41,13 +78,34 @@ Usage: ccb <command> [options]
41
78
  Commands:
42
79
  oauth usage Show usage limits
43
80
  oauth profile Show account profile
81
+ stt Transcribe raw PCM audio from stdin (see below)
82
+ stt --check Report whether this machine can dictate
44
83
 
45
84
  Options:
85
+ --env=NAME=VALUE Force one environment variable for this run (repeatable).
86
+ Outranks the env block of Claude Code's settings files.
46
87
  --account-file=<path> Read usage for a CCG saved-account snapshot (no account switch)
88
+ --language=<code> BCP-47 language for stt (default: en)
89
+ --keyterms=<a,b,c> Extra vocabulary to bias stt toward
90
+ --interims Also emit interim stt guesses
47
91
  --capabilities Output supported CLI capabilities as JSON
48
92
  --json Output as JSON
49
93
  -h, --help Show help
50
- -v, --version Show version`);
94
+ -v, --version Show version
95
+
96
+ stt reads raw PCM on stdin (16-bit LE, 16 kHz, mono) and writes one JSON
97
+ object per line to stdout. Any other audio format transcribes to silence.
98
+
99
+ ffmpeg -f avfoundation -i ':0' -ar 16000 -ac 1 -f s16le - | ccb stt`);
100
+ return;
101
+ }
102
+ // Handled before createClient(): stt reads the login inside the stream, and
103
+ // building a client up front would turn "not signed in" into a crash before
104
+ // `stt --check` could answer it calmly.
105
+ if (module === 'stt') {
106
+ const code = await sttCommand(subcommand, args, flags, jsonOutput);
107
+ if (code !== 0)
108
+ process.exit(code);
51
109
  return;
52
110
  }
53
111
  const client = await createClient();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,oBAAoB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACxF,MAAM,OAAO,GAAW,GAAG,CAAC,OAAO,CAAC;AAEpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACrE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACvC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAEzG,KAAK,UAAU,YAAY;IACzB,MAAM,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC;IACpG,MAAM,KAAK,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAC1C,OAAO,IAAI,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,GAAG;IAChB,MAAM,CAAC,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC;IAExC,IAAI,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5E,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,MAAM,KAAK,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,EAAE,CAAC;QAC5H,MAAM,IAAI,QAAQ,CAAC,iDAAiD,EAAE,kBAAkB,CAAC,CAAC;IAC5F,CAAC;IAED,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9C,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,QAAQ,OAAO;;;;;;;;;;;;;gCAaC,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;IAEpC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,MAAM,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;YACnD,MAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;YAC3C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAClB,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;gBAC3B,KAAK,EAAE;oBACL,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBAC1D;aACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACf,CAAC;IACH,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YACvC,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * `ccb stt` — dictation as a process, not as a library.
3
+ *
4
+ * The plugin cannot call {@link openSpeechToTextStream} directly. Transcribing
5
+ * reads the machine's Claude Code login, and importing this package into the
6
+ * backend would put that read inside the plugin's own process — the exact thing
7
+ * that moved these tools out to a separate package. Spawning instead keeps the
8
+ * token on this side of the process boundary: the caller writes audio and reads
9
+ * text, and never holds a credential.
10
+ *
11
+ * So the wire format here is the public contract, the same way `oauth usage
12
+ * --json` is. A terminal user can drive it by hand:
13
+ *
14
+ * ffmpeg -f avfoundation -i ':0' -ar 16000 -ac 1 -f s16le - | ccb stt
15
+ *
16
+ * ── stdin ── raw PCM: 16-bit little-endian, 16 kHz, mono. Nothing else is
17
+ * accepted, and a wrong format transcribes to silence rather than
18
+ * failing (see CLAUDE.md), so the caller must convert first.
19
+ * ── stdout ── one JSON object per line, flushed as it happens.
20
+ * ── exit ─── 0 when the speaker finished, 1 when the stream failed to open.
21
+ */
22
+ /** Line-oriented events written to stdout. */
23
+ export declare enum SttEventType {
24
+ /** The socket is open and audio is being transcribed. */
25
+ Open = "open",
26
+ /** Text arrived. `isFinal` false will be replaced by a later line. */
27
+ Transcript = "transcript",
28
+ /** The stream failed. `fatal` means retrying will not help. */
29
+ Error = "error"
30
+ }
31
+ /**
32
+ * Entry point for the `stt` module of the CLI.
33
+ *
34
+ * Takes no {@link ClaudeCodeClient}: unlike `oauth`, this command reads the
35
+ * login itself inside the stream, and building a client up front would turn
36
+ * "not signed in" into a crash before `--check` could answer it.
37
+ */
38
+ export declare function sttCommand(subcommand: string[], args: string[], flags: Set<string>, jsonOutput: boolean): Promise<number>;
@@ -0,0 +1,154 @@
1
+ import { openSpeechToTextStream, isSpeechToTextAvailable } from '../stt/index.js';
2
+ import { CcbError } from '../battery/errors.js';
3
+ /**
4
+ * `ccb stt` — dictation as a process, not as a library.
5
+ *
6
+ * The plugin cannot call {@link openSpeechToTextStream} directly. Transcribing
7
+ * reads the machine's Claude Code login, and importing this package into the
8
+ * backend would put that read inside the plugin's own process — the exact thing
9
+ * that moved these tools out to a separate package. Spawning instead keeps the
10
+ * token on this side of the process boundary: the caller writes audio and reads
11
+ * text, and never holds a credential.
12
+ *
13
+ * So the wire format here is the public contract, the same way `oauth usage
14
+ * --json` is. A terminal user can drive it by hand:
15
+ *
16
+ * ffmpeg -f avfoundation -i ':0' -ar 16000 -ac 1 -f s16le - | ccb stt
17
+ *
18
+ * ── stdin ── raw PCM: 16-bit little-endian, 16 kHz, mono. Nothing else is
19
+ * accepted, and a wrong format transcribes to silence rather than
20
+ * failing (see CLAUDE.md), so the caller must convert first.
21
+ * ── stdout ── one JSON object per line, flushed as it happens.
22
+ * ── exit ─── 0 when the speaker finished, 1 when the stream failed to open.
23
+ */
24
+ /** Line-oriented events written to stdout. */
25
+ export var SttEventType;
26
+ (function (SttEventType) {
27
+ /** The socket is open and audio is being transcribed. */
28
+ SttEventType["Open"] = "open";
29
+ /** Text arrived. `isFinal` false will be replaced by a later line. */
30
+ SttEventType["Transcript"] = "transcript";
31
+ /** The stream failed. `fatal` means retrying will not help. */
32
+ SttEventType["Error"] = "error";
33
+ })(SttEventType || (SttEventType = {}));
34
+ /**
35
+ * Write one event as a single line.
36
+ *
37
+ * `process.stdout.write` rather than `console.log` because the caller parses
38
+ * this by newline: console.log is the same thing here, but going through the
39
+ * stream directly makes it explicit that one call must produce exactly one line
40
+ * and that nothing else may ever be printed to stdout by this command.
41
+ */
42
+ function emit(event) {
43
+ process.stdout.write(`${JSON.stringify(event)}\n`);
44
+ }
45
+ /** Split a `--keyterms=a,b,c` value, dropping empties and surrounding spaces. */
46
+ function parseKeyterms(raw) {
47
+ if (!raw)
48
+ return [];
49
+ return raw
50
+ .split(',')
51
+ .map((term) => term.trim())
52
+ .filter(Boolean);
53
+ }
54
+ /**
55
+ * `ccb stt --check --json` — can this machine dictate at all?
56
+ *
57
+ * Separate from opening a stream because the answer drives different UI: a
58
+ * machine with no Claude Code login should be told to sign in, not shown a
59
+ * socket error. Always exits 0; "no" is an answer rather than a failure.
60
+ */
61
+ async function checkAvailability(jsonOutput) {
62
+ const available = await isSpeechToTextAvailable().catch(() => false);
63
+ if (jsonOutput) {
64
+ console.log(JSON.stringify({ available }));
65
+ return;
66
+ }
67
+ console.log(available ? 'available' : 'unavailable (no Claude Code login on this machine)');
68
+ }
69
+ /**
70
+ * Open the stream and pump stdin into it until the caller stops writing.
71
+ *
72
+ * Audio written before the socket finishes opening is not lost: the stream
73
+ * buffers pre-open chunks itself, which matters more here than in-process
74
+ * because a pipe delivers the caller's first chunk almost immediately.
75
+ */
76
+ async function runStream(options) {
77
+ if (process.stdin.isTTY) {
78
+ console.error('ccb stt reads raw PCM audio (16-bit LE, 16 kHz, mono) on stdin; pipe audio into it.');
79
+ return 1;
80
+ }
81
+ let stream;
82
+ try {
83
+ stream = await openSpeechToTextStream({
84
+ onTranscript: (text, isFinal) => emit({ type: SttEventType.Transcript, text, isFinal }),
85
+ onError: (message, info) => emit({ type: SttEventType.Error, message, fatal: info?.fatal ?? false }),
86
+ onOpen: () => emit({ type: SttEventType.Open }),
87
+ }, {
88
+ language: options.language,
89
+ extraKeyterms: options.extraKeyterms,
90
+ typedInterims: options.typedInterims,
91
+ });
92
+ }
93
+ catch (err) {
94
+ // Failing to open is reported on the same channel as everything else, so a
95
+ // caller parsing stdout never has to also watch stderr to learn why
96
+ // dictation did not start. A rejected login lands here.
97
+ emit({
98
+ type: SttEventType.Error,
99
+ message: err instanceof Error ? err.message : String(err),
100
+ fatal: true,
101
+ });
102
+ return 1;
103
+ }
104
+ return new Promise((resolve) => {
105
+ let finished = false;
106
+ /**
107
+ * Close once, then exit.
108
+ *
109
+ * `close()` waits for the service to flush the last words, so the trailing
110
+ * transcript is emitted before this resolves. Called from both stdin end
111
+ * and a termination signal, hence the guard.
112
+ */
113
+ const finish = () => {
114
+ if (finished)
115
+ return;
116
+ finished = true;
117
+ stream
118
+ .close()
119
+ .then(() => resolve(0))
120
+ .catch(() => resolve(0));
121
+ };
122
+ process.stdin.on('data', (chunk) => {
123
+ stream.sendAudio(new Uint8Array(chunk));
124
+ });
125
+ process.stdin.on('end', finish);
126
+ // A parent that kills us instead of closing stdin still gets the last words.
127
+ process.on('SIGTERM', finish);
128
+ process.on('SIGINT', finish);
129
+ });
130
+ }
131
+ /**
132
+ * Entry point for the `stt` module of the CLI.
133
+ *
134
+ * Takes no {@link ClaudeCodeClient}: unlike `oauth`, this command reads the
135
+ * login itself inside the stream, and building a client up front would turn
136
+ * "not signed in" into a crash before `--check` could answer it.
137
+ */
138
+ export async function sttCommand(subcommand, args, flags, jsonOutput) {
139
+ if (flags.has('--check') || subcommand[0] === 'check') {
140
+ await checkAvailability(jsonOutput);
141
+ return 0;
142
+ }
143
+ if (subcommand.length > 0) {
144
+ throw new CcbError(`Unknown stt subcommand: ${subcommand[0]}`, 'invalid_argument');
145
+ }
146
+ const language = args.find((arg) => arg.startsWith('--language='))?.slice('--language='.length);
147
+ const keyterms = args.find((arg) => arg.startsWith('--keyterms='))?.slice('--keyterms='.length);
148
+ return runStream({
149
+ language,
150
+ extraKeyterms: parseKeyterms(keyterms),
151
+ typedInterims: flags.has('--interims'),
152
+ });
153
+ }
154
+ //# sourceMappingURL=stt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt.js","sourceRoot":"","sources":["../../src/cli/stt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * The `env` block of Claude Code's settings files, applied the way `claude` applies it.
3
+ *
4
+ * `claude` reads its own settings files and puts their `env` block into the environment
5
+ * before it talks to anything. Nothing else on the machine does that — a variable written
6
+ * only into settings.json never becomes a real environment variable — so a tool that reads
7
+ * `process.env` alone sees a different configuration than `claude` does on the same machine.
8
+ *
9
+ * That difference is not hypothetical. It broke the usage panel twice: once for a proxy set
10
+ * only in settings.json, and again for the lower-case spelling of the same variable. Both
11
+ * times the fix was to name one more variable somewhere. This module reads the block whole
12
+ * instead, so the next variable needs no fix at all.
13
+ *
14
+ * The rules below were measured against `claude` 2.1.261 by writing six shapes of value into
15
+ * a project's settings.json and reading back what its child process received:
16
+ *
17
+ * "PLAIN": "value" → value (passed through)
18
+ * "BRACE": "pre-${HOME}-post" → pre-${HOME}-post (NOT expanded)
19
+ * "FALL": "${UNSET:-fb}" → ${UNSET:-fb} (NOT expanded)
20
+ * "EMPTY": "" → empty, still set (not a deletion)
21
+ * "NUMBER": 1234 → "1234" (stringified)
22
+ * "BOOL": true → "true" (stringified)
23
+ */
24
+ /**
25
+ * Where Claude Code keeps its settings and credentials.
26
+ *
27
+ * Read from the environment, never from a settings file — see {@link EXCLUDED_NAMES}.
28
+ */
29
+ export declare function claudeConfigDir(): string;
30
+ /**
31
+ * Every variable the settings files set, merged global-to-project.
32
+ *
33
+ * Returned rather than applied so a caller can see the block without changing the process,
34
+ * which is how the tests read it.
35
+ */
36
+ export declare function readSettingsEnv(projectDir?: string): Promise<Record<string, string>>;
37
+ /**
38
+ * Put the settings files' `env` block into this process's environment.
39
+ *
40
+ * The settings value wins over whatever this process inherited, because that is what `claude`
41
+ * does: with the same name exported in the shell and written into settings.json, the value its
42
+ * child received was the settings one. Matching that is the whole point — the user edits that
43
+ * file for `claude`, so `claude` is the behaviour to agree with.
44
+ *
45
+ * A value forced on the command line is the one thing that outranks this, and it is read from
46
+ * the flag that carries it rather than from here: an assignment written in front of a command
47
+ * is indistinguishable from an inherited variable by the time it arrives, so a flag is the only
48
+ * way a caller can say "this one, whatever the files say".
49
+ */
50
+ export declare function applySettingsEnv(projectDir?: string): Promise<void>;
@@ -0,0 +1,142 @@
1
+ /**
2
+ * The `env` block of Claude Code's settings files, applied the way `claude` applies it.
3
+ *
4
+ * `claude` reads its own settings files and puts their `env` block into the environment
5
+ * before it talks to anything. Nothing else on the machine does that — a variable written
6
+ * only into settings.json never becomes a real environment variable — so a tool that reads
7
+ * `process.env` alone sees a different configuration than `claude` does on the same machine.
8
+ *
9
+ * That difference is not hypothetical. It broke the usage panel twice: once for a proxy set
10
+ * only in settings.json, and again for the lower-case spelling of the same variable. Both
11
+ * times the fix was to name one more variable somewhere. This module reads the block whole
12
+ * instead, so the next variable needs no fix at all.
13
+ *
14
+ * The rules below were measured against `claude` 2.1.261 by writing six shapes of value into
15
+ * a project's settings.json and reading back what its child process received:
16
+ *
17
+ * "PLAIN": "value" → value (passed through)
18
+ * "BRACE": "pre-${HOME}-post" → pre-${HOME}-post (NOT expanded)
19
+ * "FALL": "${UNSET:-fb}" → ${UNSET:-fb} (NOT expanded)
20
+ * "EMPTY": "" → empty, still set (not a deletion)
21
+ * "NUMBER": 1234 → "1234" (stringified)
22
+ * "BOOL": true → "true" (stringified)
23
+ */
24
+ import { readFile } from 'node:fs/promises';
25
+ import { homedir } from 'node:os';
26
+ import { join } from 'node:path';
27
+ /**
28
+ * Where Claude Code keeps its settings and credentials.
29
+ *
30
+ * Read from the environment, never from a settings file — see {@link EXCLUDED_NAMES}.
31
+ */
32
+ export function claudeConfigDir() {
33
+ return process.env['CLAUDE_CONFIG_DIR'] ?? join(homedir(), '.claude');
34
+ }
35
+ /**
36
+ * Names this module refuses to take from a settings file.
37
+ *
38
+ * `CLAUDE_CONFIG_DIR` decides WHERE the settings file is. Reading it back out of that file
39
+ * would mean the file's location depends on a value only readable after the file is found,
40
+ * so the value is honoured from the environment only. The plugin that spawns this CLI settles
41
+ * it the same way: it keeps that one variable in its own settings and passes it in.
42
+ */
43
+ const EXCLUDED_NAMES = new Set(['CLAUDE_CONFIG_DIR']);
44
+ /**
45
+ * The settings files, in the order `claude` layers them — later wins.
46
+ *
47
+ * The project pair is dropped when no project directory is known, which is what a bare
48
+ * `ccb` in a directory with no `.claude` folder amounts to anyway.
49
+ */
50
+ function settingsFiles(projectDir) {
51
+ const configDir = claudeConfigDir();
52
+ const files = [
53
+ join(configDir, 'settings.json'),
54
+ join(configDir, 'settings.local.json'),
55
+ ];
56
+ if (projectDir) {
57
+ files.push(join(projectDir, '.claude', 'settings.json'), join(projectDir, '.claude', 'settings.local.json'));
58
+ }
59
+ return files;
60
+ }
61
+ /**
62
+ * One value as an environment variable, or null when it cannot be one.
63
+ *
64
+ * Numbers and booleans are stringified because `claude` passes them on stringified. An empty
65
+ * string is a value, not a removal — also measured.
66
+ *
67
+ * Objects, arrays and null are skipped. `claude`'s handling of those was NOT measured, and
68
+ * the alternatives are worse than skipping: `String({})` is the literal "[object Object]",
69
+ * which is a value no one meant to set.
70
+ */
71
+ function asEnvValue(value) {
72
+ if (typeof value === 'string')
73
+ return value;
74
+ if (typeof value === 'number' && Number.isFinite(value))
75
+ return String(value);
76
+ if (typeof value === 'boolean')
77
+ return String(value);
78
+ return null;
79
+ }
80
+ /** The `env` object of one settings file, or an empty object when there is not one. */
81
+ async function readEnvBlock(filePath) {
82
+ let raw;
83
+ try {
84
+ raw = await readFile(filePath, 'utf-8');
85
+ }
86
+ catch {
87
+ // A settings file that does not exist is the normal case, not a failure.
88
+ return {};
89
+ }
90
+ try {
91
+ const parsed = JSON.parse(raw);
92
+ const env = parsed.env;
93
+ if (!env || typeof env !== 'object' || Array.isArray(env))
94
+ return {};
95
+ return env;
96
+ }
97
+ catch {
98
+ // A settings file we cannot parse is the user's to fix. Failing the whole command over
99
+ // it would take away the usage panel and dictation for a stray comma.
100
+ return {};
101
+ }
102
+ }
103
+ /**
104
+ * Every variable the settings files set, merged global-to-project.
105
+ *
106
+ * Returned rather than applied so a caller can see the block without changing the process,
107
+ * which is how the tests read it.
108
+ */
109
+ export async function readSettingsEnv(projectDir) {
110
+ const merged = {};
111
+ for (const filePath of settingsFiles(projectDir)) {
112
+ const block = await readEnvBlock(filePath);
113
+ for (const [name, value] of Object.entries(block)) {
114
+ if (EXCLUDED_NAMES.has(name))
115
+ continue;
116
+ const asValue = asEnvValue(value);
117
+ if (asValue !== null)
118
+ merged[name] = asValue;
119
+ }
120
+ }
121
+ return merged;
122
+ }
123
+ /**
124
+ * Put the settings files' `env` block into this process's environment.
125
+ *
126
+ * The settings value wins over whatever this process inherited, because that is what `claude`
127
+ * does: with the same name exported in the shell and written into settings.json, the value its
128
+ * child received was the settings one. Matching that is the whole point — the user edits that
129
+ * file for `claude`, so `claude` is the behaviour to agree with.
130
+ *
131
+ * A value forced on the command line is the one thing that outranks this, and it is read from
132
+ * the flag that carries it rather than from here: an assignment written in front of a command
133
+ * is indistinguishable from an inherited variable by the time it arrives, so a flag is the only
134
+ * way a caller can say "this one, whatever the files say".
135
+ */
136
+ export async function applySettingsEnv(projectDir = process.cwd()) {
137
+ const settingsEnv = await readSettingsEnv(projectDir);
138
+ for (const [name, value] of Object.entries(settingsEnv)) {
139
+ process.env[name] = value;
140
+ }
141
+ }
142
+ //# sourceMappingURL=settings-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings-env.js","sourceRoot":"","sources":["../src/settings-env.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import WebSocket from 'ws';
2
- import { getCredentials, getAccessToken } from '../battery/auth/index.js';
2
+ import { getCredentials, getAccessToken, isTokenExpired } from '../battery/auth/index.js';
3
3
  import { CcbError } from '../battery/errors.js';
4
4
  import { proxyAgentFor } from '../proxy.js';
5
5
  import { DEFAULT_KEYTERMS, packKeyterms } from './keyterms.js';
@@ -222,8 +222,14 @@ export async function openSpeechToTextStream(handlers, options = {}, token) {
222
222
  */
223
223
  export async function isSpeechToTextAvailable() {
224
224
  try {
225
- getAccessToken(await getCredentials());
226
- return true;
225
+ const credentials = await getCredentials();
226
+ getAccessToken(credentials);
227
+ // An expired login answers "yes, you can dictate" and then fails the handshake with a
228
+ // 401 the caller has no way to explain. Somebody who signed in months ago and stopped
229
+ // has exactly that on disk: a credentials file, holding a token the server will refuse.
230
+ // Reading the expiry here turns that into "sign in first", which is the truth and is
231
+ // also something the user can act on.
232
+ return !isTokenExpired(credentials);
227
233
  }
228
234
  catch (err) {
229
235
  if (err instanceof CcbError)
@@ -1 +1 @@
1
- {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stt/stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stream.js","sourceRoot":"","sources":["../../src/stt/stream.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swttch/extend-kit",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "Companion tools for Swttch that live outside the plugin bundle: Claude Code account/usage SDK, the ccb CLI, and speech-to-text.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",