caflip 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -1
- package/dist/cli.js +139 -72
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,6 +67,11 @@ bun run dev -- help
|
|
|
67
67
|
caflip status
|
|
68
68
|
caflip list
|
|
69
69
|
|
|
70
|
+
# Pick provider interactively, then add/remove/login
|
|
71
|
+
caflip add
|
|
72
|
+
caflip remove
|
|
73
|
+
caflip login
|
|
74
|
+
|
|
70
75
|
# Add your first Claude account (must already be logged in)
|
|
71
76
|
caflip claude add --alias personal
|
|
72
77
|
|
|
@@ -106,6 +111,9 @@ After switching, restart the target CLI (Claude Code or Codex) to pick up new au
|
|
|
106
111
|
| `caflip` | Interactive provider picker (Claude/Codex) |
|
|
107
112
|
| `caflip list` | List managed accounts for Claude and Codex |
|
|
108
113
|
| `caflip status` | Show current account for Claude and Codex |
|
|
114
|
+
| `caflip add [--alias name]` | Pick provider, then add current account |
|
|
115
|
+
| `caflip login [-- <args...>]` | Pick provider, then run provider login and register the resulting session |
|
|
116
|
+
| `caflip remove [email]` | Pick provider, then remove an account |
|
|
109
117
|
| `caflip claude [command]` | Run command for Claude provider |
|
|
110
118
|
| `caflip codex [command]` | Run command for Codex provider |
|
|
111
119
|
| `caflip [provider]` | Interactive account picker for that provider |
|
|
@@ -132,11 +140,14 @@ caflip claude alias work hi.lucienlee@gmail.com
|
|
|
132
140
|
caflip codex alias work me@company.com
|
|
133
141
|
```
|
|
134
142
|
|
|
135
|
-
`remove`
|
|
143
|
+
`add`, `remove`, and `login` can be used without a provider prefix. In that case, caflip asks you to choose Claude or Codex first, then continues the normal command flow.
|
|
144
|
+
|
|
145
|
+
`remove` target accepts email only. Omit it to choose from the interactive picker after selecting a provider.
|
|
136
146
|
|
|
137
147
|
`login` can be used without arguments for the default login flow. Pass provider-specific flags after `--`:
|
|
138
148
|
|
|
139
149
|
```bash
|
|
150
|
+
caflip login
|
|
140
151
|
caflip claude login
|
|
141
152
|
caflip claude login -- --email lucien@aibor.io --sso
|
|
142
153
|
caflip codex login -- --device-auth
|
package/dist/cli.js
CHANGED
|
@@ -617,7 +617,7 @@ function validateAlias(alias) {
|
|
|
617
617
|
// package.json
|
|
618
618
|
var package_default = {
|
|
619
619
|
name: "caflip",
|
|
620
|
-
version: "0.3.
|
|
620
|
+
version: "0.3.1",
|
|
621
621
|
type: "module",
|
|
622
622
|
bin: {
|
|
623
623
|
caflip: "bin/caflip"
|
|
@@ -3166,6 +3166,7 @@ async function writeLastProvider(provider) {
|
|
|
3166
3166
|
|
|
3167
3167
|
// src/index.ts
|
|
3168
3168
|
var ADD_CURRENT_ACCOUNT_CHOICE = "__add_current_account__";
|
|
3169
|
+
var INTERACTIVE_PROVIDER_COMMANDS = ["add", "remove", "login"];
|
|
3169
3170
|
var activeBackupDir = BACKUP_DIR;
|
|
3170
3171
|
var activeSequenceFile = SEQUENCE_FILE;
|
|
3171
3172
|
var activeLockDir = LOCK_DIR;
|
|
@@ -3196,6 +3197,76 @@ function showProviderRequiredError(command) {
|
|
|
3196
3197
|
console.error(`Try: caflip claude ${command} or caflip codex ${command}`);
|
|
3197
3198
|
process.exit(2);
|
|
3198
3199
|
}
|
|
3200
|
+
function supportsInteractiveProviderSelection(command) {
|
|
3201
|
+
return INTERACTIVE_PROVIDER_COMMANDS.includes(command ?? "");
|
|
3202
|
+
}
|
|
3203
|
+
async function resolveProviderForCommand(provider, command, deps = {
|
|
3204
|
+
readCliMeta,
|
|
3205
|
+
pickProvider,
|
|
3206
|
+
writeLastProvider
|
|
3207
|
+
}) {
|
|
3208
|
+
if (provider || !supportsInteractiveProviderSelection(command)) {
|
|
3209
|
+
return provider;
|
|
3210
|
+
}
|
|
3211
|
+
const defaultProvider = deps.readCliMeta().lastProvider;
|
|
3212
|
+
const selectedProvider = await deps.pickProvider(defaultProvider);
|
|
3213
|
+
await deps.writeLastProvider(selectedProvider);
|
|
3214
|
+
return selectedProvider;
|
|
3215
|
+
}
|
|
3216
|
+
async function resolveCliContext(parsed, deps = { resolveProviderForCommand }) {
|
|
3217
|
+
let provider = parsed.provider;
|
|
3218
|
+
const args = parsed.commandArgs;
|
|
3219
|
+
const command = args[0];
|
|
3220
|
+
const isHelpCommand = command === "help" || command === "--help" || command === "-h";
|
|
3221
|
+
const isProviderOptionalReadOnlyCommand = command === "list" || command === "status";
|
|
3222
|
+
const supportsInteractiveProvider = supportsInteractiveProviderSelection(command);
|
|
3223
|
+
if (!parsed.isProviderQualified && command && !isHelpCommand && !isProviderOptionalReadOnlyCommand) {
|
|
3224
|
+
const isReservedCommand = RESERVED_COMMANDS.includes(command);
|
|
3225
|
+
if (!isReservedCommand) {
|
|
3226
|
+
console.error("Error: Alias requires provider prefix.");
|
|
3227
|
+
console.error("Try: caflip claude <alias> or caflip codex <alias>");
|
|
3228
|
+
process.exit(2);
|
|
3229
|
+
}
|
|
3230
|
+
if (!supportsInteractiveProvider) {
|
|
3231
|
+
showProviderRequiredError(command);
|
|
3232
|
+
}
|
|
3233
|
+
}
|
|
3234
|
+
if (!command) {
|
|
3235
|
+
return {
|
|
3236
|
+
mode: "interactive-switch",
|
|
3237
|
+
provider,
|
|
3238
|
+
args,
|
|
3239
|
+
command: undefined
|
|
3240
|
+
};
|
|
3241
|
+
}
|
|
3242
|
+
if (isHelpCommand) {
|
|
3243
|
+
showHelp();
|
|
3244
|
+
process.exit(0);
|
|
3245
|
+
}
|
|
3246
|
+
if (!provider) {
|
|
3247
|
+
if (command === "list" || command === "status") {
|
|
3248
|
+
return {
|
|
3249
|
+
mode: "all-providers",
|
|
3250
|
+
provider: null,
|
|
3251
|
+
args,
|
|
3252
|
+
command
|
|
3253
|
+
};
|
|
3254
|
+
}
|
|
3255
|
+
provider = await deps.resolveProviderForCommand(provider, command);
|
|
3256
|
+
if (!provider) {
|
|
3257
|
+
showProviderRequiredError(command);
|
|
3258
|
+
}
|
|
3259
|
+
}
|
|
3260
|
+
if (!provider) {
|
|
3261
|
+
throw new Error("Provider resolution failed");
|
|
3262
|
+
}
|
|
3263
|
+
return {
|
|
3264
|
+
mode: "provider-command",
|
|
3265
|
+
provider,
|
|
3266
|
+
args,
|
|
3267
|
+
command
|
|
3268
|
+
};
|
|
3269
|
+
}
|
|
3199
3270
|
async function syncSequenceActiveAccount(seq) {
|
|
3200
3271
|
const currentEmail = getCurrentAccount();
|
|
3201
3272
|
const resolvedActive = resolveManagedAccountNumberForEmail(seq, currentEmail);
|
|
@@ -3653,6 +3724,9 @@ Commands:
|
|
|
3653
3724
|
(no args) Interactive provider picker
|
|
3654
3725
|
list List managed accounts for all providers
|
|
3655
3726
|
status Show current account for all providers
|
|
3727
|
+
add [--alias <name>] Pick provider, then add current account
|
|
3728
|
+
login [-- <args...>] Pick provider, then run provider login
|
|
3729
|
+
remove [<email>] Pick provider, then remove an account
|
|
3656
3730
|
<provider> Interactive account picker for provider
|
|
3657
3731
|
<provider> <alias> Switch by alias for provider
|
|
3658
3732
|
<provider> list List all managed accounts
|
|
@@ -3668,10 +3742,13 @@ Examples:
|
|
|
3668
3742
|
caflip Pick provider interactively
|
|
3669
3743
|
caflip list List managed accounts for Claude and Codex
|
|
3670
3744
|
caflip status Show current account for Claude and Codex
|
|
3745
|
+
caflip add Pick provider, then add current account
|
|
3746
|
+
caflip login Pick provider, then run provider login
|
|
3747
|
+
caflip remove Pick provider, then remove an account interactively
|
|
3671
3748
|
caflip claude Pick Claude account interactively
|
|
3672
3749
|
caflip claude work Switch Claude account by alias
|
|
3673
3750
|
caflip claude add --alias personal Add current Claude account with alias
|
|
3674
|
-
caflip claude login
|
|
3751
|
+
caflip claude login Run Claude login and register session
|
|
3675
3752
|
caflip claude login -- --email me@example.com --sso
|
|
3676
3753
|
Pass provider-specific flags after --
|
|
3677
3754
|
caflip claude status --json Show Claude status as JSON
|
|
@@ -3681,76 +3758,7 @@ Examples:
|
|
|
3681
3758
|
caflip codex alias work user@company.com
|
|
3682
3759
|
Set Codex alias for target email`);
|
|
3683
3760
|
}
|
|
3684
|
-
async function
|
|
3685
|
-
const parsed = parseProviderArgs(process.argv.slice(2));
|
|
3686
|
-
const provider = parsed.provider;
|
|
3687
|
-
const args = parsed.commandArgs;
|
|
3688
|
-
const command = args[0];
|
|
3689
|
-
let lockHeld = false;
|
|
3690
|
-
const runWithLock = async (fn) => {
|
|
3691
|
-
setupDirectories();
|
|
3692
|
-
acquireLock(activeLockDir);
|
|
3693
|
-
lockHeld = true;
|
|
3694
|
-
try {
|
|
3695
|
-
return await fn();
|
|
3696
|
-
} finally {
|
|
3697
|
-
if (lockHeld) {
|
|
3698
|
-
releaseLock(activeLockDir);
|
|
3699
|
-
lockHeld = false;
|
|
3700
|
-
}
|
|
3701
|
-
}
|
|
3702
|
-
};
|
|
3703
|
-
const runWithProviderLock = async (targetProvider, fn) => {
|
|
3704
|
-
setActiveProvider(targetProvider);
|
|
3705
|
-
return await runWithLock(fn);
|
|
3706
|
-
};
|
|
3707
|
-
const isHelpCommand = command === "help" || command === "--help" || command === "-h";
|
|
3708
|
-
const isProviderOptionalReadOnlyCommand = command === "list" || command === "status";
|
|
3709
|
-
if (!parsed.isProviderQualified && command && !isHelpCommand && !isProviderOptionalReadOnlyCommand) {
|
|
3710
|
-
if (RESERVED_COMMANDS.includes(command)) {
|
|
3711
|
-
showProviderRequiredError(command);
|
|
3712
|
-
} else {
|
|
3713
|
-
console.error("Error: Alias requires provider prefix.");
|
|
3714
|
-
console.error("Try: caflip claude <alias> or caflip codex <alias>");
|
|
3715
|
-
process.exit(2);
|
|
3716
|
-
}
|
|
3717
|
-
}
|
|
3718
|
-
if (!command) {
|
|
3719
|
-
if (!provider) {
|
|
3720
|
-
const defaultProvider = readCliMeta().lastProvider;
|
|
3721
|
-
const selectedProvider = await pickProvider(defaultProvider);
|
|
3722
|
-
await writeLastProvider(selectedProvider);
|
|
3723
|
-
await runWithProviderLock(selectedProvider, async () => {
|
|
3724
|
-
await cmdInteractiveSwitch();
|
|
3725
|
-
});
|
|
3726
|
-
return;
|
|
3727
|
-
}
|
|
3728
|
-
await runWithProviderLock(provider, async () => {
|
|
3729
|
-
await cmdInteractiveSwitch();
|
|
3730
|
-
});
|
|
3731
|
-
return;
|
|
3732
|
-
}
|
|
3733
|
-
if (isHelpCommand) {
|
|
3734
|
-
showHelp();
|
|
3735
|
-
return;
|
|
3736
|
-
}
|
|
3737
|
-
if (!provider) {
|
|
3738
|
-
if (command === "list") {
|
|
3739
|
-
await cmdListAllProviders();
|
|
3740
|
-
return;
|
|
3741
|
-
}
|
|
3742
|
-
if (command === "status") {
|
|
3743
|
-
if (args.includes("--json")) {
|
|
3744
|
-
console.error("Error: Provider is required for status --json.");
|
|
3745
|
-
console.error("Try: caflip claude status --json");
|
|
3746
|
-
process.exit(2);
|
|
3747
|
-
}
|
|
3748
|
-
await cmdStatusAllProviders();
|
|
3749
|
-
return;
|
|
3750
|
-
}
|
|
3751
|
-
showProviderRequiredError(command);
|
|
3752
|
-
}
|
|
3753
|
-
setActiveProvider(provider);
|
|
3761
|
+
async function executeProviderCommand(command, args, provider, runWithLock) {
|
|
3754
3762
|
switch (command) {
|
|
3755
3763
|
case "list":
|
|
3756
3764
|
await cmdList();
|
|
@@ -3815,6 +3823,62 @@ async function main() {
|
|
|
3815
3823
|
}
|
|
3816
3824
|
}
|
|
3817
3825
|
}
|
|
3826
|
+
async function main() {
|
|
3827
|
+
const context = await resolveCliContext(parseProviderArgs(process.argv.slice(2)));
|
|
3828
|
+
let lockHeld = false;
|
|
3829
|
+
const runWithLock = async (fn) => {
|
|
3830
|
+
setupDirectories();
|
|
3831
|
+
acquireLock(activeLockDir);
|
|
3832
|
+
lockHeld = true;
|
|
3833
|
+
try {
|
|
3834
|
+
return await fn();
|
|
3835
|
+
} finally {
|
|
3836
|
+
if (lockHeld) {
|
|
3837
|
+
releaseLock(activeLockDir);
|
|
3838
|
+
lockHeld = false;
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
};
|
|
3842
|
+
const runWithProviderLock = async (targetProvider, fn) => {
|
|
3843
|
+
setActiveProvider(targetProvider);
|
|
3844
|
+
return await runWithLock(fn);
|
|
3845
|
+
};
|
|
3846
|
+
if (context.mode === "interactive-switch") {
|
|
3847
|
+
if (!context.provider) {
|
|
3848
|
+
const defaultProvider = readCliMeta().lastProvider;
|
|
3849
|
+
const selectedProvider = await pickProvider(defaultProvider);
|
|
3850
|
+
await writeLastProvider(selectedProvider);
|
|
3851
|
+
await runWithProviderLock(selectedProvider, async () => {
|
|
3852
|
+
await cmdInteractiveSwitch();
|
|
3853
|
+
});
|
|
3854
|
+
return;
|
|
3855
|
+
}
|
|
3856
|
+
await runWithProviderLock(context.provider, async () => {
|
|
3857
|
+
await cmdInteractiveSwitch();
|
|
3858
|
+
});
|
|
3859
|
+
return;
|
|
3860
|
+
}
|
|
3861
|
+
if (context.mode === "all-providers") {
|
|
3862
|
+
if (context.command === "list") {
|
|
3863
|
+
await cmdListAllProviders();
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
if (context.command === "status") {
|
|
3867
|
+
if (context.args.includes("--json")) {
|
|
3868
|
+
console.error("Error: Provider is required for status --json.");
|
|
3869
|
+
console.error("Try: caflip claude status --json");
|
|
3870
|
+
process.exit(2);
|
|
3871
|
+
}
|
|
3872
|
+
await cmdStatusAllProviders();
|
|
3873
|
+
return;
|
|
3874
|
+
}
|
|
3875
|
+
}
|
|
3876
|
+
const provider = context.provider;
|
|
3877
|
+
const args = context.args;
|
|
3878
|
+
const command = context.command;
|
|
3879
|
+
setActiveProvider(provider);
|
|
3880
|
+
await executeProviderCommand(command, args, provider, runWithLock);
|
|
3881
|
+
}
|
|
3818
3882
|
if (__require.main == __require.module) {
|
|
3819
3883
|
main().catch((err) => {
|
|
3820
3884
|
if (err instanceof PromptCancelledError) {
|
|
@@ -3826,5 +3890,8 @@ if (__require.main == __require.module) {
|
|
|
3826
3890
|
});
|
|
3827
3891
|
}
|
|
3828
3892
|
export {
|
|
3893
|
+
supportsInteractiveProviderSelection,
|
|
3894
|
+
resolveProviderForCommand,
|
|
3895
|
+
resolveCliContext,
|
|
3829
3896
|
performSwitch
|
|
3830
3897
|
};
|