@hasna/accounts 0.1.11 → 0.1.13
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 +12 -4
- package/dist/cli.js +203 -20
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +426 -279
- package/dist/lib/claude-auth.d.ts +4 -0
- package/dist/lib/claude-auth.d.ts.map +1 -1
- package/dist/lib/env.d.ts.map +1 -1
- package/dist/lib/supervisor.d.ts +1 -0
- package/dist/lib/supervisor.d.ts.map +1 -1
- package/dist/lib/switch.d.ts +2 -0
- package/dist/lib/switch.d.ts.map +1 -1
- package/dist/lib/tools.d.ts +6 -0
- package/dist/lib/tools.d.ts.map +1 -1
- package/dist/mcp.js +151 -8
- 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
|
@@ -97,8 +97,8 @@ Implementation details: [docs/IMPLEMENT.md](docs/IMPLEMENT.md).
|
|
|
97
97
|
| `accounts login <name> --tool <tool>` | Launch the tool's login flow in an isolated profile dir. |
|
|
98
98
|
| `accounts apply <name> --tool claude` | Apply profile auth to live Claude paths (requires snapshot; Claude-only). |
|
|
99
99
|
| `accounts pick` | Interactive picker; default applies. `--env`, `--no-act`. |
|
|
100
|
-
| `accounts switch <name> --tool <tool>` | Switch profile and print a restart/resume command. Add `--resume
|
|
101
|
-
| `accounts switch <name> --tool <tool> --supervisor` | Ask a running `accounts run <tool>` supervisor to restart under that profile. |
|
|
100
|
+
| `accounts switch <name> --tool <tool>` | Switch profile and print a restart/resume command. Add `--resume`, `--launch`, or `--permissions <preset>`. |
|
|
101
|
+
| `accounts switch <name> --tool <tool> --supervisor` | Ask a running `accounts run <tool>` supervisor to restart under that profile. Supports `--permissions <preset>`. |
|
|
102
102
|
| `accounts use <name> --tool <tool>` | Mark profile active; prints apply/env hints. |
|
|
103
103
|
| `accounts list` (`ls`) | List profiles (`●` active, `◉` applied, `●◉` both). |
|
|
104
104
|
| `accounts show <name> --tool <tool>` | Profile details including active/applied flags. |
|
|
@@ -106,8 +106,8 @@ Implementation details: [docs/IMPLEMENT.md](docs/IMPLEMENT.md).
|
|
|
106
106
|
| `accounts active [tool]` | Print active profile name (scripting). |
|
|
107
107
|
| `accounts applied [tool]` | Print applied profile name (scripting). |
|
|
108
108
|
| `accounts env [name] --tool <tool>` | Print one or more `export ...` lines for the profile. |
|
|
109
|
-
| `accounts launch <name> --tool <tool>` | Launch tool once with profile env. |
|
|
110
|
-
| `accounts run <tool> [args...]` | Run a tool under the supervisor so MCP/CLI can switch and restart it. |
|
|
109
|
+
| `accounts launch <name> --tool <tool>` | Launch tool once with profile env. Supports `--permissions <preset>`. |
|
|
110
|
+
| `accounts run <tool> [args...]` | Run a tool under the supervisor so MCP/CLI can switch and restart it. Supports `--permissions <preset>`. |
|
|
111
111
|
| `accounts supervisor status [tool]` | Show running supervisors. |
|
|
112
112
|
| `accounts supervisor switch <name> --tool <tool>` | Switch a running supervisor to another profile. |
|
|
113
113
|
| `accounts supervisor stop <tool>` | Stop a running supervisor and its child process. |
|
|
@@ -159,11 +159,18 @@ Human equivalent:
|
|
|
159
159
|
```bash
|
|
160
160
|
accounts switch account001 --tool claude --resume
|
|
161
161
|
accounts switch account001 --tool claude --resume --launch
|
|
162
|
+
accounts switch account001 --tool claude --resume --permissions dangerous
|
|
162
163
|
accounts switch account001 --tool claude --supervisor
|
|
163
164
|
accounts switch codex-work --tool codex --resume
|
|
164
165
|
accounts switch ops --tool opencode --resume
|
|
165
166
|
```
|
|
166
167
|
|
|
168
|
+
`--permissions <preset>` maps a permission mode to the tool's own flags. For
|
|
169
|
+
example, `--permissions dangerous` launches Claude/Takumi with
|
|
170
|
+
`--dangerously-skip-permissions`, Codex with
|
|
171
|
+
`--dangerously-bypass-approvals-and-sandbox`, and Gemini/Hermes/Kimi with their
|
|
172
|
+
YOLO mode flags. Unsupported tools fail with a list of configured presets.
|
|
173
|
+
|
|
167
174
|
## Shell hook (optional)
|
|
168
175
|
|
|
169
176
|
```bash
|
|
@@ -233,6 +240,7 @@ For Grok Build, prefer `accounts launch` or `accounts shell`; exporting `HOME`
|
|
|
233
240
|
globally is intentionally not recommended.
|
|
234
241
|
|
|
235
242
|
Custom tools can join supervised resume switching with `accounts tools add ... --resume-arg <arg>`.
|
|
243
|
+
They can also define permission presets with `--permission-arg preset=--flag`.
|
|
236
244
|
|
|
237
245
|
## Library
|
|
238
246
|
|
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
|
+
} else {}
|
|
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 = "/
|
|
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();
|
|
@@ -41977,6 +41977,7 @@ var toolDefSchema = exports_external.object({
|
|
|
41977
41977
|
loginArgs: exports_external.array(exports_external.string()).optional(),
|
|
41978
41978
|
loginHint: exports_external.string().optional(),
|
|
41979
41979
|
resumeArgs: exports_external.array(exports_external.string()).optional(),
|
|
41980
|
+
permissionArgs: exports_external.record(exports_external.array(exports_external.string())).optional(),
|
|
41980
41981
|
accountFile: exports_external.string().optional(),
|
|
41981
41982
|
emailPath: exports_external.array(exports_external.string()).optional()
|
|
41982
41983
|
});
|
|
@@ -42304,6 +42305,15 @@ var BUILTIN_TOOLS = [
|
|
|
42304
42305
|
bin: "claude",
|
|
42305
42306
|
loginHint: "run /login inside Claude, then /exit when done",
|
|
42306
42307
|
resumeArgs: ["--continue"],
|
|
42308
|
+
permissionArgs: {
|
|
42309
|
+
dangerous: ["--dangerously-skip-permissions"],
|
|
42310
|
+
"allow-dangerous": ["--allow-dangerously-skip-permissions"],
|
|
42311
|
+
bypass: ["--permission-mode", "bypassPermissions"],
|
|
42312
|
+
auto: ["--permission-mode", "auto"],
|
|
42313
|
+
"accept-edits": ["--permission-mode", "acceptEdits"],
|
|
42314
|
+
"dont-ask": ["--permission-mode", "dontAsk"],
|
|
42315
|
+
plan: ["--permission-mode", "plan"]
|
|
42316
|
+
},
|
|
42307
42317
|
accountFile: ".claude.json",
|
|
42308
42318
|
emailPath: ["oauthAccount", "emailAddress"]
|
|
42309
42319
|
},
|
|
@@ -42315,7 +42325,10 @@ var BUILTIN_TOOLS = [
|
|
|
42315
42325
|
bin: "codex",
|
|
42316
42326
|
loginArgs: ["login"],
|
|
42317
42327
|
loginHint: "complete the Codex login flow for this CODEX_HOME",
|
|
42318
|
-
resumeArgs: ["resume", "--last"]
|
|
42328
|
+
resumeArgs: ["resume", "--last"],
|
|
42329
|
+
permissionArgs: {
|
|
42330
|
+
dangerous: ["--dangerously-bypass-approvals-and-sandbox"]
|
|
42331
|
+
}
|
|
42319
42332
|
},
|
|
42320
42333
|
{
|
|
42321
42334
|
id: "takumi",
|
|
@@ -42325,6 +42338,15 @@ var BUILTIN_TOOLS = [
|
|
|
42325
42338
|
bin: "takumi",
|
|
42326
42339
|
loginHint: "complete Takumi auth in this TAKUMI_CONFIG_DIR",
|
|
42327
42340
|
resumeArgs: ["--continue"],
|
|
42341
|
+
permissionArgs: {
|
|
42342
|
+
dangerous: ["--dangerously-skip-permissions"],
|
|
42343
|
+
"allow-dangerous": ["--allow-dangerously-skip-permissions"],
|
|
42344
|
+
bypass: ["--permission-mode", "bypassPermissions"],
|
|
42345
|
+
auto: ["--permission-mode", "auto"],
|
|
42346
|
+
"accept-edits": ["--permission-mode", "acceptEdits"],
|
|
42347
|
+
"dont-ask": ["--permission-mode", "dontAsk"],
|
|
42348
|
+
plan: ["--permission-mode", "plan"]
|
|
42349
|
+
},
|
|
42328
42350
|
accountFile: ".claude.json",
|
|
42329
42351
|
emailPath: ["oauthAccount", "emailAddress"]
|
|
42330
42352
|
},
|
|
@@ -42334,7 +42356,13 @@ var BUILTIN_TOOLS = [
|
|
|
42334
42356
|
envVar: "GEMINI_CONFIG_DIR",
|
|
42335
42357
|
defaultDir: join3(homedir3(), ".gemini"),
|
|
42336
42358
|
bin: "gemini",
|
|
42337
|
-
loginHint: "complete Gemini auth in this GEMINI_CONFIG_DIR"
|
|
42359
|
+
loginHint: "complete Gemini auth in this GEMINI_CONFIG_DIR",
|
|
42360
|
+
permissionArgs: {
|
|
42361
|
+
dangerous: ["--yolo"],
|
|
42362
|
+
yolo: ["--yolo"],
|
|
42363
|
+
"auto-edit": ["--approval-mode", "auto_edit"],
|
|
42364
|
+
plan: ["--approval-mode", "plan"]
|
|
42365
|
+
}
|
|
42338
42366
|
},
|
|
42339
42367
|
{
|
|
42340
42368
|
id: "opencode",
|
|
@@ -42373,7 +42401,11 @@ var BUILTIN_TOOLS = [
|
|
|
42373
42401
|
envVar: "HERMES_HOME",
|
|
42374
42402
|
defaultDir: join3(homedir3(), ".hermes"),
|
|
42375
42403
|
bin: "hermes",
|
|
42376
|
-
loginHint: "complete Hermes auth in this HERMES_HOME"
|
|
42404
|
+
loginHint: "complete Hermes auth in this HERMES_HOME",
|
|
42405
|
+
permissionArgs: {
|
|
42406
|
+
dangerous: ["--yolo"],
|
|
42407
|
+
yolo: ["--yolo"]
|
|
42408
|
+
}
|
|
42377
42409
|
},
|
|
42378
42410
|
{
|
|
42379
42411
|
id: "kimi",
|
|
@@ -42382,7 +42414,13 @@ var BUILTIN_TOOLS = [
|
|
|
42382
42414
|
defaultDir: join3(homedir3(), ".kimi-code"),
|
|
42383
42415
|
bin: "kimi",
|
|
42384
42416
|
loginArgs: ["login"],
|
|
42385
|
-
loginHint: "complete kimi login for this KIMI_CODE_HOME"
|
|
42417
|
+
loginHint: "complete kimi login for this KIMI_CODE_HOME",
|
|
42418
|
+
permissionArgs: {
|
|
42419
|
+
dangerous: ["--yolo"],
|
|
42420
|
+
yolo: ["--yolo"],
|
|
42421
|
+
auto: ["--auto"],
|
|
42422
|
+
plan: ["--plan"]
|
|
42423
|
+
}
|
|
42386
42424
|
},
|
|
42387
42425
|
{
|
|
42388
42426
|
id: "grok",
|
|
@@ -42395,6 +42433,43 @@ var BUILTIN_TOOLS = [
|
|
|
42395
42433
|
}
|
|
42396
42434
|
];
|
|
42397
42435
|
var DEFAULT_TOOL = "claude";
|
|
42436
|
+
var PERMISSION_ALIASES = new Map([
|
|
42437
|
+
["danger", "dangerous"],
|
|
42438
|
+
["dangerously-skip-permissions", "dangerous"],
|
|
42439
|
+
["skip-permissions", "dangerous"],
|
|
42440
|
+
["skip", "dangerous"],
|
|
42441
|
+
["bypasspermissions", "bypass"],
|
|
42442
|
+
["bypass-permissions", "bypass"],
|
|
42443
|
+
["acceptedits", "accept-edits"],
|
|
42444
|
+
["accept-edit", "accept-edits"],
|
|
42445
|
+
["autoedit", "auto-edit"],
|
|
42446
|
+
["auto-edits", "auto-edit"],
|
|
42447
|
+
["auto_edit", "auto-edit"],
|
|
42448
|
+
["dontask", "dont-ask"],
|
|
42449
|
+
["dont-ask-permissions", "dont-ask"]
|
|
42450
|
+
]);
|
|
42451
|
+
function normalizePermissionPreset(value) {
|
|
42452
|
+
const normalized = value.trim().replace(/^--/, "").replaceAll("_", "-").toLowerCase();
|
|
42453
|
+
return PERMISSION_ALIASES.get(normalized) ?? normalized;
|
|
42454
|
+
}
|
|
42455
|
+
function permissionArgsFor(tool, permissions) {
|
|
42456
|
+
if (!permissions)
|
|
42457
|
+
return [];
|
|
42458
|
+
const preset = normalizePermissionPreset(permissions);
|
|
42459
|
+
if (preset === "default" || preset === "none" || preset === "off")
|
|
42460
|
+
return [];
|
|
42461
|
+
const args = tool.permissionArgs?.[preset];
|
|
42462
|
+
if (!args) {
|
|
42463
|
+
const supported = Object.keys(tool.permissionArgs ?? {}).sort();
|
|
42464
|
+
const suffix = supported.length > 0 ? ` Supported permissions: ${supported.join(", ")}.` : " No permission presets are configured.";
|
|
42465
|
+
throw new AccountsError(`tool "${tool.id}" does not support permissions "${permissions}".${suffix}`);
|
|
42466
|
+
}
|
|
42467
|
+
return args;
|
|
42468
|
+
}
|
|
42469
|
+
function mergeToolArgs(tool, args, opts = {}) {
|
|
42470
|
+
const permissionArgs = permissionArgsFor(tool, opts.permissions).filter((arg) => !args.includes(arg));
|
|
42471
|
+
return [...permissionArgs, ...args];
|
|
42472
|
+
}
|
|
42398
42473
|
var BUILTIN_IDS = new Set(BUILTIN_TOOLS.map((t) => t.id));
|
|
42399
42474
|
function isBuiltinTool(id) {
|
|
42400
42475
|
return BUILTIN_IDS.has(id);
|
|
@@ -42778,6 +42853,15 @@ function writeClaudeKeychain(cred) {
|
|
|
42778
42853
|
}
|
|
42779
42854
|
|
|
42780
42855
|
// src/lib/claude-auth.ts
|
|
42856
|
+
var CLAUDE_API_AUTH_ENV_KEYS = [
|
|
42857
|
+
"ANTHROPIC_API_KEY",
|
|
42858
|
+
"ANTHROPIC_AUTH_TOKEN",
|
|
42859
|
+
"ANTHROPIC_BASE_URL",
|
|
42860
|
+
"CLAUDE_CODE_API_KEY_HELPER",
|
|
42861
|
+
"CLAUDE_CODE_API_KEY_HELPER_TTL_MS",
|
|
42862
|
+
"CLAUDE_CODE_USE_BEDROCK",
|
|
42863
|
+
"CLAUDE_CODE_USE_VERTEX"
|
|
42864
|
+
];
|
|
42781
42865
|
function readJsonFile(path) {
|
|
42782
42866
|
if (!existsSync6(path))
|
|
42783
42867
|
return;
|
|
@@ -42796,6 +42880,11 @@ function writeJsonFile(path, data, stayUnder) {
|
|
|
42796
42880
|
function readOAuthFromPaths(paths) {
|
|
42797
42881
|
return findOAuthSource(paths)?.oauth;
|
|
42798
42882
|
}
|
|
42883
|
+
function readOAuthSnapshot(profileDir) {
|
|
42884
|
+
const snap = readJsonFile(profileOAuthSnapshot(profileDir));
|
|
42885
|
+
const oauth = snap?.oauthAccount;
|
|
42886
|
+
return oauth && typeof oauth === "object" ? oauth : undefined;
|
|
42887
|
+
}
|
|
42799
42888
|
function findOAuthSource(paths) {
|
|
42800
42889
|
for (const p of paths) {
|
|
42801
42890
|
const data = readJsonFile(p);
|
|
@@ -42837,6 +42926,46 @@ function mergeOAuthInto(paths, oauth, allowDelete, stayUnder) {
|
|
|
42837
42926
|
}
|
|
42838
42927
|
}
|
|
42839
42928
|
}
|
|
42929
|
+
function sanitizeSettingsFile(configDir, stayUnder) {
|
|
42930
|
+
const settingsPath = join7(configDir, "settings.json");
|
|
42931
|
+
const settings = readJsonFile(settingsPath);
|
|
42932
|
+
if (!settings)
|
|
42933
|
+
return false;
|
|
42934
|
+
let changed = false;
|
|
42935
|
+
if ("apiKeyHelper" in settings) {
|
|
42936
|
+
delete settings.apiKeyHelper;
|
|
42937
|
+
changed = true;
|
|
42938
|
+
}
|
|
42939
|
+
const env2 = settings.env;
|
|
42940
|
+
if (env2 && typeof env2 === "object" && !Array.isArray(env2)) {
|
|
42941
|
+
const envRecord = env2;
|
|
42942
|
+
for (const key of CLAUDE_API_AUTH_ENV_KEYS) {
|
|
42943
|
+
if (key in envRecord) {
|
|
42944
|
+
delete envRecord[key];
|
|
42945
|
+
changed = true;
|
|
42946
|
+
}
|
|
42947
|
+
}
|
|
42948
|
+
}
|
|
42949
|
+
if (changed)
|
|
42950
|
+
writeJsonFile(settingsPath, settings, stayUnder);
|
|
42951
|
+
return changed;
|
|
42952
|
+
}
|
|
42953
|
+
function sanitizeClaudeProfileApiSettings(profileDir, tool) {
|
|
42954
|
+
if (tool.id !== "claude")
|
|
42955
|
+
return false;
|
|
42956
|
+
return sanitizeSettingsFile(profileDir, profileDir);
|
|
42957
|
+
}
|
|
42958
|
+
function sanitizeClaudeOAuthProfileSettings(profileDir, tool) {
|
|
42959
|
+
if (tool.id !== "claude")
|
|
42960
|
+
return false;
|
|
42961
|
+
if (!readOAuthSnapshot(profileDir) && !readOAuthFromPaths(profileAccountJsonPaths(profileDir, tool))) {
|
|
42962
|
+
return false;
|
|
42963
|
+
}
|
|
42964
|
+
return sanitizeClaudeProfileApiSettings(profileDir, tool);
|
|
42965
|
+
}
|
|
42966
|
+
function sanitizeLiveClaudeOAuthSettings() {
|
|
42967
|
+
return sanitizeSettingsFile(liveClaudePaths().configDir, liveClaudeBase());
|
|
42968
|
+
}
|
|
42840
42969
|
function liveOAuthEmail() {
|
|
42841
42970
|
const live = liveClaudePaths();
|
|
42842
42971
|
const oauth = readOAuthFromPaths([live.homeJson]);
|
|
@@ -42877,6 +43006,7 @@ function ensureProfileAuthSnapshot(profileDir, tool, opts = {}) {
|
|
|
42877
43006
|
assertSafeWritePath(credSnap, { mustStayUnder: profileDir });
|
|
42878
43007
|
copyFileSync(credFile, credSnap);
|
|
42879
43008
|
}
|
|
43009
|
+
sanitizeClaudeOAuthProfileSettings(profileDir, tool);
|
|
42880
43010
|
}
|
|
42881
43011
|
function profileHasAuth(profileDir, tool) {
|
|
42882
43012
|
return hasAuthSnapshot(profileDir) || !!readOAuthFromPaths(profileAccountJsonPaths(profileDir, tool));
|
|
@@ -42895,6 +43025,8 @@ function restoreClaudeAuthFromProfile(profileDir, tool, profileName) {
|
|
|
42895
43025
|
if (!oauth) {
|
|
42896
43026
|
throw new AccountsError("profile has no OAuth account data to apply");
|
|
42897
43027
|
}
|
|
43028
|
+
sanitizeClaudeOAuthProfileSettings(profileDir, tool);
|
|
43029
|
+
sanitizeLiveClaudeOAuthSettings();
|
|
42898
43030
|
assertSafeWritePath(live.homeJson, { mustStayUnder: liveRoot });
|
|
42899
43031
|
mergeOAuthInto([live.homeJson], oauth, false, liveRoot);
|
|
42900
43032
|
const credSnap = profileCredentialsSnapshot(profileDir);
|
|
@@ -43345,6 +43477,11 @@ function profileEnv(profile, tool) {
|
|
|
43345
43477
|
for (const [name, value] of Object.entries(tool.extraEnv ?? {})) {
|
|
43346
43478
|
env2[name] = renderTemplate(value, profile);
|
|
43347
43479
|
}
|
|
43480
|
+
if (tool.id === "claude") {
|
|
43481
|
+
sanitizeClaudeProfileApiSettings(profile.dir, tool);
|
|
43482
|
+
for (const key of CLAUDE_API_AUTH_ENV_KEYS)
|
|
43483
|
+
env2[key] = "";
|
|
43484
|
+
}
|
|
43348
43485
|
return env2;
|
|
43349
43486
|
}
|
|
43350
43487
|
function formatEnvAssignments(env2) {
|
|
@@ -43379,7 +43516,8 @@ function commandLine(env2, command) {
|
|
|
43379
43516
|
return `${formatEnvAssignments(env2)} ${command.map(shellQuote).join(" ")}`.trim();
|
|
43380
43517
|
}
|
|
43381
43518
|
function commandFor(tool, opts) {
|
|
43382
|
-
|
|
43519
|
+
const args = [...opts.resume ? tool.resumeArgs ?? [] : [], ...opts.args ?? []];
|
|
43520
|
+
return [tool.bin, ...mergeToolArgs(tool, args, { permissions: opts.permissions })];
|
|
43383
43521
|
}
|
|
43384
43522
|
function switchProfile(name, opts = {}) {
|
|
43385
43523
|
const profile = getProfile(name, opts.tool);
|
|
@@ -43408,6 +43546,7 @@ function switchProfile(name, opts = {}) {
|
|
|
43408
43546
|
exports: formatExportLines(env2),
|
|
43409
43547
|
command,
|
|
43410
43548
|
commandLine: commandLine(env2, command),
|
|
43549
|
+
...opts.permissions ? { permissions: normalizePermissionPreset(opts.permissions) } : {},
|
|
43411
43550
|
restartRequired,
|
|
43412
43551
|
message
|
|
43413
43552
|
};
|
|
@@ -43733,7 +43872,8 @@ async function runSupervisedTool(initialProfile, tool, initialArgs = [], opts =
|
|
|
43733
43872
|
tool: tool.id,
|
|
43734
43873
|
mode: request.mode ?? "auto",
|
|
43735
43874
|
resume: request.resume ?? true,
|
|
43736
|
-
args: request.args ?? []
|
|
43875
|
+
args: request.args ?? [],
|
|
43876
|
+
permissions: request.permissions
|
|
43737
43877
|
});
|
|
43738
43878
|
log(`accounts supervisor: switching ${tool.id} to ${result.profile.name}`);
|
|
43739
43879
|
setTimeout(() => void restartWith(result), 0);
|
|
@@ -43825,6 +43965,20 @@ function printStorageSyncResult(result, json) {
|
|
|
43825
43965
|
console.log(source_default.green(`pushed ${result.pushed}, pulled ${result.pulled}`));
|
|
43826
43966
|
console.log(source_default.dim(`key: ${result.key}`));
|
|
43827
43967
|
}
|
|
43968
|
+
function parsePermissionArgs(entries) {
|
|
43969
|
+
const permissionArgs = {};
|
|
43970
|
+
for (const entry of entries ?? []) {
|
|
43971
|
+
const idx = entry.indexOf("=");
|
|
43972
|
+
if (idx <= 0)
|
|
43973
|
+
die(`invalid --permission-arg ${entry}; expected PRESET=ARG`);
|
|
43974
|
+
const preset = normalizePermissionPreset(entry.slice(0, idx));
|
|
43975
|
+
const arg = entry.slice(idx + 1);
|
|
43976
|
+
if (!arg)
|
|
43977
|
+
die(`invalid --permission-arg ${entry}; expected PRESET=ARG`);
|
|
43978
|
+
(permissionArgs[preset] ??= []).push(arg);
|
|
43979
|
+
}
|
|
43980
|
+
return permissionArgs;
|
|
43981
|
+
}
|
|
43828
43982
|
program2.name("accounts").description("Manage and switch between multiple Claude Code (and other AI tool) profiles/accounts.").version(getVersion());
|
|
43829
43983
|
program2.command("add").argument("<name>", "profile name (lowercase, hyphenated)").description("create a new profile with an isolated config dir").option("-t, --tool <tool>", "tool the profile is for", DEFAULT_TOOL).option("-e, --email <email>", "account email (auto-detected when omitted)").option("-d, --dir <path>", "config dir to use (default: managed dir under ~/.hasna/accounts)").option("--description <text>", "free-text description").action(action((name, opts) => {
|
|
43830
43984
|
const p = addProfile({ name, tool: opts.tool, email: opts.email, dir: opts.dir, description: opts.description });
|
|
@@ -43955,12 +44109,20 @@ program2.command("applied").argument("[tool]", "tool id (default: claude)").desc
|
|
|
43955
44109
|
die(`no applied profile for "${tool}". Run \`accounts apply <name>\` first.`);
|
|
43956
44110
|
console.log(p.name);
|
|
43957
44111
|
}));
|
|
43958
|
-
program2.command("switch").argument("<name>", "profile name").argument("[args...]", "extra args passed when printing/launching the tool").description("switch to a profile and print a restart/resume command; use --launch to run it").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").option("--mode <mode>", "switch mode: auto, apply, env, active", "auto").option("--resume", "include the tool's resume/continue args in the handoff command").option("--launch", "launch the tool after switching").option("--supervisor", "ask a running accounts supervisor to restart the tool").option("--json", "output JSON").action(action(async (name, args, opts) => {
|
|
44112
|
+
program2.command("switch").argument("<name>", "profile name").argument("[args...]", "extra args passed when printing/launching the tool").description("switch to a profile and print a restart/resume command; use --launch to run it").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").option("--mode <mode>", "switch mode: auto, apply, env, active", "auto").option("--resume", "include the tool's resume/continue args in the handoff command").option("--permissions <preset>", "tool-specific permission preset, e.g. dangerous").option("--launch", "launch the tool after switching").option("--supervisor", "ask a running accounts supervisor to restart the tool").option("--json", "output JSON").action(action(async (name, args, opts) => {
|
|
43959
44113
|
if (opts.supervisor && opts.launch)
|
|
43960
44114
|
die("--supervisor and --launch cannot be used together");
|
|
43961
44115
|
if (opts.supervisor) {
|
|
43962
44116
|
const profile = getProfile(name, opts.tool);
|
|
43963
|
-
const response = await sendSupervisorRequest(profile.tool, {
|
|
44117
|
+
const response = await sendSupervisorRequest(profile.tool, {
|
|
44118
|
+
type: "switch_profile",
|
|
44119
|
+
name: profile.name,
|
|
44120
|
+
tool: profile.tool,
|
|
44121
|
+
mode: opts.mode,
|
|
44122
|
+
resume: opts.resume ?? true,
|
|
44123
|
+
args,
|
|
44124
|
+
permissions: opts.permissions
|
|
44125
|
+
}, { allowMissing: true });
|
|
43964
44126
|
if (!response) {
|
|
43965
44127
|
die(`no running accounts supervisor for ${getTool(profile.tool).label}. Start one with \`accounts run ${profile.tool}\`.`);
|
|
43966
44128
|
}
|
|
@@ -43976,7 +44138,13 @@ program2.command("switch").argument("<name>", "profile name").argument("[args...
|
|
|
43976
44138
|
}
|
|
43977
44139
|
return;
|
|
43978
44140
|
}
|
|
43979
|
-
const result = switchProfile(name, {
|
|
44141
|
+
const result = switchProfile(name, {
|
|
44142
|
+
tool: opts.tool,
|
|
44143
|
+
mode: opts.mode,
|
|
44144
|
+
resume: opts.resume,
|
|
44145
|
+
args,
|
|
44146
|
+
permissions: opts.permissions
|
|
44147
|
+
});
|
|
43980
44148
|
if (opts.json) {
|
|
43981
44149
|
console.log(JSON.stringify(result, null, 2));
|
|
43982
44150
|
} else {
|
|
@@ -44022,13 +44190,14 @@ program2.command("env").argument("[name]", "profile name (defaults to the active
|
|
|
44022
44190
|
const tool = getTool(profile.tool);
|
|
44023
44191
|
console.log(formatExportLines(profileEnv(profile, tool)));
|
|
44024
44192
|
}));
|
|
44025
|
-
program2.command("launch").argument("<name>", "profile name").argument("[args...]", "extra args passed to the tool binary").description("launch the tool's binary with the profile's config dir active").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").action(action((name, args, opts) => {
|
|
44193
|
+
program2.command("launch").argument("<name>", "profile name").argument("[args...]", "extra args passed to the tool binary").description("launch the tool's binary with the profile's config dir active").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").option("--permissions <preset>", "tool-specific permission preset, e.g. dangerous").action(action((name, args, opts) => {
|
|
44026
44194
|
const profile = getProfile(name, opts.tool);
|
|
44027
44195
|
const tool = getTool(profile.tool);
|
|
44028
44196
|
const env2 = profileEnv(profile, tool);
|
|
44197
|
+
const launchArgs = mergeToolArgs(tool, args, { permissions: opts.permissions });
|
|
44029
44198
|
useProfile(name, tool.id);
|
|
44030
|
-
console.log(source_default.dim(`→ ${formatEnvAssignments(env2)} ${tool.bin} ${
|
|
44031
|
-
const res = spawnSync2(tool.bin,
|
|
44199
|
+
console.log(source_default.dim(`→ ${formatEnvAssignments(env2)} ${tool.bin} ${launchArgs.join(" ")}`));
|
|
44200
|
+
const res = spawnSync2(tool.bin, launchArgs, {
|
|
44032
44201
|
stdio: "inherit",
|
|
44033
44202
|
env: { ...process.env, ...env2 }
|
|
44034
44203
|
});
|
|
@@ -44036,9 +44205,11 @@ program2.command("launch").argument("<name>", "profile name").argument("[args...
|
|
|
44036
44205
|
die(`failed to launch ${tool.bin}: ${res.error.message}`);
|
|
44037
44206
|
process.exit(res.status ?? 0);
|
|
44038
44207
|
}));
|
|
44039
|
-
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").action(action(async (target, args, opts) => {
|
|
44208
|
+
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) => {
|
|
44040
44209
|
const plan = resolveSupervisorLaunch(target, { profile: opts.profile, tool: opts.tool });
|
|
44041
|
-
const runArgs = [...opts.resume ? plan.tool.resumeArgs ?? [] : [], ...args]
|
|
44210
|
+
const runArgs = mergeToolArgs(plan.tool, [...opts.resume ? plan.tool.resumeArgs ?? [] : [], ...args], {
|
|
44211
|
+
permissions: opts.permissions
|
|
44212
|
+
});
|
|
44042
44213
|
console.error(source_default.green(`✓ accounts supervisor running ${plan.tool.label} as ${source_default.bold(plan.profile.name)}`));
|
|
44043
44214
|
console.error(source_default.dim(` control: accounts supervisor status ${plan.tool.id}`));
|
|
44044
44215
|
console.error(source_default.dim(` switch: accounts switch <profile> --tool ${plan.tool.id} --supervisor`));
|
|
@@ -44071,9 +44242,17 @@ supervisor.command("status").argument("[tool]", "tool id").description("show run
|
|
|
44071
44242
|
console.log(source_default.dim(` ${state2.command.join(" ")}`));
|
|
44072
44243
|
}
|
|
44073
44244
|
}));
|
|
44074
|
-
supervisor.command("switch").argument("<name>", "profile name").argument("[args...]", "extra args passed after resume/continue args").description("switch a running supervisor to another profile").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").option("--mode <mode>", "switch mode: auto, apply, env, active", "auto").option("--no-resume", "restart without the tool's resume/continue args").option("--json", "output JSON").action(action(async (name, args, opts) => {
|
|
44245
|
+
supervisor.command("switch").argument("<name>", "profile name").argument("[args...]", "extra args passed after resume/continue args").description("switch a running supervisor to another profile").option("-t, --tool <tool>", "tool when the profile name exists for multiple tools").option("--mode <mode>", "switch mode: auto, apply, env, active", "auto").option("--no-resume", "restart without the tool's resume/continue args").option("--permissions <preset>", "tool-specific permission preset, e.g. dangerous").option("--json", "output JSON").action(action(async (name, args, opts) => {
|
|
44075
44246
|
const profile = getProfile(name, opts.tool);
|
|
44076
|
-
const response = await sendSupervisorRequest(profile.tool, {
|
|
44247
|
+
const response = await sendSupervisorRequest(profile.tool, {
|
|
44248
|
+
type: "switch_profile",
|
|
44249
|
+
name: profile.name,
|
|
44250
|
+
tool: profile.tool,
|
|
44251
|
+
mode: opts.mode,
|
|
44252
|
+
resume: opts.resume !== false,
|
|
44253
|
+
args,
|
|
44254
|
+
permissions: opts.permissions
|
|
44255
|
+
}, { allowMissing: true });
|
|
44077
44256
|
if (!response)
|
|
44078
44257
|
die(`no running accounts supervisor for ${getTool(profile.tool).label}`);
|
|
44079
44258
|
if (!response.ok)
|
|
@@ -44209,10 +44388,12 @@ tools.command("list", { isDefault: true }).description("list supported tools (bu
|
|
|
44209
44388
|
for (const t of all) {
|
|
44210
44389
|
const tag = isBuiltinTool(t.id) ? source_default.dim("built-in") : source_default.magenta("custom");
|
|
44211
44390
|
const envNames = [t.envVar, ...Object.keys(t.extraEnv ?? {})].join(", ");
|
|
44212
|
-
|
|
44391
|
+
const permissions = Object.keys(t.permissionArgs ?? {});
|
|
44392
|
+
const permissionsHint = permissions.length > 0 ? source_default.dim(` permissions: ${permissions.sort().join(",")}`) : "";
|
|
44393
|
+
console.log(`${source_default.cyan(t.id.padEnd(10))} ${t.label.padEnd(16)} ${source_default.dim(envNames)} → ${source_default.dim(t.defaultDir)} ${tag}${permissionsHint}`);
|
|
44213
44394
|
}
|
|
44214
44395
|
}));
|
|
44215
|
-
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("--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) => {
|
|
44396
|
+
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) => {
|
|
44216
44397
|
const extraEnv = {};
|
|
44217
44398
|
for (const entry of opts.extraEnv ?? []) {
|
|
44218
44399
|
const idx = entry.indexOf("=");
|
|
@@ -44220,6 +44401,7 @@ tools.command("add").argument("<id>", "tool id, e.g. cursor").description("regis
|
|
|
44220
44401
|
die(`invalid --extra-env ${entry}; expected VAR=VALUE`);
|
|
44221
44402
|
extraEnv[entry.slice(0, idx)] = entry.slice(idx + 1);
|
|
44222
44403
|
}
|
|
44404
|
+
const permissionArgs = parsePermissionArgs(opts.permissionArg);
|
|
44223
44405
|
const def = {
|
|
44224
44406
|
id,
|
|
44225
44407
|
label: opts.label,
|
|
@@ -44229,6 +44411,7 @@ tools.command("add").argument("<id>", "tool id, e.g. cursor").description("regis
|
|
|
44229
44411
|
...Object.keys(extraEnv).length > 0 ? { extraEnv } : {},
|
|
44230
44412
|
...opts.loginArg ? { loginArgs: opts.loginArg } : {},
|
|
44231
44413
|
...opts.resumeArg ? { resumeArgs: opts.resumeArg } : {},
|
|
44414
|
+
...Object.keys(permissionArgs).length > 0 ? { permissionArgs } : {},
|
|
44232
44415
|
...opts.accountFile ? { accountFile: opts.accountFile } : {},
|
|
44233
44416
|
...opts.emailPath ? { emailPath: opts.emailPath.split(".") } : {}
|
|
44234
44417
|
};
|
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, } from "./lib/tools.js";
|
|
3
|
+
export { BUILTIN_TOOLS, DEFAULT_TOOL, getTool, listTools, isBuiltinTool, addCustomTool, removeCustomTool, mergeToolArgs, 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";
|
|
@@ -17,7 +17,7 @@ export type { RunSupervisorOptions, SupervisorClientOptions, SupervisorLaunchPla
|
|
|
17
17
|
export { pickProfile } from "./lib/pick.js";
|
|
18
18
|
export type { PickOptions, PickResult } from "./lib/pick.js";
|
|
19
19
|
export { installHook, uninstallHook, hookPath, hookScript, shellSnippet } from "./lib/hook.js";
|
|
20
|
-
export { snapshotClaudeAuthToProfile, snapshotLiveAuthToProfile, restoreClaudeAuthFromProfile, ensureProfileAuthSnapshot, hasAuthSnapshot, profileHasAuth, } from "./lib/claude-auth.js";
|
|
20
|
+
export { snapshotClaudeAuthToProfile, snapshotLiveAuthToProfile, restoreClaudeAuthFromProfile, ensureProfileAuthSnapshot, hasAuthSnapshot, profileHasAuth, sanitizeClaudeProfileApiSettings, sanitizeClaudeOAuthProfileSettings, sanitizeLiveClaudeOAuthSettings, CLAUDE_API_AUTH_ENV_KEYS, } from "./lib/claude-auth.js";
|
|
21
21
|
export { withApplyLock } from "./lib/apply-lock.js";
|
|
22
22
|
export { isSafeProfileName } from "./lib/hook.js";
|
|
23
23
|
export { readClaudeKeychain, keychainSupported } from "./lib/keychain.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,
|
|
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"}
|