tokenmaxxing 1.10.0 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DESIGN.md +4 -4
- package/README.md +6 -5
- package/agent-plugin/plugin.json +1 -1
- package/agent-plugin/skills/pool-status/SKILL.md +2 -2
- package/agent-plugin/skills/pool-status/references/commands.md +1 -0
- package/agent-plugin/skills/switching-policy/SKILL.md +2 -2
- package/agent-plugin/skills/switching-policy/references/policy.md +1 -1
- package/package.json +1 -1
- package/src/cli/check.ts +17 -4
- package/src/cli/codexrm.ts +8 -7
- package/src/cli/codexswitch.ts +48 -18
- package/src/cli/config.ts +86 -42
- package/src/cli/doctor.ts +25 -9
- package/src/cli/ls.ts +37 -2
- package/src/cli/rename.ts +17 -14
- package/src/cli/render.ts +20 -0
- package/src/cli/rm.ts +12 -8
- package/src/cli/status.ts +239 -110
- package/src/cli/switch.ts +64 -28
- package/src/cli/watch.ts +13 -7
- package/src/entries/mcp.ts +1 -1
- package/src/lib/state.ts +2 -2
- package/src/main.ts +44 -22
package/src/main.ts
CHANGED
|
@@ -26,7 +26,10 @@ import { cmdSwitch } from "./cli/switch.ts";
|
|
|
26
26
|
import { cmdCheck } from "./cli/check.ts";
|
|
27
27
|
import { cmdConfig } from "./cli/config.ts";
|
|
28
28
|
import { timerDeactivationHint, uninstallSupervisor } from "./lib/install.ts";
|
|
29
|
-
import { c } from "./cli/render.ts";
|
|
29
|
+
import { c, emitError, emitJson } from "./cli/render.ts";
|
|
30
|
+
|
|
31
|
+
const JSON_FLAG = "--json";
|
|
32
|
+
const INTERACTIVE_COMMANDS = new Set(["init", "add", "auth"]);
|
|
30
33
|
|
|
31
34
|
function printHelp(): void {
|
|
32
35
|
console.log(`${c.bold("tokenmaxxing")} - automatic Claude Code account switching
|
|
@@ -50,30 +53,45 @@ function printHelp(): void {
|
|
|
50
53
|
${c.cyan("tokenmaxxing rm")} [--codex] <sel>
|
|
51
54
|
${c.cyan("tokenmaxxing uninstall")} remove supervisor + settings entries
|
|
52
55
|
|
|
56
|
+
${c.cyan("--json")} print one JSON document on stdout instead of text (status, ls, config, doctor, check, switch, rename, rm, uninstall; one per tick for watch); every document carries ${c.bold("ok")}, failures add ${c.bold("error")}
|
|
57
|
+
|
|
53
58
|
${c.dim("(aliased as")} ${c.cyan("xx")}${c.dim(")")} - then just run ${c.bold("claude")} as always; it switches accounts near quota automatically.`);
|
|
54
59
|
}
|
|
55
60
|
|
|
61
|
+
let jsonMode = false;
|
|
62
|
+
|
|
56
63
|
async function main(): Promise<number> {
|
|
57
64
|
if (process.platform !== "darwin" && process.platform !== "linux") {
|
|
58
65
|
console.error(`tokenmaxxing supports macOS and Linux only (this is ${process.platform})`);
|
|
59
66
|
return 1;
|
|
60
67
|
}
|
|
61
|
-
const
|
|
68
|
+
const argv = process.argv.slice(2);
|
|
62
69
|
const argv0 = basename(process.argv0 || process.argv[0] || "");
|
|
63
|
-
const sub = args[0];
|
|
64
70
|
|
|
65
|
-
if (argv0 === "claude" ||
|
|
66
|
-
return runSupervisor(
|
|
71
|
+
if (argv0 === "claude" || argv[0] === "__supervise") {
|
|
72
|
+
return runSupervisor(argv[0] === "__supervise" ? argv.slice(1) : argv);
|
|
67
73
|
}
|
|
68
|
-
if (argv0 === "codex" ||
|
|
69
|
-
return runCodexSupervisor({ argv:
|
|
74
|
+
if (argv0 === "codex" || argv[0] === "__supervise-codex") {
|
|
75
|
+
return runCodexSupervisor({ argv: argv[0] === "__supervise-codex" ? argv.slice(1) : argv });
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
jsonMode = argv.includes(JSON_FLAG);
|
|
79
|
+
const json = jsonMode;
|
|
80
|
+
const args = argv.filter((a) => a !== JSON_FLAG);
|
|
81
|
+
const sub = args[0];
|
|
82
|
+
|
|
83
|
+
if (json && sub != null && INTERACTIVE_COMMANDS.has(sub)) {
|
|
84
|
+
emitError({ json, message: `${sub} is interactive (it runs a login flow) and has no --json form` });
|
|
85
|
+
return 2;
|
|
86
|
+
}
|
|
72
87
|
if (!(sub != null && sub.startsWith("__")) && !process.env.TOKENMAXXING_PROBE) {
|
|
73
88
|
const nonEmpty = (v: string | undefined) => (v != null && v !== "" ? v : null);
|
|
74
89
|
const ambient = nonEmpty(process.env.CLAUDE_SECURESTORAGE_CONFIG_DIR) ?? nonEmpty(process.env.CLAUDE_CONFIG_DIR);
|
|
75
90
|
if (ambient != null) {
|
|
76
|
-
|
|
91
|
+
emitError({
|
|
92
|
+
json,
|
|
93
|
+
message: `CLAUDE_CONFIG_DIR / CLAUDE_SECURESTORAGE_CONFIG_DIR is set (${ambient}): claude uses a namespaced credential store there that tokenmaxxing does not manage - unset it (or run from a clean shell) and retry.`,
|
|
94
|
+
});
|
|
77
95
|
return 1;
|
|
78
96
|
}
|
|
79
97
|
}
|
|
@@ -85,26 +103,26 @@ async function main(): Promise<number> {
|
|
|
85
103
|
case "__stop-failure-hook": return runStopFailureHook();
|
|
86
104
|
case "__session-start": return runSessionStart();
|
|
87
105
|
case "__codex-stop-hook": return runCodexStopHook();
|
|
88
|
-
case undefined: return cmdStatus();
|
|
89
|
-
case "--force": return cmdStatus(true);
|
|
106
|
+
case undefined: return cmdStatus({ json });
|
|
107
|
+
case "--force": return cmdStatus({ force: true, json });
|
|
90
108
|
case "switch": {
|
|
91
109
|
const rest = args.slice(1).filter((a) => a !== "--codex");
|
|
92
|
-
return args.includes("--codex") ? cmdCodexSwitch(rest[0]) : cmdSwitch(rest[0]);
|
|
110
|
+
return args.includes("--codex") ? cmdCodexSwitch(rest[0], json) : cmdSwitch(rest[0], json);
|
|
93
111
|
}
|
|
94
|
-
case "check": return cmdCheck(args.slice(1));
|
|
95
|
-
case "config": return cmdConfig(args.slice(1));
|
|
112
|
+
case "check": return cmdCheck(args.slice(1), json);
|
|
113
|
+
case "config": return cmdConfig(args.slice(1), json);
|
|
96
114
|
case "init": return args.includes("--codex") ? cmdCodexInit() : cmdInit();
|
|
97
115
|
case "add": return args.includes("--codex") ? cmdCodexAdd() : cmdAdd();
|
|
98
116
|
case "auth": return cmdAuth(args.slice(1));
|
|
99
|
-
case "ls": return cmdLs();
|
|
100
|
-
case "status": return cmdStatus(args.includes("--force"));
|
|
101
|
-
case "watch": return cmdWatch(args[1]);
|
|
102
|
-
case "doctor": return cmdDoctor();
|
|
117
|
+
case "ls": return cmdLs(json);
|
|
118
|
+
case "status": return cmdStatus({ force: args.includes("--force"), json });
|
|
119
|
+
case "watch": return cmdWatch(args[1], json);
|
|
120
|
+
case "doctor": return cmdDoctor(json);
|
|
103
121
|
case "rm": {
|
|
104
122
|
const rest = args.slice(1).filter((a) => a !== "--codex");
|
|
105
|
-
return args.includes("--codex") ? cmdCodexRm(rest[0]) : cmdRm(rest[0]);
|
|
123
|
+
return args.includes("--codex") ? cmdCodexRm(rest[0], json) : cmdRm(rest[0], json);
|
|
106
124
|
}
|
|
107
|
-
case "rename": return cmdRename(args.slice(1));
|
|
125
|
+
case "rename": return cmdRename(args.slice(1), json);
|
|
108
126
|
case "uninstall": {
|
|
109
127
|
const out = uninstallSupervisor();
|
|
110
128
|
const removed = [
|
|
@@ -113,6 +131,10 @@ async function main(): Promise<number> {
|
|
|
113
131
|
...(out.timerDeactivated ? ["check timer"] : []),
|
|
114
132
|
...(out.pathLineRemoved ? ["rc PATH line"] : []),
|
|
115
133
|
];
|
|
134
|
+
if (json) {
|
|
135
|
+
emitJson({ ok: true, removed, timerDeactivated: out.timerDeactivated, pathLineRemoved: out.pathLineRemoved });
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
116
138
|
console.log(`removed ${removed.join(", ")}`);
|
|
117
139
|
if (!out.timerDeactivated) console.log(c.yellow(`⚠ the check job may still be loaded - run: ${timerDeactivationHint()}`));
|
|
118
140
|
if (!out.pathLineRemoved) console.log(c.dim("(no tokenmaxxing PATH line found in the shell rc)"));
|
|
@@ -125,8 +147,8 @@ async function main(): Promise<number> {
|
|
|
125
147
|
printHelp();
|
|
126
148
|
return 0;
|
|
127
149
|
default:
|
|
128
|
-
|
|
129
|
-
printHelp();
|
|
150
|
+
emitError({ json, message: `unknown command: ${sub}` });
|
|
151
|
+
if (!json) printHelp();
|
|
130
152
|
return 2;
|
|
131
153
|
}
|
|
132
154
|
}
|
|
@@ -134,6 +156,6 @@ async function main(): Promise<number> {
|
|
|
134
156
|
try {
|
|
135
157
|
process.exit(await main());
|
|
136
158
|
} catch (e) {
|
|
137
|
-
|
|
159
|
+
emitError({ json: jsonMode, message: e instanceof Error ? e.message : String(e) });
|
|
138
160
|
process.exit(1);
|
|
139
161
|
}
|