@bridge4dev/runner 0.65.1 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/account-commands.d.ts +44 -0
- package/dist/account-commands.js +99 -0
- package/dist/adapters/claude-usage.d.ts +79 -15
- package/dist/adapters/claude-usage.js +143 -67
- package/dist/adapters/claude.d.ts +30 -1
- package/dist/adapters/claude.js +171 -11
- package/dist/adapters/types.d.ts +22 -0
- package/dist/agent-auth.d.ts +87 -0
- package/dist/agent-auth.js +249 -15
- package/dist/auth-relay.d.ts +110 -26
- package/dist/auth-relay.js +339 -232
- package/dist/claude-homes.d.ts +436 -0
- package/dist/claude-homes.js +1567 -0
- package/dist/commit-message.js +4 -1
- package/dist/config.d.ts +14 -14
- package/dist/index.js +53 -1
- package/dist/login-marks.d.ts +31 -0
- package/dist/login-marks.js +47 -0
- package/dist/protocol.d.ts +38 -38
- package/dist/protocol.js +3 -1
- package/dist/supervisor.js +17 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { type ClaudeIdentity } from './agent-auth.js';
|
|
2
|
+
import { type UsageReading, type UsageRow, type UsageSignature } from './adapters/claude-usage.js';
|
|
3
|
+
/**
|
|
4
|
+
* Several Claude logins on one machine – one HOME per account (#422, D1).
|
|
5
|
+
*
|
|
6
|
+
* An account is a small directory of its own: its login (`.credentials.json`)
|
|
7
|
+
* and the CLI's working files (`.claude.json` – where the last measured limits
|
|
8
|
+
* live – `sessions/`, `backups/`). Everything else is a link into the machine's
|
|
9
|
+
* `~/.claude`: the transcripts (without them no conversation resumes across
|
|
10
|
+
* accounts), settings, plugins, agents, commands, hooks, skills. Switching is
|
|
11
|
+
* choosing which home the NEXT session starts with – `CLAUDE_CONFIG_DIR` in the
|
|
12
|
+
* session's own environment, never in the daemon's (risk К1 of the plan).
|
|
13
|
+
*
|
|
14
|
+
* The login of this machine is the default home, `~/.claude`. It is the first
|
|
15
|
+
* row, it cannot be forgotten, and while it is active nothing here sets any
|
|
16
|
+
* variable – the behaviour is exactly the pre-#422 one. No code in this module
|
|
17
|
+
* writes, moves or deletes the machine's own login file: the one legitimate way
|
|
18
|
+
* to touch it stays the person's «Log in again» on that row, which is the old
|
|
19
|
+
* sign-in path in `auth-relay.ts`, not this file.
|
|
20
|
+
*
|
|
21
|
+
* NOT ONE COPY of a login file, by construction rather than by agreement. The
|
|
22
|
+
* CLI's token-refresh lock is taken by the PATH of the file, so a copy in a
|
|
23
|
+
* second home is a second holder of a one-time refresh token – the copy that
|
|
24
|
+
* signed out 47 agents and four sessions on 08.09.2026 (gotcha 460). Every
|
|
25
|
+
* login here exists in exactly one place; a login is only ever moved into its
|
|
26
|
+
* home by `rename`, and a `rename` that would have to cross filesystems is
|
|
27
|
+
* refused instead of falling back to a copy.
|
|
28
|
+
*
|
|
29
|
+
* Proven live on this machine before a line of it was written (S1 item 1,
|
|
30
|
+
* 17.09.2026, CLI 2.1.273, SDK 0.3.226): a session started through the Agent
|
|
31
|
+
* SDK with `CLAUDE_CONFIG_DIR` in `env` ran under that home's subscription, its
|
|
32
|
+
* transcript landed in the machine's `projects/` through the link, and the
|
|
33
|
+
* same session resumed under the machine login – a different subscription –
|
|
34
|
+
* and back again, with its context.
|
|
35
|
+
*/
|
|
36
|
+
/** Where the saved homes live – next to the runner's other private state. */
|
|
37
|
+
export declare function claudeHomesDir(): string;
|
|
38
|
+
/**
|
|
39
|
+
* The machine's own Claude home. `os.homedir()` rather than anything cleverer:
|
|
40
|
+
* it is what the CLI itself uses when no `CLAUDE_CONFIG_DIR` is set, which is
|
|
41
|
+
* exactly the definition of «the machine login».
|
|
42
|
+
*/
|
|
43
|
+
export declare function machineHome(homedir?: string): string;
|
|
44
|
+
/** A saved account's id: twelve lowercase letters and digits, never `machine`. */
|
|
45
|
+
export declare function isAccountId(id: unknown): id is string;
|
|
46
|
+
/** The home of a saved account. Throws on anything that is not an account id. */
|
|
47
|
+
export declare function accountHome(id: string): string;
|
|
48
|
+
/** A refusal meant for a person: the wire (S2) sends its message as it is. */
|
|
49
|
+
export declare class AccountError extends Error {
|
|
50
|
+
constructor(message: string);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* What a saved home reaches through a link rather than owning (R20).
|
|
54
|
+
*
|
|
55
|
+
* `projects` is the one that must never be missing: it is where transcripts
|
|
56
|
+
* live, and a session resumes only from the home it can see them in. The rest
|
|
57
|
+
* is parity with the terminal – the machine's settings (hooks, the search
|
|
58
|
+
* guard, enabled plugins), its plugins, agents, commands, hooks and skills.
|
|
59
|
+
* Deliberately NOT here: `.credentials.json` and `.claude.json` (they are the
|
|
60
|
+
* account), and the CLI's per-process scratch (`sessions`, `session-env`,
|
|
61
|
+
* `shell-snapshots`, `backups`, …), which it recreates on its own.
|
|
62
|
+
*/
|
|
63
|
+
export declare const SHARED_ENTRIES: readonly ["projects", "settings.json", "settings.local.json", "CLAUDE.md", "plugins", "agents", "commands", "hooks", "skills"];
|
|
64
|
+
export interface SharedLinkChange {
|
|
65
|
+
name: string;
|
|
66
|
+
action: 'linked' | 'relinked' | 'displaced' | 'dropped';
|
|
67
|
+
/** Where a file that stood in place of the link was moved to. */
|
|
68
|
+
displacedTo?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create and repair the links of a saved home into the machine's `~/.claude`.
|
|
72
|
+
*
|
|
73
|
+
* A link is set only where its target exists; `projects` is the exception and
|
|
74
|
+
* gets its target created, because a home without it would quietly start a
|
|
75
|
+
* transcript directory of its own and every later resume across accounts would
|
|
76
|
+
* fail to find the conversation.
|
|
77
|
+
*
|
|
78
|
+
* A link the CLI replaced with a real file or directory (an atomic write of
|
|
79
|
+
* `settings.json` does exactly that) is NOT silently re-linked: the thing in
|
|
80
|
+
* its place may be the only copy of what was written through it. It is moved
|
|
81
|
+
* aside under a dated name and logged, and the link is put back.
|
|
82
|
+
*
|
|
83
|
+
* Never follows a link to remove anything, never writes into the machine home
|
|
84
|
+
* beyond creating its empty `projects/`.
|
|
85
|
+
*/
|
|
86
|
+
export declare function ensureSharedLinks(home: string, machine?: string): SharedLinkChange[];
|
|
87
|
+
/**
|
|
88
|
+
* Seed a home's `.claude.json` with the machine's configuration (R20).
|
|
89
|
+
*
|
|
90
|
+
* A home without the file gets one. A home WITH one (a login moved in from
|
|
91
|
+
* elsewhere) gets only the keys it does not have yet, project by project – its
|
|
92
|
+
* own identity and anything it configured for itself stay as they are.
|
|
93
|
+
*
|
|
94
|
+
* Only for a home no CLI is running in: the CLI rewrites this file on its own
|
|
95
|
+
* schedule, and a write racing it would lose one side. That is why it runs when
|
|
96
|
+
* a home is created or moved in, and not at every session start.
|
|
97
|
+
*/
|
|
98
|
+
export declare function ensureHomeConfig(home: string, machineConfig?: string): 'created' | 'merged' | 'unchanged';
|
|
99
|
+
/** What `claude auth status` says about a home – without a verdict on the login. */
|
|
100
|
+
export interface AccountIdentity {
|
|
101
|
+
email?: string;
|
|
102
|
+
orgId?: string;
|
|
103
|
+
orgName?: string;
|
|
104
|
+
plan?: string;
|
|
105
|
+
}
|
|
106
|
+
/** Runs `claude auth status` in a home. Replaced only by tests. */
|
|
107
|
+
export type IdentityRunner = (home: string | null) => Promise<AccountIdentity | null>;
|
|
108
|
+
/**
|
|
109
|
+
* The environment `claude auth status` runs with (R14) – and, since S2, every
|
|
110
|
+
* CLI run that works in a home as that home's own account: the sign-in through
|
|
111
|
+
* `agent_account_login_start` uses it too (§8), for the reason below.
|
|
112
|
+
*
|
|
113
|
+
* `CLAUDE_CONFIG_DIR` of the home, or none for the machine, and never the
|
|
114
|
+
* operator's `CLAUDE_CODE_OAUTH_TOKEN`: the CLI puts that variable above every
|
|
115
|
+
* login file, so on a machine that has one every home would answer with the
|
|
116
|
+
* token's blind identity – no e-mail, no plan, the same for all of them.
|
|
117
|
+
*/
|
|
118
|
+
export declare function identityProbeEnv(home: string | null, base?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
119
|
+
/** `claude auth status --json` → identity. `loggedIn: false` is no identity at all. */
|
|
120
|
+
export declare function parseAuthStatus(output: string): AccountIdentity | null;
|
|
121
|
+
export declare function setIdentityRunner(run: IdentityRunner | null): void;
|
|
122
|
+
/** Ask a home who it is. Only the four callers R14 names reach this. */
|
|
123
|
+
export declare function readAccountIdentity(home: string | null): Promise<AccountIdentity | null>;
|
|
124
|
+
/** Forget remembered misses – tests. */
|
|
125
|
+
export declare function resetIdentityMisses(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Who a row is, from the cache or – when that is unknown, old, or contradicted by
|
|
128
|
+
* the home – from `claude auth status` in its home, persisted (R14).
|
|
129
|
+
*
|
|
130
|
+
* A probe that answers nothing keeps what was known: a CLI that timed out once
|
|
131
|
+
* must not turn a named account into «card not filled». And it is remembered for
|
|
132
|
+
* a while, so a home with no identity to give is not asked at every session start.
|
|
133
|
+
*/
|
|
134
|
+
export declare function refreshAccountIdentity(id: string, options?: {
|
|
135
|
+
force?: boolean;
|
|
136
|
+
}): Promise<ClaudeIdentity | null>;
|
|
137
|
+
/** What one credentials file says, before any fallback is consulted. */
|
|
138
|
+
export interface CredentialVerdict {
|
|
139
|
+
status: 'ok' | 'expired' | 'missing' | 'unknown';
|
|
140
|
+
expiresAt?: string;
|
|
141
|
+
detail?: string;
|
|
142
|
+
/**
|
|
143
|
+
* May a token this runner captured answer instead? Only where the pre-#422
|
|
144
|
+
* verdict consulted it: no file, nothing recognisable in it, or a dead login.
|
|
145
|
+
* Never over a file we could not parse or could not read.
|
|
146
|
+
*/
|
|
147
|
+
fallbackEligible: boolean;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Judge a Claude credentials file – moved here unchanged from `claudeAuthStatus`
|
|
151
|
+
* so a saved home and the machine are judged by the same lines (#422 R14).
|
|
152
|
+
*
|
|
153
|
+
* `expiresAt` is NOT the login. It is the expiry of a short-lived access token
|
|
154
|
+
* (~8 hours on a live file), and next to it sits `refreshToken` with
|
|
155
|
+
* `refreshTokenExpiresAt` ~26 days out, which the CLI spends silently on its
|
|
156
|
+
* next run. Judging the login by `expiresAt` alone is why every server nobody
|
|
157
|
+
* had touched since the morning reported "login expired — re-login needed"
|
|
158
|
+
* over a login that was good for another three weeks (#121). Codex has carried
|
|
159
|
+
* exactly this guard since day one (`readCodexCredential`); Claude did not.
|
|
160
|
+
*
|
|
161
|
+
* Deliberately NOT asking the CLI. `claude auth status --json` looks like an
|
|
162
|
+
* arbiter and is not one: measured live (SDK binary 2.1.218), it answers
|
|
163
|
+
* `loggedIn: true` for a credential whose access token has expired AND which
|
|
164
|
+
* carries no refresh token at all — i.e. for a genuinely dead login. It never
|
|
165
|
+
* leaves the machine, so it cannot see a server-side revocation either. It
|
|
166
|
+
* would have cost a ~800 ms / ~300 MB subprocess per poll under `MemoryMax=2G`
|
|
167
|
+
* (gotcha #100) and echoed the account's e-mail and org name to every member of
|
|
168
|
+
* the organization, in exchange for no truth at all. A revoked login is caught
|
|
169
|
+
* instead by the refusal marks — from a real refusal, not a guess.
|
|
170
|
+
*/
|
|
171
|
+
export declare function judgeCredentialFile(file: string): CredentialVerdict;
|
|
172
|
+
/** The verdict on one row, as the panel and the list both read it. */
|
|
173
|
+
export interface ClaudeLoginStatus {
|
|
174
|
+
status: 'ok' | 'expired' | 'missing' | 'unknown';
|
|
175
|
+
expiresAt?: string;
|
|
176
|
+
detail?: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The machine row: the pre-#422 verdict, word for word.
|
|
180
|
+
*
|
|
181
|
+
* The operator's variable first, then the credentials file, then a token this
|
|
182
|
+
* runner captured – the LAST word, never the first. Read from disk rather than
|
|
183
|
+
* from the environment, so `doctor` (a different process, which never applied
|
|
184
|
+
* it) gives the same verdict as the daemon.
|
|
185
|
+
*
|
|
186
|
+
* One change, from S1 item 3: a refusal no longer DISCARDS the captured token
|
|
187
|
+
* (the old discard erased the whole file, and with it every saved account). The
|
|
188
|
+
* refusal is kept as a mark instead, and a token captured after it outranks it.
|
|
189
|
+
*/
|
|
190
|
+
export declare function machineLoginStatus(homedir?: string): ClaudeLoginStatus;
|
|
191
|
+
/**
|
|
192
|
+
* Do the machine's Claude settings – which every saved home reads through its
|
|
193
|
+
* link – carry a credential that outranks a home's own login?
|
|
194
|
+
*
|
|
195
|
+
* `withAccountHome` takes the operator's token out of the PROCESS environment,
|
|
196
|
+
* but a settings file with `env: { CLAUDE_CODE_OAUTH_TOKEN }`, an API key or an
|
|
197
|
+
* `apiKeyHelper` puts one back inside the CLI, and a switch of account would
|
|
198
|
+
* then be a silent no-op under a green verdict – #121 once more (К14, found by
|
|
199
|
+
* the independent check of S1).
|
|
200
|
+
*/
|
|
201
|
+
export declare function machineSettingsOverrideLogin(machine?: string): boolean;
|
|
202
|
+
/**
|
|
203
|
+
* A saved row: its own file and nothing else (R14).
|
|
204
|
+
*
|
|
205
|
+
* No operator variable and no captured token – a session under a saved account
|
|
206
|
+
* has both taken out of its environment, so neither can make this row green.
|
|
207
|
+
* Anything short of a live login in the file is `expired`: the row stays in the
|
|
208
|
+
* list with that mark (D2), and «missing» would read as «never added».
|
|
209
|
+
*/
|
|
210
|
+
export declare function savedLoginStatus(id: string): ClaudeLoginStatus;
|
|
211
|
+
/**
|
|
212
|
+
* A session under this account was refused (D2): mark the row, remove nothing.
|
|
213
|
+
*
|
|
214
|
+
* By the id of the account the SESSION ran under, not «whatever is active now»
|
|
215
|
+
* (R14): a session started under A and refused after the machine was switched to
|
|
216
|
+
* B says nothing about B.
|
|
217
|
+
*/
|
|
218
|
+
export declare function markLoginExpired(id: string): void;
|
|
219
|
+
/** The account worked again. Writes only when there was a mark to clear. */
|
|
220
|
+
export declare function clearLoginExpired(id: string): void;
|
|
221
|
+
/**
|
|
222
|
+
* The account the next session starts under. Absent pointer: the machine login,
|
|
223
|
+
* which is how a pre-#422 file reads.
|
|
224
|
+
*
|
|
225
|
+
* A pointer to a row or a home that is gone reads as the machine too, and says
|
|
226
|
+
* so once – sessions and the verdict then agree on the same login instead of
|
|
227
|
+
* one of them running under a home the other cannot see.
|
|
228
|
+
*/
|
|
229
|
+
export declare function activeAccountId(): string;
|
|
230
|
+
/** Make a row active. `activate` leaves the usage cache alone: keys keep accounts apart (R16). */
|
|
231
|
+
export declare function setActiveAccount(id: string): string;
|
|
232
|
+
/** The account a session runs under – captured at its start and kept to its end (R14, R16). */
|
|
233
|
+
export interface SessionAccount {
|
|
234
|
+
id: string;
|
|
235
|
+
kind: 'machine' | 'saved';
|
|
236
|
+
/** `CLAUDE_CONFIG_DIR`; null for the machine login. */
|
|
237
|
+
home: string | null;
|
|
238
|
+
email?: string;
|
|
239
|
+
orgId?: string;
|
|
240
|
+
orgName?: string;
|
|
241
|
+
plan?: string;
|
|
242
|
+
}
|
|
243
|
+
/** Who a row is, for the verdict's `activeAccount` (§8) – from what is known, no CLI. */
|
|
244
|
+
export declare function readActiveAccountSummary(id: string): {
|
|
245
|
+
id: string;
|
|
246
|
+
email?: string;
|
|
247
|
+
orgId?: string;
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Which home a one-shot run of the agent should use – the active account, read
|
|
251
|
+
* only: no link repair, no identity. For the commit-message run, which is
|
|
252
|
+
* Claude working as the machine's active account too (found by the independent
|
|
253
|
+
* check of S1: it kept running as the machine login after a switch).
|
|
254
|
+
*/
|
|
255
|
+
export declare function activeAccountHome(): Pick<SessionAccount, 'kind' | 'home'>;
|
|
256
|
+
/**
|
|
257
|
+
* The active account, ready for a session to start under.
|
|
258
|
+
*
|
|
259
|
+
* A saved home has its links re-asserted first: a link the CLI replaced with a
|
|
260
|
+
* file since the last session is repaired before this session can write through
|
|
261
|
+
* the gap (it would otherwise resume nothing and share nothing).
|
|
262
|
+
*/
|
|
263
|
+
export declare function resolveSessionAccount(): SessionAccount;
|
|
264
|
+
/**
|
|
265
|
+
* The environment of a process that works AS this account.
|
|
266
|
+
*
|
|
267
|
+
* For a saved account: its home, and nothing that outranks the home. The CLI
|
|
268
|
+
* puts `CLAUDE_CODE_OAUTH_TOKEN` above every login file, so with the operator's
|
|
269
|
+
* token left in, switching would be a silent no-op under a green verdict – #121
|
|
270
|
+
* again (К14). The API keys go for the same reason.
|
|
271
|
+
*
|
|
272
|
+
* For the machine login: the input as it was, minus a `CLAUDE_CONFIG_DIR` that
|
|
273
|
+
* would point it elsewhere – the pre-#422 environment.
|
|
274
|
+
*/
|
|
275
|
+
export declare function withAccountHome<T extends Record<string, string | undefined>>(env: T, account: Pick<SessionAccount, 'kind' | 'home'>): T;
|
|
276
|
+
/**
|
|
277
|
+
* Who a home's `/usage` reading belongs to, read right after the probe (S1 item 5).
|
|
278
|
+
*
|
|
279
|
+
* `accountUuid` is where the CLI itself signs its figures; `organizationUuid` is
|
|
280
|
+
* the same key `claude auth status` calls `orgId` (checked on both homes of this
|
|
281
|
+
* machine, 17.09.2026). An internal file, so best-effort: nothing read, nothing
|
|
282
|
+
* signed.
|
|
283
|
+
*/
|
|
284
|
+
export declare function usageSignature(account: Pick<SessionAccount, 'home'>): UsageSignature;
|
|
285
|
+
/**
|
|
286
|
+
* The subscription a home's own file names at this moment (S2, found by the
|
|
287
|
+
* independent check): a live session signs its limits with the subscription it
|
|
288
|
+
* STARTED under, and has to notice when somebody signed the home in to another
|
|
289
|
+
* one – the CLI moves the running process onto the new login by path (gotcha
|
|
290
|
+
* 531). Cheap enough for every frame: a `stat`, and a parse only after a write.
|
|
291
|
+
*/
|
|
292
|
+
export declare function currentHomeOrgId(home: string | null): string | undefined;
|
|
293
|
+
/**
|
|
294
|
+
* The limits the CLI last measured in a home, from its own `.claude.json` (R19).
|
|
295
|
+
*
|
|
296
|
+
* Only for the line «when measured»: an internal file, rewritten by any update
|
|
297
|
+
* of the CLI (§11). Accepted only when it is signed by the account the same file
|
|
298
|
+
* says it belongs to – half-way through a re-login the two can disagree, and a
|
|
299
|
+
* number under the wrong name is worse than none.
|
|
300
|
+
*/
|
|
301
|
+
export declare function readLastUsage(home: string | null): UsageReading | null;
|
|
302
|
+
/** A session's process is starting under this account. */
|
|
303
|
+
export declare function noteSessionAccount(sessionId: string, accountId: string): void;
|
|
304
|
+
/** That process is gone. */
|
|
305
|
+
export declare function releaseSessionAccount(sessionId: string): void;
|
|
306
|
+
/** Accounts some live session process is running under right now. */
|
|
307
|
+
export declare function liveAccountIds(): Set<string>;
|
|
308
|
+
/**
|
|
309
|
+
* Finish a swap of homes the previous daemon did not finish (R15).
|
|
310
|
+
*
|
|
311
|
+
* A replacement moves the old home to `<id>.retired-<ts>` for the length of one
|
|
312
|
+
* call: long enough to put it back if the new login cannot take its place. A
|
|
313
|
+
* daemon that died inside that call leaves the name behind. If `<id>` is there,
|
|
314
|
+
* the swap went through and the retired home is the replaced login – removed. If
|
|
315
|
+
* `<id>` is missing, the swap did not happen – the retired home is put back,
|
|
316
|
+
* because it is the row's only login. Run at daemon start, when nothing runs.
|
|
317
|
+
*/
|
|
318
|
+
export declare function recoverInterruptedSwaps(): string[];
|
|
319
|
+
/** One row of the list, without a secret or a path to one (§8 `Card`). */
|
|
320
|
+
export interface AccountCard {
|
|
321
|
+
id: string;
|
|
322
|
+
kind: 'machine' | 'saved';
|
|
323
|
+
email?: string;
|
|
324
|
+
orgId?: string;
|
|
325
|
+
orgName?: string;
|
|
326
|
+
plan?: string;
|
|
327
|
+
/** Best-effort, from the home's `.claude.json` – e.g. `default_claude_max_20x`. */
|
|
328
|
+
tier?: string;
|
|
329
|
+
/** Always on a saved row; the machine login was never «added». */
|
|
330
|
+
addedAt?: string;
|
|
331
|
+
active: boolean;
|
|
332
|
+
login: 'ok' | 'expired' | 'unknown';
|
|
333
|
+
loginUntil?: string;
|
|
334
|
+
usage?: UsageRow[];
|
|
335
|
+
usageMeasuredAt?: string;
|
|
336
|
+
/** A saved row of the same subscription as the machine login (§2, scenarios). */
|
|
337
|
+
sameAsMachine?: true;
|
|
338
|
+
}
|
|
339
|
+
export interface AccountList {
|
|
340
|
+
accounts: AccountCard[];
|
|
341
|
+
active: string;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* The list, from what is already known – no subprocess (§8 `agent_accounts`
|
|
345
|
+
* reads this after `listAccounts` refreshed the identities).
|
|
346
|
+
*/
|
|
347
|
+
export declare function buildAccountList(homedir?: string): AccountList;
|
|
348
|
+
/**
|
|
349
|
+
* The list of Claude accounts on this machine (§8 `agent_accounts`).
|
|
350
|
+
*
|
|
351
|
+
* `probeIdentity` is the one place in the product where `claude auth status`
|
|
352
|
+
* runs on request (R14 a): home by home, one at a time, and only for a row whose
|
|
353
|
+
* known identity is older than its login file or than a few hours. Never from
|
|
354
|
+
* the minute poll – that reads the panel verdict, which asks no CLI.
|
|
355
|
+
*/
|
|
356
|
+
export declare function listAccounts(options?: {
|
|
357
|
+
probeIdentity?: boolean;
|
|
358
|
+
}): Promise<AccountList>;
|
|
359
|
+
/**
|
|
360
|
+
* A fresh home for a sign-in that has not happened yet (§8 `target: 'saved'`).
|
|
361
|
+
*
|
|
362
|
+
* Links and config first, so the CLI that signs in here writes its identity
|
|
363
|
+
* into a file that already has the machine's configuration. Hidden by its name:
|
|
364
|
+
* the list never shows a staging home, and an abandoned one older than an hour
|
|
365
|
+
* is removed the next time somebody starts a sign-in.
|
|
366
|
+
*/
|
|
367
|
+
export declare function prepareStagingHome(): string;
|
|
368
|
+
/**
|
|
369
|
+
* Remove every staging home, whatever its age – at daemon start, and only there.
|
|
370
|
+
*
|
|
371
|
+
* A sign-in whose code was accepted leaves the relay before its home is adopted
|
|
372
|
+
* (the identity is asked first, and waits in the machine-wide queue). A daemon
|
|
373
|
+
* that stops in that moment – «Update runner», a restart, an OOM – leaves a live
|
|
374
|
+
* login in a hidden home nobody lists, forgets or adopts; the hourly sweep in
|
|
375
|
+
* `prepareStagingHome` reaches it only when somebody next signs in (found by the
|
|
376
|
+
* independent check of S2). At start nothing can be adopting yet, so all of them go.
|
|
377
|
+
*/
|
|
378
|
+
export declare function discardAbandonedStagingHomes(): string[];
|
|
379
|
+
/** Throw a sign-in away, whatever state it reached – it may hold a login nobody adopted. */
|
|
380
|
+
export declare function discardStagingHome(dir: string): void;
|
|
381
|
+
export interface AdoptResult {
|
|
382
|
+
account: AccountCard;
|
|
383
|
+
active: string;
|
|
384
|
+
/** The saved row whose login this sign-in replaced – same subscription (D19). */
|
|
385
|
+
replaced?: string;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* A sign-in in a staging home succeeded: make it a saved account (§8
|
|
389
|
+
* `agent_account_login_code`).
|
|
390
|
+
*
|
|
391
|
+
* One subscription – one row (D19, R1). Identity is asked once, in the staging
|
|
392
|
+
* home, BEFORE anything moves (R14 b). A known `orgId` that a saved row already
|
|
393
|
+
* has REPLACES that row: the new login takes the row's id and `addedAt` (marks
|
|
394
|
+
* and a live session's reading are keyed by the id, R15) and the old login is
|
|
395
|
+
* deleted. An unknown `orgId` merges with nothing («card not filled»). The
|
|
396
|
+
* machine row takes no part: it is a different file, and a saved row of the same
|
|
397
|
+
* subscription is marked `sameAsMachine` instead of merged.
|
|
398
|
+
*
|
|
399
|
+
* A session running under the replaced row moves onto the new login at its next
|
|
400
|
+
* token refresh – the CLI finds its home by PATH, and the path now holds the new
|
|
401
|
+
* login. The plan (R15) asked to keep the old home renamed while such a session
|
|
402
|
+
* lives, «because the CLI writes its refreshed token into it»; the independent
|
|
403
|
+
* check of S1 read the CLI and showed it does not – a renamed home is never
|
|
404
|
+
* touched again, and keeping it would only keep an unused grant on disk. Both
|
|
405
|
+
* logins are of ONE subscription (that is what made them the same row), so the
|
|
406
|
+
* session keeps its account.
|
|
407
|
+
*
|
|
408
|
+
* Every move is a `rename`; the login is never in two places. A swap that cannot
|
|
409
|
+
* finish is undone – the old login goes back where it was. The row is recorded
|
|
410
|
+
* BEFORE a new home is moved into place, so a failed write never leaves a login
|
|
411
|
+
* nobody can list or forget. The signed-in row becomes active (R15).
|
|
412
|
+
*/
|
|
413
|
+
export declare function adoptLoginResult(stagingDir: string): Promise<AdoptResult>;
|
|
414
|
+
/**
|
|
415
|
+
* Bring a home that already holds a login into the store – by rename (D17, R7).
|
|
416
|
+
*
|
|
417
|
+
* For the one login this plan names: the probe's `/root/.probe-422/login/home`.
|
|
418
|
+
* Refused, rather than done by copy, when the rename would cross filesystems.
|
|
419
|
+
* Refused for the machine home and for anything already in the store, whatever
|
|
420
|
+
* the spelling of the path. Refused when a saved row of the same subscription
|
|
421
|
+
* exists (one subscription – one row, and nothing here is allowed to delete a
|
|
422
|
+
* login to make room). Recorded before it moves; never activates.
|
|
423
|
+
*/
|
|
424
|
+
export declare function importLoginHome(source: string): Promise<AccountCard>;
|
|
425
|
+
/**
|
|
426
|
+
* Forget a saved account: its home goes, its record goes (§8 `agent_account_forget`).
|
|
427
|
+
*
|
|
428
|
+
* The machine row cannot be forgotten. A row a live session runs under is
|
|
429
|
+
* refused – its process writes into that home until it ends. `rmSync` removes
|
|
430
|
+
* the links of the home as links: nothing in `~/.claude` is followed or touched.
|
|
431
|
+
* Forgetting the active row makes the machine login active.
|
|
432
|
+
*/
|
|
433
|
+
export declare function forgetAccount(id: string): {
|
|
434
|
+
active: string;
|
|
435
|
+
};
|
|
436
|
+
//# sourceMappingURL=claude-homes.d.ts.map
|