@hasna/accounts 0.1.15 → 0.1.17
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.md +34 -6
- package/dist/cli.js +107 -51
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +109 -48
- package/dist/lib/codex-app.d.ts +2 -0
- package/dist/lib/codex-app.d.ts.map +1 -0
- package/dist/lib/env.d.ts.map +1 -1
- package/dist/lib/tools.d.ts +3 -1
- package/dist/lib/tools.d.ts.map +1 -1
- package/dist/mcp.js +74 -14
- package/dist/storage.js +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @hasna/accounts
|
|
2
2
|
|
|
3
3
|
> Manage and switch between multiple AI coding tool profiles/accounts on one
|
|
4
|
-
> machine — Claude Code, Takumi, Codex CLI, Gemini CLI, opencode,
|
|
5
|
-
> Agent, Pi Coding Agent, Hermes, Kimi Code, Grok Build, and custom tools.
|
|
4
|
+
> machine — Claude Code, Takumi, Codex CLI, Codex App, Gemini CLI, opencode,
|
|
5
|
+
> Cursor Agent, Pi Coding Agent, Hermes, Kimi Code, Grok Build, and custom tools.
|
|
6
6
|
|
|
7
7
|
`accounts` is a local-first CLI. Each **profile** is an isolated config directory.
|
|
8
8
|
Switch **in the terminal** with `CLAUDE_CONFIG_DIR`, or **in Cursor / VS Code** with
|
|
@@ -11,9 +11,9 @@ Switch **in the terminal** with `CLAUDE_CONFIG_DIR`, or **in Cursor / VS Code**
|
|
|
11
11
|
- **Isolated profiles** — separate config dirs (skills, settings, sessions). Nothing leaks.
|
|
12
12
|
- **Apply mode** — sync OAuth / credentials to live paths for IDEs (Claude-only today).
|
|
13
13
|
- **Remembers the email** — auto-detected from `.claude.json` when possible.
|
|
14
|
-
- **Multi-tool** — first-class built-ins for Claude, Takumi, Codex,
|
|
15
|
-
opencode, Cursor Agent, Pi, Hermes, Kimi Code, and Grok Build;
|
|
16
|
-
via `accounts tools add`.
|
|
14
|
+
- **Multi-tool** — first-class built-ins for Claude, Takumi, Codex CLI, Codex
|
|
15
|
+
App, Gemini, opencode, Cursor Agent, Pi, Hermes, Kimi Code, and Grok Build;
|
|
16
|
+
custom tools via `accounts tools add`.
|
|
17
17
|
- **Per-tool names** — `work` can exist for Claude, Codex, Cursor, etc.; pass
|
|
18
18
|
`--tool` when a bare profile name is ambiguous.
|
|
19
19
|
- **Local-first** — registry at `~/.hasna/accounts/`. No network, no telemetry.
|
|
@@ -60,6 +60,30 @@ updates the detected email, and applies that profile to live `~/.claude` paths
|
|
|
60
60
|
automatically. `accounts apply` still refuses profiles without auth so live OAuth
|
|
61
61
|
is not wiped.
|
|
62
62
|
|
|
63
|
+
## Codex App profiles on macOS
|
|
64
|
+
|
|
65
|
+
Codex CLI profiles use `--tool codex`. The macOS desktop app needs its own tool
|
|
66
|
+
because it also needs an isolated Electron user data directory:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Create/sign into a desktop app profile. Quit Codex.app after login finishes.
|
|
70
|
+
accounts login personal --tool codex-app
|
|
71
|
+
accounts login work --tool codex-app
|
|
72
|
+
|
|
73
|
+
# Switch by launching the desired app profile.
|
|
74
|
+
accounts launch personal --tool codex-app
|
|
75
|
+
accounts launch work --tool codex-app
|
|
76
|
+
|
|
77
|
+
# Or print/launch the exact handoff command.
|
|
78
|
+
accounts switch work --tool codex-app
|
|
79
|
+
accounts switch work --tool codex-app --launch
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Each `codex-app` profile gets its own `CODEX_HOME` and
|
|
83
|
+
`--user-data-dir=<profile>/electron-user-data`. New profiles also get
|
|
84
|
+
`cli_auth_credentials_store = "file"` in `config.toml` so ChatGPT auth stays in
|
|
85
|
+
that profile directory instead of sharing one macOS Keychain credential.
|
|
86
|
+
|
|
63
87
|
## Three pointers (active, applied, isolated)
|
|
64
88
|
|
|
65
89
|
| Pointer / mode | Set by | Meaning |
|
|
@@ -224,9 +248,10 @@ JSON by default; auth snapshots stay local.
|
|
|
224
248
|
|
|
225
249
|
| Tool | id | Env var | Default dir |
|
|
226
250
|
|------|----|---------|-------------|
|
|
227
|
-
| Claude Code | `claude` | `CLAUDE_CONFIG_DIR` | `~/.claude` |
|
|
251
|
+
| Claude Code | `claude` | `CLAUDE_CONFIG_DIR`, `TELEGRAM_STATE_DIR` | `~/.claude` |
|
|
228
252
|
| Takumi | `takumi` | `TAKUMI_CONFIG_DIR` | `~/.takumi` |
|
|
229
253
|
| Codex CLI | `codex` | `CODEX_HOME` | `~/.codex` |
|
|
254
|
+
| Codex App | `codex-app` | `CODEX_HOME` + `--user-data-dir` | `~/.codex` |
|
|
230
255
|
| Gemini CLI | `gemini` | `GEMINI_CONFIG_DIR` | `~/.gemini` |
|
|
231
256
|
| opencode | `opencode` | `OPENCODE_CONFIG_DIR`, `XDG_CONFIG_HOME`, `XDG_DATA_HOME` | `~/.config/opencode` |
|
|
232
257
|
| Cursor Agent | `cursor` | `CURSOR_CONFIG_DIR` | `~/.cursor` |
|
|
@@ -241,6 +266,9 @@ globally is intentionally not recommended.
|
|
|
241
266
|
|
|
242
267
|
Custom tools can join supervised resume switching with `accounts tools add ... --resume-arg <arg>`.
|
|
243
268
|
They can also define permission presets with `--permission-arg preset=--flag`.
|
|
269
|
+
Use `--launch-arg` for app-level arguments that should be prepended to every
|
|
270
|
+
login/launch/run command; templates support `{profileDir}`, `{profileName}`, and
|
|
271
|
+
`{toolId}`.
|
|
244
272
|
|
|
245
273
|
## Library
|
|
246
274
|
|
package/dist/cli.js
CHANGED
|
@@ -992,7 +992,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
992
992
|
this._exitCallback = (err) => {
|
|
993
993
|
if (err.code !== "commander.executeSubCommandAsync") {
|
|
994
994
|
throw err;
|
|
995
|
-
}
|
|
995
|
+
}
|
|
996
996
|
};
|
|
997
997
|
}
|
|
998
998
|
return this;
|
|
@@ -12259,7 +12259,7 @@ var require_es5 = __commonJS((exports, module) => {
|
|
|
12259
12259
|
|
|
12260
12260
|
// node_modules/@aws-sdk/core/dist-cjs/submodules/client/index.js
|
|
12261
12261
|
var require_client2 = __commonJS((exports) => {
|
|
12262
|
-
var __dirname = "/home/hasna/
|
|
12262
|
+
var __dirname = "/home/hasna/Workspace/hasna/opensource/open-accounts/node_modules/@aws-sdk/core/dist-cjs/submodules/client";
|
|
12263
12263
|
var retry = require_retry();
|
|
12264
12264
|
var protocols = require_protocols();
|
|
12265
12265
|
var lambdaInvokeStore = require_invoke_store();
|
|
@@ -36797,9 +36797,9 @@ var require_dist_cjs22 = __commonJS((exports) => {
|
|
|
36797
36797
|
|
|
36798
36798
|
// src/cli.ts
|
|
36799
36799
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
36800
|
-
import { existsSync as
|
|
36800
|
+
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "node:fs";
|
|
36801
36801
|
import { homedir as homedir6 } from "node:os";
|
|
36802
|
-
import { dirname as dirname5, join as
|
|
36802
|
+
import { dirname as dirname5, join as join13 } from "node:path";
|
|
36803
36803
|
import { fileURLToPath } from "node:url";
|
|
36804
36804
|
|
|
36805
36805
|
// node_modules/commander/esm.mjs
|
|
@@ -37381,15 +37381,9 @@ function print(value, json, text) {
|
|
|
37381
37381
|
else
|
|
37382
37382
|
console.log(text);
|
|
37383
37383
|
}
|
|
37384
|
-
function hasJsonOption(options) {
|
|
37385
|
-
return Boolean(options?.json || options?.opts?.().json || options?.optsWithGlobals?.().json || options?.parent?.opts?.().json || options?.parent?.optsWithGlobals?.().json);
|
|
37386
|
-
}
|
|
37387
|
-
function wantsJson(actionOptions, command) {
|
|
37388
|
-
return hasJsonOption(actionOptions) || hasJsonOption(command);
|
|
37389
|
-
}
|
|
37390
37384
|
function registerWebhookCommands(program2, options) {
|
|
37391
37385
|
const webhooks = program2.command(options.webhooksCommandName ?? "webhooks").description("Manage Hasna event webhook subscriptions");
|
|
37392
|
-
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions
|
|
37386
|
+
webhooks.command("add").description("Add or replace a webhook or command subscription").argument("<target>", "Webhook URL or command binary").requiredOption("--id <id>", "Subscription/channel identifier").option("--transport <kind>", "Transport kind: webhook or command", "webhook").option("--name <name>", "Display name").option("--type <pattern>", "Event type filter, e.g. todos.task.*").option("--source <pattern>", "Event source filter").option("--subject <pattern>", "Event subject filter").option("--severity <pattern>", "Event severity filter").option("--secret <secret>", "Webhook HMAC secret").option("--header <name=value...>", "Webhook header", collectValues, []).option("--arg <arg...>", "Command argument", collectValues, []).option("--timeout-ms <ms>", "Transport timeout in milliseconds", parseNumber).option("--retry-attempts <n>", "Maximum delivery attempts", parseNumber).option("--retry-backoff-ms <ms>", "Initial retry backoff in milliseconds", parseNumber).option("--redact <path...>", "Event field path to redact before delivery", collectValues, []).option("--disabled", "Create channel disabled", false).option("-j, --json", "Print JSON output", false).action(async (target, actionOptions) => {
|
|
37393
37387
|
const timestamp = new Date().toISOString();
|
|
37394
37388
|
const channel = {
|
|
37395
37389
|
id: actionOptions.id,
|
|
@@ -37410,11 +37404,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
37410
37404
|
throw new Error(`Transport ${actionOptions.transport} is reserved for future use and cannot be added yet`);
|
|
37411
37405
|
}
|
|
37412
37406
|
const saved = await createClient(options).addChannel(channel);
|
|
37413
|
-
print(sanitizeChannelForOutput(saved),
|
|
37407
|
+
print(sanitizeChannelForOutput(saved), Boolean(actionOptions.json), `Added ${saved.transport} channel ${saved.id}`);
|
|
37414
37408
|
});
|
|
37415
|
-
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions
|
|
37409
|
+
webhooks.command("list").description("List configured subscriptions").option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
37416
37410
|
const channels = await createClient(options).listChannels();
|
|
37417
|
-
if (
|
|
37411
|
+
if (actionOptions.json) {
|
|
37418
37412
|
console.log(JSON.stringify(sanitizeChannelsForOutput(channels), null, 2));
|
|
37419
37413
|
return;
|
|
37420
37414
|
}
|
|
@@ -37426,11 +37420,11 @@ function registerWebhookCommands(program2, options) {
|
|
|
37426
37420
|
console.log(`${channel.id} ${channel.enabled ? "enabled" : "disabled"} ${channel.transport} ${channel.webhook?.url ?? channel.command?.command ?? channel.transport}`);
|
|
37427
37421
|
}
|
|
37428
37422
|
});
|
|
37429
|
-
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions
|
|
37423
|
+
webhooks.command("remove").description("Remove a subscription").argument("<id>", "Subscription/channel identifier").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
37430
37424
|
const removed = await createClient(options).removeChannel(id);
|
|
37431
|
-
print({ removed },
|
|
37425
|
+
print({ removed }, Boolean(actionOptions.json), removed ? `Removed ${id}` : `Channel not found: ${id}`);
|
|
37432
37426
|
});
|
|
37433
|
-
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions
|
|
37427
|
+
webhooks.command("test").description("Send a test event to one subscription").argument("<id>", "Subscription/channel identifier").option("--type <type>", "Event type", "events.test").option("--subject <subject>", "Event subject").option("--message <message>", "Event message", "Hasna events test delivery").option("--data <json>", "Event data JSON object").option("-j, --json", "Print JSON output", false).action(async (id, actionOptions) => {
|
|
37434
37428
|
const result = await createClient(options).testChannel(id, {
|
|
37435
37429
|
source: options.source,
|
|
37436
37430
|
type: actionOptions.type,
|
|
@@ -37438,13 +37432,13 @@ function registerWebhookCommands(program2, options) {
|
|
|
37438
37432
|
message: actionOptions.message,
|
|
37439
37433
|
data: parseJsonObject(actionOptions.data, { test: true })
|
|
37440
37434
|
});
|
|
37441
|
-
print(result,
|
|
37435
|
+
print(result, Boolean(actionOptions.json), `${result.status}: ${result.channelId}`);
|
|
37442
37436
|
});
|
|
37443
37437
|
return webhooks;
|
|
37444
37438
|
}
|
|
37445
37439
|
function registerEventCommands(program2, options) {
|
|
37446
37440
|
const events = program2.command(options.eventsCommandName ?? "events").description("Emit, list, and replay Hasna events");
|
|
37447
|
-
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions
|
|
37441
|
+
events.command("emit").description("Emit an event from this app").argument("<type>", "Event type").option("--source <source>", "Event source override").option("--subject <subject>", "Event subject").option("--severity <severity>", "Event severity", "info").option("--message <message>", "Event message").option("--dedupe-key <key>", "Dedupe key").option("--data <json>", "Event data JSON object").option("--metadata <json>", "Event metadata JSON object").option("--no-deliver", "Record without delivering").option("--no-dedupe", "Allow duplicate id/dedupeKey events").option("-j, --json", "Print JSON output", false).action(async (type, actionOptions) => {
|
|
37448
37442
|
const result = await createClient(options).emit({
|
|
37449
37443
|
source: actionOptions.source ?? options.source,
|
|
37450
37444
|
type,
|
|
@@ -37455,9 +37449,9 @@ function registerEventCommands(program2, options) {
|
|
|
37455
37449
|
data: parseJsonObject(actionOptions.data, {}),
|
|
37456
37450
|
metadata: parseJsonObject(actionOptions.metadata, {})
|
|
37457
37451
|
}, { deliver: actionOptions.deliver, dedupe: actionOptions.dedupe });
|
|
37458
|
-
print(result,
|
|
37452
|
+
print(result, Boolean(actionOptions.json), `${result.deduped ? "Deduped" : "Emitted"} ${result.event.id} to ${result.deliveries.length} channel(s)`);
|
|
37459
37453
|
});
|
|
37460
|
-
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions
|
|
37454
|
+
events.command("list").description("List recorded events").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--limit <n>", "Limit results", parseNumber).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
37461
37455
|
let rows = await createClient(options).listEvents();
|
|
37462
37456
|
if (actionOptions.source)
|
|
37463
37457
|
rows = rows.filter((event) => event.source === actionOptions.source);
|
|
@@ -37465,7 +37459,7 @@ function registerEventCommands(program2, options) {
|
|
|
37465
37459
|
rows = rows.filter((event) => event.type === actionOptions.type);
|
|
37466
37460
|
if (actionOptions.limit)
|
|
37467
37461
|
rows = rows.slice(-actionOptions.limit);
|
|
37468
|
-
if (
|
|
37462
|
+
if (actionOptions.json) {
|
|
37469
37463
|
console.log(JSON.stringify(rows, null, 2));
|
|
37470
37464
|
return;
|
|
37471
37465
|
}
|
|
@@ -37476,14 +37470,14 @@ function registerEventCommands(program2, options) {
|
|
|
37476
37470
|
for (const event of rows)
|
|
37477
37471
|
console.log(`${event.time} ${event.id} ${event.source} ${event.type} ${event.severity}`);
|
|
37478
37472
|
});
|
|
37479
|
-
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions
|
|
37473
|
+
events.command("replay").description("Replay recorded events").option("--id <id>", "Replay one event id").option("--source <source>", "Filter by source").option("--type <type>", "Filter by type").option("--dry-run", "Preview without delivery", false).option("-j, --json", "Print JSON output", false).action(async (actionOptions) => {
|
|
37480
37474
|
const result = await createClient(options).replay({
|
|
37481
37475
|
eventId: actionOptions.id,
|
|
37482
37476
|
source: actionOptions.source,
|
|
37483
37477
|
type: actionOptions.type,
|
|
37484
37478
|
dryRun: actionOptions.dryRun
|
|
37485
37479
|
});
|
|
37486
|
-
print(result,
|
|
37480
|
+
print(result, Boolean(actionOptions.json), `Replayed ${result.events.length} event(s), ${result.deliveries.length} delivery result(s)`);
|
|
37487
37481
|
});
|
|
37488
37482
|
return events;
|
|
37489
37483
|
}
|
|
@@ -41978,6 +41972,7 @@ var toolDefSchema = exports_external.object({
|
|
|
41978
41972
|
loginHint: exports_external.string().optional(),
|
|
41979
41973
|
resumeArgs: exports_external.array(exports_external.string()).optional(),
|
|
41980
41974
|
permissionArgs: exports_external.record(exports_external.array(exports_external.string())).optional(),
|
|
41975
|
+
launchArgs: exports_external.array(exports_external.string()).optional(),
|
|
41981
41976
|
accountFile: exports_external.string().optional(),
|
|
41982
41977
|
emailPath: exports_external.array(exports_external.string()).optional()
|
|
41983
41978
|
});
|
|
@@ -42301,6 +42296,9 @@ var BUILTIN_TOOLS = [
|
|
|
42301
42296
|
id: "claude",
|
|
42302
42297
|
label: "Claude Code",
|
|
42303
42298
|
envVar: "CLAUDE_CONFIG_DIR",
|
|
42299
|
+
extraEnv: {
|
|
42300
|
+
TELEGRAM_STATE_DIR: "{profileDir}/channels/telegram"
|
|
42301
|
+
},
|
|
42304
42302
|
defaultDir: join3(homedir3(), ".claude"),
|
|
42305
42303
|
bin: "claude",
|
|
42306
42304
|
loginHint: "run /login inside Claude, then /exit when done",
|
|
@@ -42317,6 +42315,16 @@ var BUILTIN_TOOLS = [
|
|
|
42317
42315
|
accountFile: ".claude.json",
|
|
42318
42316
|
emailPath: ["oauthAccount", "emailAddress"]
|
|
42319
42317
|
},
|
|
42318
|
+
{
|
|
42319
|
+
id: "codex-app",
|
|
42320
|
+
label: "Codex App",
|
|
42321
|
+
envVar: "CODEX_HOME",
|
|
42322
|
+
defaultDir: join3(homedir3(), ".codex"),
|
|
42323
|
+
bin: "/Applications/Codex.app/Contents/MacOS/Codex",
|
|
42324
|
+
loginHint: "sign in inside Codex.app, then quit the app when the profile is ready",
|
|
42325
|
+
launchArgs: ["--user-data-dir={profileDir}/electron-user-data"],
|
|
42326
|
+
accountFile: "auth.json"
|
|
42327
|
+
},
|
|
42320
42328
|
{
|
|
42321
42329
|
id: "codex",
|
|
42322
42330
|
label: "Codex CLI",
|
|
@@ -42466,9 +42474,17 @@ function permissionArgsFor(tool, permissions) {
|
|
|
42466
42474
|
}
|
|
42467
42475
|
return args;
|
|
42468
42476
|
}
|
|
42477
|
+
function renderToolArg(value, profile) {
|
|
42478
|
+
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
42479
|
+
}
|
|
42480
|
+
function launchArgsFor(tool, profile) {
|
|
42481
|
+
const args = tool.launchArgs ?? [];
|
|
42482
|
+
return profile ? args.map((arg) => renderToolArg(arg, profile)) : args;
|
|
42483
|
+
}
|
|
42469
42484
|
function mergeToolArgs(tool, args, opts = {}) {
|
|
42485
|
+
const launchArgs = launchArgsFor(tool, opts.profile).filter((arg) => !args.includes(arg));
|
|
42470
42486
|
const permissionArgs = permissionArgsFor(tool, opts.permissions).filter((arg) => !args.includes(arg));
|
|
42471
|
-
return [...permissionArgs, ...args];
|
|
42487
|
+
return [...permissionArgs, ...launchArgs, ...args];
|
|
42472
42488
|
}
|
|
42473
42489
|
var BUILTIN_IDS = new Set(BUILTIN_TOOLS.map((t) => t.id));
|
|
42474
42490
|
function isBuiltinTool(id) {
|
|
@@ -42743,7 +42759,7 @@ function currentProfile(toolId) {
|
|
|
42743
42759
|
const name = store.current[toolId];
|
|
42744
42760
|
if (!name)
|
|
42745
42761
|
return;
|
|
42746
|
-
return store.profiles.find((p) => p.name === name);
|
|
42762
|
+
return store.profiles.find((p) => p.name === name && p.tool === toolId);
|
|
42747
42763
|
}
|
|
42748
42764
|
|
|
42749
42765
|
// src/lib/claude-auth.ts
|
|
@@ -43482,6 +43498,42 @@ function shellSnippet() {
|
|
|
43482
43498
|
return `source ${shellQuotePath(hookPath())}`;
|
|
43483
43499
|
}
|
|
43484
43500
|
|
|
43501
|
+
// src/lib/codex-app.ts
|
|
43502
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
43503
|
+
import { join as join11 } from "node:path";
|
|
43504
|
+
var FILE_CREDENTIALS_LINE = 'cli_auth_credentials_store = "file"';
|
|
43505
|
+
function insertRootConfigLine(config, line) {
|
|
43506
|
+
if (config.trim() === "")
|
|
43507
|
+
return `${line}
|
|
43508
|
+
`;
|
|
43509
|
+
const lines = config.split(/\r?\n/);
|
|
43510
|
+
const tableIndex = lines.findIndex((entry) => /^\s*\[[^\]]+\]\s*(?:#.*)?$/.test(entry));
|
|
43511
|
+
if (tableIndex === -1)
|
|
43512
|
+
return `${config.trimEnd()}
|
|
43513
|
+
|
|
43514
|
+
${line}
|
|
43515
|
+
`;
|
|
43516
|
+
const before = lines.slice(0, tableIndex).join(`
|
|
43517
|
+
`).trimEnd();
|
|
43518
|
+
const after = lines.slice(tableIndex).join(`
|
|
43519
|
+
`).trimStart();
|
|
43520
|
+
return `${before}${before ? `
|
|
43521
|
+
|
|
43522
|
+
` : ""}${line}
|
|
43523
|
+
|
|
43524
|
+
${after}${after.endsWith(`
|
|
43525
|
+
`) ? "" : `
|
|
43526
|
+
`}`;
|
|
43527
|
+
}
|
|
43528
|
+
function ensureCodexAppProfileConfig(profileDir) {
|
|
43529
|
+
mkdirSync7(profileDir, { recursive: true });
|
|
43530
|
+
const configPath = join11(profileDir, "config.toml");
|
|
43531
|
+
const current = existsSync11(configPath) ? readFileSync6(configPath, "utf8") : "";
|
|
43532
|
+
if (/^\s*cli_auth_credentials_store\s*=/.test(current))
|
|
43533
|
+
return;
|
|
43534
|
+
writeFileSync5(configPath, insertRootConfigLine(current, FILE_CREDENTIALS_LINE), { mode: 384 });
|
|
43535
|
+
}
|
|
43536
|
+
|
|
43485
43537
|
// src/lib/env.ts
|
|
43486
43538
|
function renderTemplate(value, profile) {
|
|
43487
43539
|
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
@@ -43498,6 +43550,8 @@ function profileEnv(profile, tool) {
|
|
|
43498
43550
|
for (const key of CLAUDE_API_AUTH_ENV_KEYS)
|
|
43499
43551
|
env2[key] = "";
|
|
43500
43552
|
}
|
|
43553
|
+
if (tool.id === "codex-app")
|
|
43554
|
+
ensureCodexAppProfileConfig(profile.dir);
|
|
43501
43555
|
return env2;
|
|
43502
43556
|
}
|
|
43503
43557
|
function formatEnvAssignments(env2) {
|
|
@@ -43531,9 +43585,9 @@ function shellQuote(value) {
|
|
|
43531
43585
|
function commandLine(env2, command) {
|
|
43532
43586
|
return `${formatEnvAssignments(env2)} ${command.map(shellQuote).join(" ")}`.trim();
|
|
43533
43587
|
}
|
|
43534
|
-
function commandFor(tool, opts) {
|
|
43588
|
+
function commandFor(profile, tool, opts) {
|
|
43535
43589
|
const args = [...opts.resume ? tool.resumeArgs ?? [] : [], ...opts.args ?? []];
|
|
43536
|
-
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions })];
|
|
43590
|
+
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions, profile })];
|
|
43537
43591
|
}
|
|
43538
43592
|
function switchProfile(name, opts = {}) {
|
|
43539
43593
|
const profile = getProfile(name, opts.tool);
|
|
@@ -43550,7 +43604,7 @@ function switchProfile(name, opts = {}) {
|
|
|
43550
43604
|
} else {
|
|
43551
43605
|
useProfile(name, tool.id);
|
|
43552
43606
|
}
|
|
43553
|
-
const command = commandFor(tool, opts);
|
|
43607
|
+
const command = commandFor(profile, tool, opts);
|
|
43554
43608
|
const restartRequired = opts.resume === true || applied || mode === "env";
|
|
43555
43609
|
const message = applied ? `${profile.name} is now the live/default ${tool.label} profile` : `${profile.name} is now the active ${tool.label} profile`;
|
|
43556
43610
|
return {
|
|
@@ -43571,22 +43625,22 @@ function switchProfile(name, opts = {}) {
|
|
|
43571
43625
|
// src/lib/supervisor.ts
|
|
43572
43626
|
import { spawn as spawn2 } from "node:child_process";
|
|
43573
43627
|
import { createHash } from "node:crypto";
|
|
43574
|
-
import { existsSync as
|
|
43628
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "node:fs";
|
|
43575
43629
|
import { createConnection, createServer } from "node:net";
|
|
43576
|
-
import { basename, join as
|
|
43630
|
+
import { basename, join as join12 } from "node:path";
|
|
43577
43631
|
var STATE_SUFFIX = ".json";
|
|
43578
43632
|
function supervisorDir() {
|
|
43579
|
-
return
|
|
43633
|
+
return join12(accountsHome(), "supervisors");
|
|
43580
43634
|
}
|
|
43581
43635
|
function supervisorStatePath(toolId) {
|
|
43582
|
-
return
|
|
43636
|
+
return join12(supervisorDir(), `${toolId}${STATE_SUFFIX}`);
|
|
43583
43637
|
}
|
|
43584
43638
|
function supervisorSocketPath(toolId) {
|
|
43585
43639
|
if (process.platform === "win32") {
|
|
43586
43640
|
const hash = createHash("sha1").update(accountsHome()).digest("hex").slice(0, 12);
|
|
43587
43641
|
return `\\\\.\\pipe\\hasna-accounts-${hash}-${toolId}`;
|
|
43588
43642
|
}
|
|
43589
|
-
return
|
|
43643
|
+
return join12(supervisorDir(), `${toolId}.sock`);
|
|
43590
43644
|
}
|
|
43591
43645
|
function nowIso2() {
|
|
43592
43646
|
return new Date().toISOString();
|
|
@@ -43600,23 +43654,23 @@ function parseState(raw) {
|
|
|
43600
43654
|
}
|
|
43601
43655
|
function readSupervisorState(toolId) {
|
|
43602
43656
|
const path = supervisorStatePath(toolId);
|
|
43603
|
-
if (!
|
|
43657
|
+
if (!existsSync12(path))
|
|
43604
43658
|
return;
|
|
43605
43659
|
try {
|
|
43606
|
-
return parseState(
|
|
43660
|
+
return parseState(readFileSync7(path, "utf8"));
|
|
43607
43661
|
} catch {
|
|
43608
43662
|
return;
|
|
43609
43663
|
}
|
|
43610
43664
|
}
|
|
43611
43665
|
function listSupervisorStates() {
|
|
43612
43666
|
const dir = supervisorDir();
|
|
43613
|
-
if (!
|
|
43667
|
+
if (!existsSync12(dir))
|
|
43614
43668
|
return [];
|
|
43615
43669
|
return readdirSync(dir).filter((name) => name.endsWith(STATE_SUFFIX)).map((name) => basename(name, STATE_SUFFIX)).map((toolId) => readSupervisorState(toolId)).filter((state) => state !== undefined);
|
|
43616
43670
|
}
|
|
43617
43671
|
function writeSupervisorState(state) {
|
|
43618
|
-
|
|
43619
|
-
|
|
43672
|
+
mkdirSync8(supervisorDir(), { recursive: true });
|
|
43673
|
+
writeFileSync6(supervisorStatePath(state.tool), JSON.stringify(state, null, 2) + `
|
|
43620
43674
|
`, { mode: 384 });
|
|
43621
43675
|
}
|
|
43622
43676
|
function removeSupervisorFiles(toolId) {
|
|
@@ -43757,7 +43811,7 @@ async function runSupervisedTool(initialProfile, tool, initialArgs = [], opts =
|
|
|
43757
43811
|
throw new AccountsError(`an accounts supervisor for ${tool.label} is already running (pid ${existing.pid})`);
|
|
43758
43812
|
}
|
|
43759
43813
|
removeSupervisorFiles(tool.id);
|
|
43760
|
-
|
|
43814
|
+
mkdirSync8(supervisorDir(), { recursive: true });
|
|
43761
43815
|
const startedAt = nowIso2();
|
|
43762
43816
|
const restartDelayMs = opts.restartDelayMs ?? 350;
|
|
43763
43817
|
const log = opts.log ?? (() => {
|
|
@@ -44032,7 +44086,7 @@ program2.command("show").argument("<name>", "profile name").description("show fu
|
|
|
44032
44086
|
console.log(` tool: ${p.tool} (${getTool(p.tool).label})`);
|
|
44033
44087
|
console.log(` active: ${active ? source_default.green("yes") : source_default.dim("no")}`);
|
|
44034
44088
|
console.log(` applied: ${isApplied ? source_default.magenta("yes") : source_default.dim("no")}`);
|
|
44035
|
-
console.log(` config dir: ${p.dir}${
|
|
44089
|
+
console.log(` config dir: ${p.dir}${existsSync13(p.dir) ? "" : source_default.red(" [missing]")}`);
|
|
44036
44090
|
console.log(` email: ${p.email ?? source_default.dim("(none)")}`);
|
|
44037
44091
|
console.log(` created: ${p.createdAt}`);
|
|
44038
44092
|
if (p.lastUsedAt)
|
|
@@ -44082,7 +44136,7 @@ program2.command("login").argument("<name>", "profile name").description("launch
|
|
|
44082
44136
|
if (tool.id === "claude") {
|
|
44083
44137
|
console.log(source_default.dim(" After Claude exits, accounts will make this the live/default Claude account."));
|
|
44084
44138
|
}
|
|
44085
|
-
const res = spawnSync2(tool.bin, loginArgs, {
|
|
44139
|
+
const res = spawnSync2(tool.bin, mergeToolArgs(tool, loginArgs, { profile }), {
|
|
44086
44140
|
stdio: "inherit",
|
|
44087
44141
|
env: { ...process.env, ...env2 }
|
|
44088
44142
|
});
|
|
@@ -44184,7 +44238,7 @@ program2.command("switch").argument("<name>", "profile name").argument("[args...
|
|
|
44184
44238
|
}
|
|
44185
44239
|
}));
|
|
44186
44240
|
var hook = program2.command("hook").description("install a shell wrapper for claude");
|
|
44187
|
-
hook.command("install").description(`write ${
|
|
44241
|
+
hook.command("install").description(`write ${join13(accountsHome(), "claude-hook.sh")}`).action(action(() => {
|
|
44188
44242
|
const { path, created } = installHook();
|
|
44189
44243
|
console.log(source_default.green(created ? `✓ installed hook at ${path}` : `✓ updated hook at ${path}`));
|
|
44190
44244
|
console.log(source_default.dim(` add to ~/.zshrc: ${shellSnippet()}`));
|
|
@@ -44210,7 +44264,7 @@ program2.command("launch").argument("<name>", "profile name").argument("[args...
|
|
|
44210
44264
|
const profile = getProfile(name, opts.tool);
|
|
44211
44265
|
const tool = getTool(profile.tool);
|
|
44212
44266
|
const env2 = profileEnv(profile, tool);
|
|
44213
|
-
const launchArgs = mergeToolArgs(tool, args, { permissions: opts.permissions });
|
|
44267
|
+
const launchArgs = mergeToolArgs(tool, args, { permissions: opts.permissions, profile });
|
|
44214
44268
|
useProfile(name, tool.id);
|
|
44215
44269
|
console.log(source_default.dim(`→ ${formatEnvAssignments(env2)} ${tool.bin} ${launchArgs.join(" ")}`));
|
|
44216
44270
|
const res = spawnSync2(tool.bin, launchArgs, {
|
|
@@ -44224,7 +44278,8 @@ program2.command("launch").argument("<name>", "profile name").argument("[args...
|
|
|
44224
44278
|
program2.command("run").argument("<target>", "tool id to supervise (claude, codex, opencode...) or a profile name").argument("[args...]", "extra args passed to the tool binary").description("run a tool under the accounts supervisor so MCP can switch/restart it").option("-p, --profile <name>", "profile to run when target is a tool id").option("-t, --tool <tool>", "tool when target is a profile name").option("--resume", "start with the tool's resume/continue args").option("--permissions <preset>", "tool-specific permission preset, e.g. dangerous").action(action(async (target, args, opts) => {
|
|
44225
44279
|
const plan = resolveSupervisorLaunch(target, { profile: opts.profile, tool: opts.tool });
|
|
44226
44280
|
const runArgs = mergeToolArgs(plan.tool, [...opts.resume ? plan.tool.resumeArgs ?? [] : [], ...args], {
|
|
44227
|
-
permissions: opts.permissions
|
|
44281
|
+
permissions: opts.permissions,
|
|
44282
|
+
profile: plan.profile
|
|
44228
44283
|
});
|
|
44229
44284
|
console.error(source_default.green(`✓ accounts supervisor running ${plan.tool.label} as ${source_default.bold(plan.profile.name)}`));
|
|
44230
44285
|
console.error(source_default.dim(` control: accounts supervisor status ${plan.tool.id}`));
|
|
@@ -44409,7 +44464,7 @@ tools.command("list", { isDefault: true }).description("list supported tools (bu
|
|
|
44409
44464
|
console.log(`${source_default.cyan(t.id.padEnd(10))} ${t.label.padEnd(16)} ${source_default.dim(envNames)} → ${source_default.dim(t.defaultDir)} ${tag}${permissionsHint}`);
|
|
44410
44465
|
}
|
|
44411
44466
|
}));
|
|
44412
|
-
tools.command("add").argument("<id>", "tool id, e.g. cursor").description("register a custom tool/app so profiles can target it").requiredOption("--label <label>", 'display name, e.g. "Cursor"').requiredOption("--env-var <VAR>", "env var that points the tool at its config dir").requiredOption("--bin <bin>", "binary to launch").option("--default-dir <path>", "default config dir (default: ~/.<id>)").option("--extra-env <VAR=VALUE...>", "additional env var templates; supports {profileDir}, {profileName}, {toolId}").option("--login-arg <arg...>", "arguments for `accounts login <profile> --tool <id>`").option("--resume-arg <arg...>", "arguments for supervised resume/restart, e.g. --continue").option("--permission-arg <preset=arg...>", "tool permission preset args, e.g. dangerous=--yolo").option("--account-file <file>", "file inside the config dir holding the email").option("--email-path <path>", "dot-path to the email inside that file (e.g. account.email)").action(action((id, opts) => {
|
|
44467
|
+
tools.command("add").argument("<id>", "tool id, e.g. cursor").description("register a custom tool/app so profiles can target it").requiredOption("--label <label>", 'display name, e.g. "Cursor"').requiredOption("--env-var <VAR>", "env var that points the tool at its config dir").requiredOption("--bin <bin>", "binary to launch").option("--default-dir <path>", "default config dir (default: ~/.<id>)").option("--extra-env <VAR=VALUE...>", "additional env var templates; supports {profileDir}, {profileName}, {toolId}").option("--login-arg <arg...>", "arguments for `accounts login <profile> --tool <id>`").option("--launch-arg <arg...>", "arguments prepended when launching; supports {profileDir}, {profileName}, {toolId}").option("--resume-arg <arg...>", "arguments for supervised resume/restart, e.g. --continue").option("--permission-arg <preset=arg...>", "tool permission preset args, e.g. dangerous=--yolo").option("--account-file <file>", "file inside the config dir holding the email").option("--email-path <path>", "dot-path to the email inside that file (e.g. account.email)").action(action((id, opts) => {
|
|
44413
44468
|
const extraEnv = {};
|
|
44414
44469
|
for (const entry of opts.extraEnv ?? []) {
|
|
44415
44470
|
const idx = entry.indexOf("=");
|
|
@@ -44423,9 +44478,10 @@ tools.command("add").argument("<id>", "tool id, e.g. cursor").description("regis
|
|
|
44423
44478
|
label: opts.label,
|
|
44424
44479
|
envVar: opts.envVar,
|
|
44425
44480
|
bin: opts.bin,
|
|
44426
|
-
defaultDir: opts.defaultDir ? expandPath(opts.defaultDir) :
|
|
44481
|
+
defaultDir: opts.defaultDir ? expandPath(opts.defaultDir) : join13(homedir6(), `.${id}`),
|
|
44427
44482
|
...Object.keys(extraEnv).length > 0 ? { extraEnv } : {},
|
|
44428
44483
|
...opts.loginArg ? { loginArgs: opts.loginArg } : {},
|
|
44484
|
+
...opts.launchArg ? { launchArgs: opts.launchArg } : {},
|
|
44429
44485
|
...opts.resumeArg ? { resumeArgs: opts.resumeArg } : {},
|
|
44430
44486
|
...Object.keys(permissionArgs).length > 0 ? { permissionArgs } : {},
|
|
44431
44487
|
...opts.accountFile ? { accountFile: opts.accountFile } : {},
|
|
@@ -44445,7 +44501,7 @@ program2.command("doctor").description("check the store and profile dirs for pro
|
|
|
44445
44501
|
const profiles = listProfiles();
|
|
44446
44502
|
let problems = 0;
|
|
44447
44503
|
for (const p of profiles) {
|
|
44448
|
-
const missing = !
|
|
44504
|
+
const missing = !existsSync13(p.dir);
|
|
44449
44505
|
const noEmail = !p.email;
|
|
44450
44506
|
if (missing) {
|
|
44451
44507
|
console.log(source_default.red(` ✗ ${p.name}: config dir missing (${p.dir})`));
|
|
@@ -44494,9 +44550,9 @@ program2.parseAsync(process.argv);
|
|
|
44494
44550
|
function getVersion() {
|
|
44495
44551
|
try {
|
|
44496
44552
|
const here = dirname5(fileURLToPath(import.meta.url));
|
|
44497
|
-
for (const candidate of [
|
|
44498
|
-
if (
|
|
44499
|
-
const pkg = JSON.parse(
|
|
44553
|
+
for (const candidate of [join13(here, "..", "package.json"), join13(here, "package.json")]) {
|
|
44554
|
+
if (existsSync13(candidate)) {
|
|
44555
|
+
const pkg = JSON.parse(readFileSync8(candidate, "utf8"));
|
|
44500
44556
|
if (pkg.version)
|
|
44501
44557
|
return pkg.version;
|
|
44502
44558
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export * from "./types.js";
|
|
2
2
|
export { loadStore, saveStore, storePath, accountsHome, profilesDir } from "./storage.js";
|
|
3
|
-
export { BUILTIN_TOOLS, DEFAULT_TOOL, getTool, listTools, isBuiltinTool, addCustomTool, removeCustomTool, mergeToolArgs, normalizePermissionPreset, permissionArgsFor, } from "./lib/tools.js";
|
|
3
|
+
export { BUILTIN_TOOLS, DEFAULT_TOOL, getTool, listTools, isBuiltinTool, addCustomTool, removeCustomTool, mergeToolArgs, launchArgsFor, normalizePermissionPreset, permissionArgsFor, } from "./lib/tools.js";
|
|
4
4
|
export { profileEnv, formatEnvAssignments, formatExportLines } from "./lib/env.js";
|
|
5
5
|
export { detectEmail } from "./lib/detect.js";
|
|
6
6
|
export { expandPath, listProfiles, findProfile, getProfile, addProfile, removeProfile, renameProfile, updateProfile, redetectEmail, useProfile, currentProfile, } from "./lib/profiles.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,OAAO,EACP,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,UAAU,EACV,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,eAAe,EACf,cAAc,EACd,gCAAgC,EAChC,kCAAkC,EAClC,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EACL,aAAa,EACb,YAAY,EACZ,OAAO,EACP,SAAS,EACT,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EACL,UAAU,EACV,YAAY,EACZ,WAAW,EACX,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,UAAU,EACV,cAAc,GACf,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAC/E,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,EACrB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,eAAe,EACf,cAAc,EACd,gCAAgC,EAChC,kCAAkC,EAClC,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4000,6 +4000,7 @@ var toolDefSchema = exports_external.object({
|
|
|
4000
4000
|
loginHint: exports_external.string().optional(),
|
|
4001
4001
|
resumeArgs: exports_external.array(exports_external.string()).optional(),
|
|
4002
4002
|
permissionArgs: exports_external.record(exports_external.array(exports_external.string())).optional(),
|
|
4003
|
+
launchArgs: exports_external.array(exports_external.string()).optional(),
|
|
4003
4004
|
accountFile: exports_external.string().optional(),
|
|
4004
4005
|
emailPath: exports_external.array(exports_external.string()).optional()
|
|
4005
4006
|
});
|
|
@@ -4171,6 +4172,9 @@ var BUILTIN_TOOLS = [
|
|
|
4171
4172
|
id: "claude",
|
|
4172
4173
|
label: "Claude Code",
|
|
4173
4174
|
envVar: "CLAUDE_CONFIG_DIR",
|
|
4175
|
+
extraEnv: {
|
|
4176
|
+
TELEGRAM_STATE_DIR: "{profileDir}/channels/telegram"
|
|
4177
|
+
},
|
|
4174
4178
|
defaultDir: join2(homedir2(), ".claude"),
|
|
4175
4179
|
bin: "claude",
|
|
4176
4180
|
loginHint: "run /login inside Claude, then /exit when done",
|
|
@@ -4187,6 +4191,16 @@ var BUILTIN_TOOLS = [
|
|
|
4187
4191
|
accountFile: ".claude.json",
|
|
4188
4192
|
emailPath: ["oauthAccount", "emailAddress"]
|
|
4189
4193
|
},
|
|
4194
|
+
{
|
|
4195
|
+
id: "codex-app",
|
|
4196
|
+
label: "Codex App",
|
|
4197
|
+
envVar: "CODEX_HOME",
|
|
4198
|
+
defaultDir: join2(homedir2(), ".codex"),
|
|
4199
|
+
bin: "/Applications/Codex.app/Contents/MacOS/Codex",
|
|
4200
|
+
loginHint: "sign in inside Codex.app, then quit the app when the profile is ready",
|
|
4201
|
+
launchArgs: ["--user-data-dir={profileDir}/electron-user-data"],
|
|
4202
|
+
accountFile: "auth.json"
|
|
4203
|
+
},
|
|
4190
4204
|
{
|
|
4191
4205
|
id: "codex",
|
|
4192
4206
|
label: "Codex CLI",
|
|
@@ -4336,9 +4350,17 @@ function permissionArgsFor(tool, permissions) {
|
|
|
4336
4350
|
}
|
|
4337
4351
|
return args;
|
|
4338
4352
|
}
|
|
4353
|
+
function renderToolArg(value, profile) {
|
|
4354
|
+
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
4355
|
+
}
|
|
4356
|
+
function launchArgsFor(tool, profile) {
|
|
4357
|
+
const args = tool.launchArgs ?? [];
|
|
4358
|
+
return profile ? args.map((arg) => renderToolArg(arg, profile)) : args;
|
|
4359
|
+
}
|
|
4339
4360
|
function mergeToolArgs(tool, args, opts = {}) {
|
|
4361
|
+
const launchArgs = launchArgsFor(tool, opts.profile).filter((arg) => !args.includes(arg));
|
|
4340
4362
|
const permissionArgs = permissionArgsFor(tool, opts.permissions).filter((arg) => !args.includes(arg));
|
|
4341
|
-
return [...permissionArgs, ...args];
|
|
4363
|
+
return [...permissionArgs, ...launchArgs, ...args];
|
|
4342
4364
|
}
|
|
4343
4365
|
var BUILTIN_IDS = new Set(BUILTIN_TOOLS.map((t) => t.id));
|
|
4344
4366
|
function isBuiltinTool(id) {
|
|
@@ -4725,6 +4747,42 @@ function hasAuthSnapshot(profileDir) {
|
|
|
4725
4747
|
return existsSync3(profileOAuthSnapshot(profileDir)) || existsSync3(profileCredentialsSnapshot(profileDir)) || existsSync3(profileKeychainSnapshot(profileDir));
|
|
4726
4748
|
}
|
|
4727
4749
|
|
|
4750
|
+
// src/lib/codex-app.ts
|
|
4751
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
4752
|
+
import { join as join5 } from "node:path";
|
|
4753
|
+
var FILE_CREDENTIALS_LINE = 'cli_auth_credentials_store = "file"';
|
|
4754
|
+
function insertRootConfigLine(config, line) {
|
|
4755
|
+
if (config.trim() === "")
|
|
4756
|
+
return `${line}
|
|
4757
|
+
`;
|
|
4758
|
+
const lines = config.split(/\r?\n/);
|
|
4759
|
+
const tableIndex = lines.findIndex((entry) => /^\s*\[[^\]]+\]\s*(?:#.*)?$/.test(entry));
|
|
4760
|
+
if (tableIndex === -1)
|
|
4761
|
+
return `${config.trimEnd()}
|
|
4762
|
+
|
|
4763
|
+
${line}
|
|
4764
|
+
`;
|
|
4765
|
+
const before = lines.slice(0, tableIndex).join(`
|
|
4766
|
+
`).trimEnd();
|
|
4767
|
+
const after = lines.slice(tableIndex).join(`
|
|
4768
|
+
`).trimStart();
|
|
4769
|
+
return `${before}${before ? `
|
|
4770
|
+
|
|
4771
|
+
` : ""}${line}
|
|
4772
|
+
|
|
4773
|
+
${after}${after.endsWith(`
|
|
4774
|
+
`) ? "" : `
|
|
4775
|
+
`}`;
|
|
4776
|
+
}
|
|
4777
|
+
function ensureCodexAppProfileConfig(profileDir) {
|
|
4778
|
+
mkdirSync4(profileDir, { recursive: true });
|
|
4779
|
+
const configPath = join5(profileDir, "config.toml");
|
|
4780
|
+
const current = existsSync4(configPath) ? readFileSync3(configPath, "utf8") : "";
|
|
4781
|
+
if (/^\s*cli_auth_credentials_store\s*=/.test(current))
|
|
4782
|
+
return;
|
|
4783
|
+
writeFileSync3(configPath, insertRootConfigLine(current, FILE_CREDENTIALS_LINE), { mode: 384 });
|
|
4784
|
+
}
|
|
4785
|
+
|
|
4728
4786
|
// src/lib/env.ts
|
|
4729
4787
|
function renderTemplate(value, profile) {
|
|
4730
4788
|
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
@@ -4741,6 +4799,8 @@ function profileEnv(profile, tool) {
|
|
|
4741
4799
|
for (const key of CLAUDE_API_AUTH_ENV_KEYS)
|
|
4742
4800
|
env[key] = "";
|
|
4743
4801
|
}
|
|
4802
|
+
if (tool.id === "codex-app")
|
|
4803
|
+
ensureCodexAppProfileConfig(profile.dir);
|
|
4744
4804
|
return env;
|
|
4745
4805
|
}
|
|
4746
4806
|
function formatEnvAssignments(env) {
|
|
@@ -4751,14 +4811,14 @@ function formatExportLines(env) {
|
|
|
4751
4811
|
`);
|
|
4752
4812
|
}
|
|
4753
4813
|
// src/lib/detect.ts
|
|
4754
|
-
import { existsSync as
|
|
4755
|
-
import { dirname as dirname4, join as
|
|
4814
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
|
|
4815
|
+
import { dirname as dirname4, join as join6 } from "node:path";
|
|
4756
4816
|
function detectEmail(dir, tool) {
|
|
4757
4817
|
if (!tool.accountFile || !tool.emailPath)
|
|
4758
4818
|
return;
|
|
4759
|
-
const candidates = [
|
|
4819
|
+
const candidates = [join6(dir, tool.accountFile)];
|
|
4760
4820
|
if (dir === tool.defaultDir)
|
|
4761
|
-
candidates.push(
|
|
4821
|
+
candidates.push(join6(dirname4(dir), tool.accountFile));
|
|
4762
4822
|
for (const file of candidates) {
|
|
4763
4823
|
const email = readEmail(file, tool.emailPath);
|
|
4764
4824
|
if (email)
|
|
@@ -4767,11 +4827,11 @@ function detectEmail(dir, tool) {
|
|
|
4767
4827
|
return;
|
|
4768
4828
|
}
|
|
4769
4829
|
function readEmail(file, path) {
|
|
4770
|
-
if (!
|
|
4830
|
+
if (!existsSync5(file))
|
|
4771
4831
|
return;
|
|
4772
4832
|
let cursor;
|
|
4773
4833
|
try {
|
|
4774
|
-
cursor = JSON.parse(
|
|
4834
|
+
cursor = JSON.parse(readFileSync4(file, "utf8"));
|
|
4775
4835
|
} catch {
|
|
4776
4836
|
return;
|
|
4777
4837
|
}
|
|
@@ -4786,8 +4846,8 @@ function readEmail(file, path) {
|
|
|
4786
4846
|
}
|
|
4787
4847
|
// src/lib/profiles.ts
|
|
4788
4848
|
import { homedir as homedir4 } from "node:os";
|
|
4789
|
-
import { isAbsolute, join as
|
|
4790
|
-
import { existsSync as
|
|
4849
|
+
import { isAbsolute, join as join7, resolve as resolve2 } from "node:path";
|
|
4850
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, rmSync } from "node:fs";
|
|
4791
4851
|
function nowIso() {
|
|
4792
4852
|
return new Date().toISOString();
|
|
4793
4853
|
}
|
|
@@ -4796,7 +4856,7 @@ function expandPath(p) {
|
|
|
4796
4856
|
if (out === "~")
|
|
4797
4857
|
out = homedir4();
|
|
4798
4858
|
else if (out.startsWith("~/"))
|
|
4799
|
-
out =
|
|
4859
|
+
out = join7(homedir4(), out.slice(2));
|
|
4800
4860
|
return isAbsolute(out) ? out : resolve2(process.cwd(), out);
|
|
4801
4861
|
}
|
|
4802
4862
|
function listProfiles(toolId) {
|
|
@@ -4834,11 +4894,11 @@ function addProfile(opts) {
|
|
|
4834
4894
|
if (store.profiles.some((p) => p.name === name && p.tool === toolId)) {
|
|
4835
4895
|
throw new AccountsError(`a ${toolId} profile named "${name}" already exists`);
|
|
4836
4896
|
}
|
|
4837
|
-
const dir = opts.dir ? expandPath(opts.dir) :
|
|
4897
|
+
const dir = opts.dir ? expandPath(opts.dir) : join7(profilesDir(), toolId, name);
|
|
4838
4898
|
if (store.profiles.some((p) => p.dir === dir)) {
|
|
4839
4899
|
throw new AccountsError(`a profile already uses config dir ${dir}`);
|
|
4840
4900
|
}
|
|
4841
|
-
|
|
4901
|
+
mkdirSync5(dir, { recursive: true });
|
|
4842
4902
|
const email = opts.email ?? detectEmail(dir, tool);
|
|
4843
4903
|
const profile = {
|
|
4844
4904
|
name,
|
|
@@ -4876,7 +4936,7 @@ function removeProfile(name, opts = {}) {
|
|
|
4876
4936
|
if (options.purge) {
|
|
4877
4937
|
const managed = profile.dir.startsWith(profilesDir());
|
|
4878
4938
|
const isDefault = profile.dir === getTool(profile.tool).defaultDir;
|
|
4879
|
-
if (managed && !isDefault &&
|
|
4939
|
+
if (managed && !isDefault && existsSync6(profile.dir)) {
|
|
4880
4940
|
rmSync(profile.dir, { recursive: true, force: true });
|
|
4881
4941
|
purged = true;
|
|
4882
4942
|
} else {
|
|
@@ -4927,7 +4987,7 @@ function updateProfile(name, opts) {
|
|
|
4927
4987
|
profile.description = opts.description;
|
|
4928
4988
|
if (opts.dir !== undefined) {
|
|
4929
4989
|
const dir = expandPath(opts.dir);
|
|
4930
|
-
|
|
4990
|
+
mkdirSync5(dir, { recursive: true });
|
|
4931
4991
|
profile.dir = dir;
|
|
4932
4992
|
}
|
|
4933
4993
|
saveStore(store);
|
|
@@ -4971,22 +5031,22 @@ function currentProfile(toolId) {
|
|
|
4971
5031
|
const name = store.current[toolId];
|
|
4972
5032
|
if (!name)
|
|
4973
5033
|
return;
|
|
4974
|
-
return store.profiles.find((p) => p.name === name);
|
|
5034
|
+
return store.profiles.find((p) => p.name === name && p.tool === toolId);
|
|
4975
5035
|
}
|
|
4976
5036
|
// src/lib/apply-lock.ts
|
|
4977
|
-
import { closeSync, existsSync as
|
|
4978
|
-
import { join as
|
|
5037
|
+
import { closeSync, existsSync as existsSync7, mkdirSync as mkdirSync6, openSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
5038
|
+
import { join as join8 } from "node:path";
|
|
4979
5039
|
function lockPath() {
|
|
4980
|
-
return
|
|
5040
|
+
return join8(accountsHome(), ".apply.lock");
|
|
4981
5041
|
}
|
|
4982
5042
|
function withApplyLock(fn) {
|
|
4983
5043
|
const home = accountsHome();
|
|
4984
|
-
|
|
5044
|
+
mkdirSync6(home, { recursive: true });
|
|
4985
5045
|
const path = lockPath();
|
|
4986
5046
|
let fd;
|
|
4987
5047
|
try {
|
|
4988
5048
|
fd = openSync(path, "wx", 384);
|
|
4989
|
-
|
|
5049
|
+
writeFileSync4(fd, `${process.pid}
|
|
4990
5050
|
`, { encoding: "utf8", mode: 384 });
|
|
4991
5051
|
return fn();
|
|
4992
5052
|
} catch (err) {
|
|
@@ -5002,7 +5062,7 @@ function withApplyLock(fn) {
|
|
|
5002
5062
|
if (fd !== undefined) {
|
|
5003
5063
|
closeSync(fd);
|
|
5004
5064
|
try {
|
|
5005
|
-
if (
|
|
5065
|
+
if (existsSync7(path))
|
|
5006
5066
|
unlinkSync2(path);
|
|
5007
5067
|
} catch {}
|
|
5008
5068
|
}
|
|
@@ -5046,19 +5106,19 @@ function applyProfileUnlocked(name, toolId) {
|
|
|
5046
5106
|
return { profile, ...previous && previous !== name ? { previous } : {} };
|
|
5047
5107
|
}
|
|
5048
5108
|
// src/lib/import-profile.ts
|
|
5049
|
-
import { cpSync, existsSync as
|
|
5050
|
-
import { join as
|
|
5109
|
+
import { cpSync, existsSync as existsSync8 } from "node:fs";
|
|
5110
|
+
import { join as join9 } from "node:path";
|
|
5051
5111
|
function importProfile(opts) {
|
|
5052
5112
|
const toolId = opts.tool ?? DEFAULT_TOOL;
|
|
5053
5113
|
const tool = getTool(toolId);
|
|
5054
5114
|
const name = opts.name ?? "main";
|
|
5055
5115
|
const sourceDir = opts.dir ? expandPath(opts.dir) : tool.defaultDir;
|
|
5056
|
-
if (!
|
|
5116
|
+
if (!existsSync8(sourceDir)) {
|
|
5057
5117
|
throw new AccountsError(`config dir does not exist: ${sourceDir}`);
|
|
5058
5118
|
}
|
|
5059
5119
|
if (opts.copy) {
|
|
5060
|
-
const targetDir =
|
|
5061
|
-
if (
|
|
5120
|
+
const targetDir = join9(profilesDir(), toolId, name);
|
|
5121
|
+
if (existsSync8(targetDir)) {
|
|
5062
5122
|
throw new AccountsError(`managed copy target already exists: ${targetDir}`);
|
|
5063
5123
|
}
|
|
5064
5124
|
cpSync(sourceDir, targetDir, { recursive: true });
|
|
@@ -5122,9 +5182,9 @@ function shellQuote(value) {
|
|
|
5122
5182
|
function commandLine(env, command) {
|
|
5123
5183
|
return `${formatEnvAssignments(env)} ${command.map(shellQuote).join(" ")}`.trim();
|
|
5124
5184
|
}
|
|
5125
|
-
function commandFor(tool, opts) {
|
|
5185
|
+
function commandFor(profile, tool, opts) {
|
|
5126
5186
|
const args = [...opts.resume ? tool.resumeArgs ?? [] : [], ...opts.args ?? []];
|
|
5127
|
-
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions })];
|
|
5187
|
+
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions, profile })];
|
|
5128
5188
|
}
|
|
5129
5189
|
function switchProfile(name, opts = {}) {
|
|
5130
5190
|
const profile = getProfile(name, opts.tool);
|
|
@@ -5141,7 +5201,7 @@ function switchProfile(name, opts = {}) {
|
|
|
5141
5201
|
} else {
|
|
5142
5202
|
useProfile(name, tool.id);
|
|
5143
5203
|
}
|
|
5144
|
-
const command = commandFor(tool, opts);
|
|
5204
|
+
const command = commandFor(profile, tool, opts);
|
|
5145
5205
|
const restartRequired = opts.resume === true || applied || mode === "env";
|
|
5146
5206
|
const message = applied ? `${profile.name} is now the live/default ${tool.label} profile` : `${profile.name} is now the active ${tool.label} profile`;
|
|
5147
5207
|
return {
|
|
@@ -5161,22 +5221,22 @@ function switchProfile(name, opts = {}) {
|
|
|
5161
5221
|
// src/lib/supervisor.ts
|
|
5162
5222
|
import { spawn } from "node:child_process";
|
|
5163
5223
|
import { createHash } from "node:crypto";
|
|
5164
|
-
import { existsSync as
|
|
5224
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readFileSync as readFileSync5, readdirSync, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
5165
5225
|
import { createConnection, createServer } from "node:net";
|
|
5166
|
-
import { basename, join as
|
|
5226
|
+
import { basename, join as join10 } from "node:path";
|
|
5167
5227
|
var STATE_SUFFIX = ".json";
|
|
5168
5228
|
function supervisorDir() {
|
|
5169
|
-
return
|
|
5229
|
+
return join10(accountsHome(), "supervisors");
|
|
5170
5230
|
}
|
|
5171
5231
|
function supervisorStatePath(toolId) {
|
|
5172
|
-
return
|
|
5232
|
+
return join10(supervisorDir(), `${toolId}${STATE_SUFFIX}`);
|
|
5173
5233
|
}
|
|
5174
5234
|
function supervisorSocketPath(toolId) {
|
|
5175
5235
|
if (process.platform === "win32") {
|
|
5176
5236
|
const hash = createHash("sha1").update(accountsHome()).digest("hex").slice(0, 12);
|
|
5177
5237
|
return `\\\\.\\pipe\\hasna-accounts-${hash}-${toolId}`;
|
|
5178
5238
|
}
|
|
5179
|
-
return
|
|
5239
|
+
return join10(supervisorDir(), `${toolId}.sock`);
|
|
5180
5240
|
}
|
|
5181
5241
|
function nowIso2() {
|
|
5182
5242
|
return new Date().toISOString();
|
|
@@ -5190,23 +5250,23 @@ function parseState(raw) {
|
|
|
5190
5250
|
}
|
|
5191
5251
|
function readSupervisorState(toolId) {
|
|
5192
5252
|
const path = supervisorStatePath(toolId);
|
|
5193
|
-
if (!
|
|
5253
|
+
if (!existsSync9(path))
|
|
5194
5254
|
return;
|
|
5195
5255
|
try {
|
|
5196
|
-
return parseState(
|
|
5256
|
+
return parseState(readFileSync5(path, "utf8"));
|
|
5197
5257
|
} catch {
|
|
5198
5258
|
return;
|
|
5199
5259
|
}
|
|
5200
5260
|
}
|
|
5201
5261
|
function listSupervisorStates() {
|
|
5202
5262
|
const dir = supervisorDir();
|
|
5203
|
-
if (!
|
|
5263
|
+
if (!existsSync9(dir))
|
|
5204
5264
|
return [];
|
|
5205
5265
|
return readdirSync(dir).filter((name) => name.endsWith(STATE_SUFFIX)).map((name) => basename(name, STATE_SUFFIX)).map((toolId) => readSupervisorState(toolId)).filter((state) => state !== undefined);
|
|
5206
5266
|
}
|
|
5207
5267
|
function writeSupervisorState(state) {
|
|
5208
|
-
|
|
5209
|
-
|
|
5268
|
+
mkdirSync7(supervisorDir(), { recursive: true });
|
|
5269
|
+
writeFileSync5(supervisorStatePath(state.tool), JSON.stringify(state, null, 2) + `
|
|
5210
5270
|
`, { mode: 384 });
|
|
5211
5271
|
}
|
|
5212
5272
|
function removeSupervisorFiles(toolId) {
|
|
@@ -5347,7 +5407,7 @@ async function runSupervisedTool(initialProfile, tool, initialArgs = [], opts =
|
|
|
5347
5407
|
throw new AccountsError(`an accounts supervisor for ${tool.label} is already running (pid ${existing.pid})`);
|
|
5348
5408
|
}
|
|
5349
5409
|
removeSupervisorFiles(tool.id);
|
|
5350
|
-
|
|
5410
|
+
mkdirSync7(supervisorDir(), { recursive: true });
|
|
5351
5411
|
const startedAt = nowIso2();
|
|
5352
5412
|
const restartDelayMs = opts.restartDelayMs ?? 350;
|
|
5353
5413
|
const log = opts.log ?? (() => {
|
|
@@ -5552,8 +5612,8 @@ async function pickProfile(opts = {}) {
|
|
|
5552
5612
|
return { profile, mode };
|
|
5553
5613
|
}
|
|
5554
5614
|
// src/lib/hook.ts
|
|
5555
|
-
import { existsSync as
|
|
5556
|
-
import { join as
|
|
5615
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync6, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "node:fs";
|
|
5616
|
+
import { join as join11 } from "node:path";
|
|
5557
5617
|
var HOOK_FILE = "claude-hook.sh";
|
|
5558
5618
|
var MARKER = "# accounts-claude-hook";
|
|
5559
5619
|
var NAME_PATTERN = "^[a-z0-9][a-z0-9-]*$";
|
|
@@ -5561,7 +5621,7 @@ function shellQuotePath(path) {
|
|
|
5561
5621
|
return `'${path.replace(/'/g, `'\\''`)}'`;
|
|
5562
5622
|
}
|
|
5563
5623
|
function hookPath() {
|
|
5564
|
-
return
|
|
5624
|
+
return join11(accountsHome(), HOOK_FILE);
|
|
5565
5625
|
}
|
|
5566
5626
|
function hookScript() {
|
|
5567
5627
|
const quotedHook = shellQuotePath(hookPath());
|
|
@@ -5591,16 +5651,16 @@ claude() {
|
|
|
5591
5651
|
}
|
|
5592
5652
|
function installHook() {
|
|
5593
5653
|
const path = hookPath();
|
|
5594
|
-
|
|
5595
|
-
const created = !
|
|
5596
|
-
|
|
5654
|
+
mkdirSync8(accountsHome(), { recursive: true });
|
|
5655
|
+
const created = !existsSync10(path);
|
|
5656
|
+
writeFileSync6(path, hookScript(), { mode: 493 });
|
|
5597
5657
|
return { path, created };
|
|
5598
5658
|
}
|
|
5599
5659
|
function uninstallHook() {
|
|
5600
5660
|
const path = hookPath();
|
|
5601
|
-
if (!
|
|
5661
|
+
if (!existsSync10(path))
|
|
5602
5662
|
return false;
|
|
5603
|
-
const content =
|
|
5663
|
+
const content = readFileSync6(path, "utf8");
|
|
5604
5664
|
if (!content.includes(MARKER))
|
|
5605
5665
|
return false;
|
|
5606
5666
|
unlinkSync3(path);
|
|
@@ -5654,6 +5714,7 @@ export {
|
|
|
5654
5714
|
listTools,
|
|
5655
5715
|
listSupervisorStates,
|
|
5656
5716
|
listProfiles,
|
|
5717
|
+
launchArgsFor,
|
|
5657
5718
|
keychainSupported,
|
|
5658
5719
|
isSafeProfileName,
|
|
5659
5720
|
isBuiltinTool,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-app.d.ts","sourceRoot":"","sources":["../../src/lib/codex-app.ts"],"names":[],"mappings":"AAgBA,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAMpE"}
|
package/dist/lib/env.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/lib/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/lib/env.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAQpD,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAalF;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAIxE;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAIrE"}
|
package/dist/lib/tools.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ToolDef } from "../types.js";
|
|
1
|
+
import { type Profile, type ToolDef } from "../types.js";
|
|
2
2
|
/**
|
|
3
3
|
* Built-in tools. Users can register more at runtime with `accounts tools add`,
|
|
4
4
|
* which persists them in the store — so the CLI scales to any app that reads a
|
|
@@ -8,9 +8,11 @@ export declare const BUILTIN_TOOLS: ToolDef[];
|
|
|
8
8
|
export declare const DEFAULT_TOOL = "claude";
|
|
9
9
|
export interface ToolArgOptions {
|
|
10
10
|
permissions?: string;
|
|
11
|
+
profile?: Profile;
|
|
11
12
|
}
|
|
12
13
|
export declare function normalizePermissionPreset(value: string): string;
|
|
13
14
|
export declare function permissionArgsFor(tool: ToolDef, permissions?: string): string[];
|
|
15
|
+
export declare function launchArgsFor(tool: ToolDef, profile?: Profile): string[];
|
|
14
16
|
export declare function mergeToolArgs(tool: ToolDef, args: string[], opts?: ToolArgOptions): string[];
|
|
15
17
|
export declare function isBuiltinTool(id: string): boolean;
|
|
16
18
|
/** All tools: built-ins plus any user-registered ones (custom wins on id clash). */
|
package/dist/lib/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAgC,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/lib/tools.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAgC,MAAM,aAAa,CAAC;AAGvF;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,OAAO,EAoJlC,CAAC;AAEF,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAkBD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAW/E;AASD,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,CAGxE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE,cAAmB,GAAG,MAAM,EAAE,CAIhG;AAID,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,oFAAoF;AACpF,wBAAgB,SAAS,IAAI,OAAO,EAAE,CAMrC;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAS3C;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAanD;AAED,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAWjD"}
|
package/dist/mcp.js
CHANGED
|
@@ -16635,6 +16635,7 @@ var toolDefSchema = exports_external.object({
|
|
|
16635
16635
|
loginHint: exports_external.string().optional(),
|
|
16636
16636
|
resumeArgs: exports_external.array(exports_external.string()).optional(),
|
|
16637
16637
|
permissionArgs: exports_external.record(exports_external.array(exports_external.string())).optional(),
|
|
16638
|
+
launchArgs: exports_external.array(exports_external.string()).optional(),
|
|
16638
16639
|
accountFile: exports_external.string().optional(),
|
|
16639
16640
|
emailPath: exports_external.array(exports_external.string()).optional()
|
|
16640
16641
|
});
|
|
@@ -16805,6 +16806,9 @@ var BUILTIN_TOOLS = [
|
|
|
16805
16806
|
id: "claude",
|
|
16806
16807
|
label: "Claude Code",
|
|
16807
16808
|
envVar: "CLAUDE_CONFIG_DIR",
|
|
16809
|
+
extraEnv: {
|
|
16810
|
+
TELEGRAM_STATE_DIR: "{profileDir}/channels/telegram"
|
|
16811
|
+
},
|
|
16808
16812
|
defaultDir: join2(homedir2(), ".claude"),
|
|
16809
16813
|
bin: "claude",
|
|
16810
16814
|
loginHint: "run /login inside Claude, then /exit when done",
|
|
@@ -16821,6 +16825,16 @@ var BUILTIN_TOOLS = [
|
|
|
16821
16825
|
accountFile: ".claude.json",
|
|
16822
16826
|
emailPath: ["oauthAccount", "emailAddress"]
|
|
16823
16827
|
},
|
|
16828
|
+
{
|
|
16829
|
+
id: "codex-app",
|
|
16830
|
+
label: "Codex App",
|
|
16831
|
+
envVar: "CODEX_HOME",
|
|
16832
|
+
defaultDir: join2(homedir2(), ".codex"),
|
|
16833
|
+
bin: "/Applications/Codex.app/Contents/MacOS/Codex",
|
|
16834
|
+
loginHint: "sign in inside Codex.app, then quit the app when the profile is ready",
|
|
16835
|
+
launchArgs: ["--user-data-dir={profileDir}/electron-user-data"],
|
|
16836
|
+
accountFile: "auth.json"
|
|
16837
|
+
},
|
|
16824
16838
|
{
|
|
16825
16839
|
id: "codex",
|
|
16826
16840
|
label: "Codex CLI",
|
|
@@ -16969,9 +16983,17 @@ function permissionArgsFor(tool, permissions) {
|
|
|
16969
16983
|
}
|
|
16970
16984
|
return args;
|
|
16971
16985
|
}
|
|
16986
|
+
function renderToolArg(value, profile) {
|
|
16987
|
+
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
16988
|
+
}
|
|
16989
|
+
function launchArgsFor(tool, profile) {
|
|
16990
|
+
const args = tool.launchArgs ?? [];
|
|
16991
|
+
return profile ? args.map((arg) => renderToolArg(arg, profile)) : args;
|
|
16992
|
+
}
|
|
16972
16993
|
function mergeToolArgs(tool, args, opts = {}) {
|
|
16994
|
+
const launchArgs = launchArgsFor(tool, opts.profile).filter((arg) => !args.includes(arg));
|
|
16973
16995
|
const permissionArgs = permissionArgsFor(tool, opts.permissions).filter((arg) => !args.includes(arg));
|
|
16974
|
-
return [...permissionArgs, ...args];
|
|
16996
|
+
return [...permissionArgs, ...launchArgs, ...args];
|
|
16975
16997
|
}
|
|
16976
16998
|
var BUILTIN_IDS = new Set(BUILTIN_TOOLS.map((t) => t.id));
|
|
16977
16999
|
function listTools() {
|
|
@@ -17037,7 +17059,7 @@ function currentProfile(toolId) {
|
|
|
17037
17059
|
const name = store.current[toolId];
|
|
17038
17060
|
if (!name)
|
|
17039
17061
|
return;
|
|
17040
|
-
return store.profiles.find((p) => p.name === name);
|
|
17062
|
+
return store.profiles.find((p) => p.name === name && p.tool === toolId);
|
|
17041
17063
|
}
|
|
17042
17064
|
|
|
17043
17065
|
// src/lib/claude-auth.ts
|
|
@@ -17443,6 +17465,42 @@ function applyProfileUnlocked(name, toolId) {
|
|
|
17443
17465
|
return { profile, ...previous && previous !== name ? { previous } : {} };
|
|
17444
17466
|
}
|
|
17445
17467
|
|
|
17468
|
+
// src/lib/codex-app.ts
|
|
17469
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
17470
|
+
import { join as join6 } from "node:path";
|
|
17471
|
+
var FILE_CREDENTIALS_LINE = 'cli_auth_credentials_store = "file"';
|
|
17472
|
+
function insertRootConfigLine(config2, line) {
|
|
17473
|
+
if (config2.trim() === "")
|
|
17474
|
+
return `${line}
|
|
17475
|
+
`;
|
|
17476
|
+
const lines = config2.split(/\r?\n/);
|
|
17477
|
+
const tableIndex = lines.findIndex((entry) => /^\s*\[[^\]]+\]\s*(?:#.*)?$/.test(entry));
|
|
17478
|
+
if (tableIndex === -1)
|
|
17479
|
+
return `${config2.trimEnd()}
|
|
17480
|
+
|
|
17481
|
+
${line}
|
|
17482
|
+
`;
|
|
17483
|
+
const before = lines.slice(0, tableIndex).join(`
|
|
17484
|
+
`).trimEnd();
|
|
17485
|
+
const after = lines.slice(tableIndex).join(`
|
|
17486
|
+
`).trimStart();
|
|
17487
|
+
return `${before}${before ? `
|
|
17488
|
+
|
|
17489
|
+
` : ""}${line}
|
|
17490
|
+
|
|
17491
|
+
${after}${after.endsWith(`
|
|
17492
|
+
`) ? "" : `
|
|
17493
|
+
`}`;
|
|
17494
|
+
}
|
|
17495
|
+
function ensureCodexAppProfileConfig(profileDir) {
|
|
17496
|
+
mkdirSync5(profileDir, { recursive: true });
|
|
17497
|
+
const configPath = join6(profileDir, "config.toml");
|
|
17498
|
+
const current = existsSync5(configPath) ? readFileSync3(configPath, "utf8") : "";
|
|
17499
|
+
if (/^\s*cli_auth_credentials_store\s*=/.test(current))
|
|
17500
|
+
return;
|
|
17501
|
+
writeFileSync4(configPath, insertRootConfigLine(current, FILE_CREDENTIALS_LINE), { mode: 384 });
|
|
17502
|
+
}
|
|
17503
|
+
|
|
17446
17504
|
// src/lib/env.ts
|
|
17447
17505
|
function renderTemplate(value, profile) {
|
|
17448
17506
|
return value.replaceAll("{profileDir}", profile.dir).replaceAll("{profileName}", profile.name).replaceAll("{toolId}", profile.tool);
|
|
@@ -17459,6 +17517,8 @@ function profileEnv(profile, tool) {
|
|
|
17459
17517
|
for (const key of CLAUDE_API_AUTH_ENV_KEYS)
|
|
17460
17518
|
env[key] = "";
|
|
17461
17519
|
}
|
|
17520
|
+
if (tool.id === "codex-app")
|
|
17521
|
+
ensureCodexAppProfileConfig(profile.dir);
|
|
17462
17522
|
return env;
|
|
17463
17523
|
}
|
|
17464
17524
|
function formatEnvAssignments(env) {
|
|
@@ -17478,9 +17538,9 @@ function shellQuote(value) {
|
|
|
17478
17538
|
function commandLine(env, command) {
|
|
17479
17539
|
return `${formatEnvAssignments(env)} ${command.map(shellQuote).join(" ")}`.trim();
|
|
17480
17540
|
}
|
|
17481
|
-
function commandFor(tool, opts) {
|
|
17541
|
+
function commandFor(profile, tool, opts) {
|
|
17482
17542
|
const args = [...opts.resume ? tool.resumeArgs ?? [] : [], ...opts.args ?? []];
|
|
17483
|
-
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions })];
|
|
17543
|
+
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions, profile })];
|
|
17484
17544
|
}
|
|
17485
17545
|
function switchProfile(name, opts = {}) {
|
|
17486
17546
|
const profile = getProfile(name, opts.tool);
|
|
@@ -17497,7 +17557,7 @@ function switchProfile(name, opts = {}) {
|
|
|
17497
17557
|
} else {
|
|
17498
17558
|
useProfile(name, tool.id);
|
|
17499
17559
|
}
|
|
17500
|
-
const command = commandFor(tool, opts);
|
|
17560
|
+
const command = commandFor(profile, tool, opts);
|
|
17501
17561
|
const restartRequired = opts.resume === true || applied || mode === "env";
|
|
17502
17562
|
const message = applied ? `${profile.name} is now the live/default ${tool.label} profile` : `${profile.name} is now the active ${tool.label} profile`;
|
|
17503
17563
|
return {
|
|
@@ -17517,22 +17577,22 @@ function switchProfile(name, opts = {}) {
|
|
|
17517
17577
|
|
|
17518
17578
|
// src/lib/supervisor.ts
|
|
17519
17579
|
import { createHash } from "node:crypto";
|
|
17520
|
-
import { existsSync as
|
|
17580
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync6, readFileSync as readFileSync4, readdirSync, rmSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
17521
17581
|
import { createConnection, createServer } from "node:net";
|
|
17522
|
-
import { basename, join as
|
|
17582
|
+
import { basename, join as join7 } from "node:path";
|
|
17523
17583
|
var STATE_SUFFIX = ".json";
|
|
17524
17584
|
function supervisorDir() {
|
|
17525
|
-
return
|
|
17585
|
+
return join7(accountsHome(), "supervisors");
|
|
17526
17586
|
}
|
|
17527
17587
|
function supervisorStatePath(toolId) {
|
|
17528
|
-
return
|
|
17588
|
+
return join7(supervisorDir(), `${toolId}${STATE_SUFFIX}`);
|
|
17529
17589
|
}
|
|
17530
17590
|
function supervisorSocketPath(toolId) {
|
|
17531
17591
|
if (process.platform === "win32") {
|
|
17532
17592
|
const hash = createHash("sha1").update(accountsHome()).digest("hex").slice(0, 12);
|
|
17533
17593
|
return `\\\\.\\pipe\\hasna-accounts-${hash}-${toolId}`;
|
|
17534
17594
|
}
|
|
17535
|
-
return
|
|
17595
|
+
return join7(supervisorDir(), `${toolId}.sock`);
|
|
17536
17596
|
}
|
|
17537
17597
|
function parseState(raw) {
|
|
17538
17598
|
const data = JSON.parse(raw);
|
|
@@ -17543,17 +17603,17 @@ function parseState(raw) {
|
|
|
17543
17603
|
}
|
|
17544
17604
|
function readSupervisorState(toolId) {
|
|
17545
17605
|
const path = supervisorStatePath(toolId);
|
|
17546
|
-
if (!
|
|
17606
|
+
if (!existsSync6(path))
|
|
17547
17607
|
return;
|
|
17548
17608
|
try {
|
|
17549
|
-
return parseState(
|
|
17609
|
+
return parseState(readFileSync4(path, "utf8"));
|
|
17550
17610
|
} catch {
|
|
17551
17611
|
return;
|
|
17552
17612
|
}
|
|
17553
17613
|
}
|
|
17554
17614
|
function listSupervisorStates() {
|
|
17555
17615
|
const dir = supervisorDir();
|
|
17556
|
-
if (!
|
|
17616
|
+
if (!existsSync6(dir))
|
|
17557
17617
|
return [];
|
|
17558
17618
|
return readdirSync(dir).filter((name) => name.endsWith(STATE_SUFFIX)).map((name) => basename(name, STATE_SUFFIX)).map((toolId) => readSupervisorState(toolId)).filter((state) => state !== undefined);
|
|
17559
17619
|
}
|
|
@@ -17619,7 +17679,7 @@ function ok(data) {
|
|
|
17619
17679
|
function fail(message) {
|
|
17620
17680
|
return { content: [{ type: "text", text: JSON.stringify({ error: message }) }], isError: true };
|
|
17621
17681
|
}
|
|
17622
|
-
var server = new Server({ name: "accounts", version: "0.1.
|
|
17682
|
+
var server = new Server({ name: "accounts", version: "0.1.16" }, { capabilities: { tools: {} } });
|
|
17623
17683
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
17624
17684
|
tools: [
|
|
17625
17685
|
{
|
package/dist/storage.js
CHANGED
|
@@ -4008,6 +4008,7 @@ var toolDefSchema = exports_external.object({
|
|
|
4008
4008
|
loginHint: exports_external.string().optional(),
|
|
4009
4009
|
resumeArgs: exports_external.array(exports_external.string()).optional(),
|
|
4010
4010
|
permissionArgs: exports_external.record(exports_external.array(exports_external.string())).optional(),
|
|
4011
|
+
launchArgs: exports_external.array(exports_external.string()).optional(),
|
|
4011
4012
|
accountFile: exports_external.string().optional(),
|
|
4012
4013
|
emailPath: exports_external.array(exports_external.string()).optional()
|
|
4013
4014
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export declare const toolDefSchema: z.ZodObject<{
|
|
|
14
14
|
resumeArgs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
15
15
|
/** Tool-specific permission presets exposed through `--permissions <preset>`. */
|
|
16
16
|
permissionArgs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
17
|
+
/** Tool args prepended for launch/login/run; supports {profileDir}, {profileName}, {toolId}. */
|
|
18
|
+
launchArgs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
17
19
|
accountFile: z.ZodOptional<z.ZodString>;
|
|
18
20
|
emailPath: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
19
21
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -27,6 +29,7 @@ export declare const toolDefSchema: z.ZodObject<{
|
|
|
27
29
|
loginHint?: string | undefined;
|
|
28
30
|
resumeArgs?: string[] | undefined;
|
|
29
31
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
32
|
+
launchArgs?: string[] | undefined;
|
|
30
33
|
accountFile?: string | undefined;
|
|
31
34
|
emailPath?: string[] | undefined;
|
|
32
35
|
}, {
|
|
@@ -40,6 +43,7 @@ export declare const toolDefSchema: z.ZodObject<{
|
|
|
40
43
|
loginHint?: string | undefined;
|
|
41
44
|
resumeArgs?: string[] | undefined;
|
|
42
45
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
46
|
+
launchArgs?: string[] | undefined;
|
|
43
47
|
accountFile?: string | undefined;
|
|
44
48
|
emailPath?: string[] | undefined;
|
|
45
49
|
}>;
|
|
@@ -123,6 +127,8 @@ export declare const storeSchema: z.ZodObject<{
|
|
|
123
127
|
resumeArgs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
124
128
|
/** Tool-specific permission presets exposed through `--permissions <preset>`. */
|
|
125
129
|
permissionArgs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
130
|
+
/** Tool args prepended for launch/login/run; supports {profileDir}, {profileName}, {toolId}. */
|
|
131
|
+
launchArgs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
126
132
|
accountFile: z.ZodOptional<z.ZodString>;
|
|
127
133
|
emailPath: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
128
134
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -136,6 +142,7 @@ export declare const storeSchema: z.ZodObject<{
|
|
|
136
142
|
loginHint?: string | undefined;
|
|
137
143
|
resumeArgs?: string[] | undefined;
|
|
138
144
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
145
|
+
launchArgs?: string[] | undefined;
|
|
139
146
|
accountFile?: string | undefined;
|
|
140
147
|
emailPath?: string[] | undefined;
|
|
141
148
|
}, {
|
|
@@ -149,6 +156,7 @@ export declare const storeSchema: z.ZodObject<{
|
|
|
149
156
|
loginHint?: string | undefined;
|
|
150
157
|
resumeArgs?: string[] | undefined;
|
|
151
158
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
159
|
+
launchArgs?: string[] | undefined;
|
|
152
160
|
accountFile?: string | undefined;
|
|
153
161
|
emailPath?: string[] | undefined;
|
|
154
162
|
}>, "many">>;
|
|
@@ -176,6 +184,7 @@ export declare const storeSchema: z.ZodObject<{
|
|
|
176
184
|
loginHint?: string | undefined;
|
|
177
185
|
resumeArgs?: string[] | undefined;
|
|
178
186
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
187
|
+
launchArgs?: string[] | undefined;
|
|
179
188
|
accountFile?: string | undefined;
|
|
180
189
|
emailPath?: string[] | undefined;
|
|
181
190
|
}[];
|
|
@@ -203,6 +212,7 @@ export declare const storeSchema: z.ZodObject<{
|
|
|
203
212
|
loginHint?: string | undefined;
|
|
204
213
|
resumeArgs?: string[] | undefined;
|
|
205
214
|
permissionArgs?: Record<string, string[]> | undefined;
|
|
215
|
+
launchArgs?: string[] | undefined;
|
|
206
216
|
accountFile?: string | undefined;
|
|
207
217
|
emailPath?: string[] | undefined;
|
|
208
218
|
}[] | undefined;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,8BAA8B;AAC9B,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C,uEAAuE;AACvE,eAAO,MAAM,aAAa;;;;;;;;;;IAUxB,iFAAiF
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,8BAA8B;AAC9B,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C,uEAAuE;AACvE,eAAO,MAAM,aAAa;;;;;;;;;;IAUxB,iFAAiF;;IAEjF,gGAAgG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAIhG,CAAC;AAEH;;;;;GAKG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;EAQxB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,eAAO,MAAM,WAAW;;IAEtB,mEAAmE;;IAEnE;;;OAGG;;;;;;;;;;;;;;;;;;;;;;;;;;;IAGH,0EAA0E;;;;;;;;;;;QAtC1E,iFAAiF;;QAEjF,gGAAgG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsChG,CAAC;AAEH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,qBAAa,aAAc,SAAQ,KAAK;gBAC1B,OAAO,EAAE,MAAM;CAI5B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/accounts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Manage and switch between multiple Claude Code (and other AI coding tool) profiles/accounts locally — isolated config dirs, per-account email, one-command switching.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|