@imdeadpool/codex-account-switcher 0.1.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sls0n
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # codex-auth
2
+
3
+ A command-line tool that lets you manage and switch between multiple Codex accounts instantly, no more constant logins and logouts.
4
+
5
+ > [!WARNING]
6
+ > Not affiliated with OpenAI or Codex. Not an official tool.
7
+
8
+ ## How it Works
9
+
10
+ Codex stores your authentication session in a single `auth.json` file. This tool works by creating named snapshots of that file for each of your accounts. When you want to switch, `codex-auth` swaps the active `~/.codex/auth.json` with the snapshot you select, instantly changing your logged-in account.
11
+
12
+ ## Requirements
13
+
14
+ - Node.js 18 or newer
15
+
16
+ ## Install (npm)
17
+
18
+ ```sh
19
+ npm i -g @imdeadpool/codex-account-switcher
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```sh
25
+ # save the current logged-in token as a named account
26
+ codex-auth save <name>
27
+
28
+ # switch active account (symlinks on macOS/Linux; copies on Windows)
29
+ codex-auth use <name>
30
+
31
+ # or pick interactively
32
+ codex-auth use
33
+
34
+ # list accounts
35
+ codex-auth list
36
+
37
+ # show current account name
38
+ codex-auth current
39
+ ```
40
+
41
+ ### Command reference
42
+
43
+ - `codex-auth save <name>` – Validates `<name>`, ensures `auth.json` exists, then snapshots it to `~/.codex/accounts/<name>.json`.
44
+ - `codex-auth use [name]` – Accepts a name or launches an interactive selector with the current account pre-selected. Copies on Windows, creates a symlink elsewhere, and records the active name.
45
+ - `codex-auth list` – Lists all saved snapshots alphabetically and marks the active one with `*`.
46
+ - `codex-auth current` – Prints the active account name, or a friendly message if none is active.
47
+
48
+ Notes:
49
+
50
+ - Works on macOS/Linux (symlink) and Windows (copy).
51
+ - Requires Node 18+.
@@ -0,0 +1,5 @@
1
+ import { BaseCommand } from "../lib/base-command";
2
+ export default class CurrentCommand extends BaseCommand {
3
+ static description: string;
4
+ run(): Promise<void>;
5
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_command_1 = require("../lib/base-command");
4
+ class CurrentCommand extends base_command_1.BaseCommand {
5
+ async run() {
6
+ await this.runSafe(async () => {
7
+ const name = await this.accounts.getCurrentAccountName();
8
+ this.log(name !== null && name !== void 0 ? name : "No Codex account is active yet.");
9
+ });
10
+ }
11
+ }
12
+ CurrentCommand.description = "Show the currently active account name";
13
+ exports.default = CurrentCommand;
@@ -0,0 +1,5 @@
1
+ import { BaseCommand } from "../lib/base-command";
2
+ export default class ListCommand extends BaseCommand {
3
+ static description: string;
4
+ run(): Promise<void>;
5
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const base_command_1 = require("../lib/base-command");
4
+ class ListCommand extends base_command_1.BaseCommand {
5
+ async run() {
6
+ await this.runSafe(async () => {
7
+ const accounts = await this.accounts.listAccountNames();
8
+ const current = await this.accounts.getCurrentAccountName();
9
+ if (!accounts.length) {
10
+ this.log("No saved Codex accounts yet. Run `codex-auth save <name>`.");
11
+ return;
12
+ }
13
+ for (const name of accounts) {
14
+ const mark = current === name ? "*" : " ";
15
+ this.log(`${mark} ${name}`);
16
+ }
17
+ });
18
+ }
19
+ }
20
+ ListCommand.description = "List accounts managed under ~/.codex";
21
+ exports.default = ListCommand;
@@ -0,0 +1,8 @@
1
+ import { BaseCommand } from "../lib/base-command";
2
+ export default class SaveCommand extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ readonly name: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
6
+ };
7
+ run(): Promise<void>;
8
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const core_1 = require("@oclif/core");
4
+ const base_command_1 = require("../lib/base-command");
5
+ class SaveCommand extends base_command_1.BaseCommand {
6
+ async run() {
7
+ await this.runSafe(async () => {
8
+ const { args } = await this.parse(SaveCommand);
9
+ const savedName = await this.accounts.saveAccount(args.name);
10
+ this.log(`Saved current Codex auth tokens as "${savedName}".`);
11
+ });
12
+ }
13
+ }
14
+ SaveCommand.description = "Save the current ~/.codex/auth.json as a named account";
15
+ SaveCommand.args = {
16
+ name: core_1.Args.string({
17
+ name: "name",
18
+ required: true,
19
+ description: "Name for the account snapshot",
20
+ }),
21
+ };
22
+ exports.default = SaveCommand;
@@ -0,0 +1,9 @@
1
+ import { BaseCommand } from "../lib/base-command";
2
+ export default class UseCommand extends BaseCommand {
3
+ static description: string;
4
+ static args: {
5
+ readonly account: import("@oclif/core/lib/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ run(): Promise<void>;
8
+ private promptForAccount;
9
+ }
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const core_1 = require("@oclif/core");
7
+ const prompts_1 = __importDefault(require("prompts"));
8
+ const base_command_1 = require("../lib/base-command");
9
+ const accounts_1 = require("../lib/accounts");
10
+ class UseCommand extends base_command_1.BaseCommand {
11
+ async run() {
12
+ await this.runSafe(async () => {
13
+ const { args } = await this.parse(UseCommand);
14
+ let account = args.account;
15
+ if (!account) {
16
+ account = await this.promptForAccount();
17
+ }
18
+ const activated = await this.accounts.useAccount(account);
19
+ this.log(`Switched Codex auth to "${activated}".`);
20
+ });
21
+ }
22
+ async promptForAccount() {
23
+ const accounts = await this.accounts.listAccountNames();
24
+ if (!accounts.length) {
25
+ throw new accounts_1.NoAccountsSavedError();
26
+ }
27
+ const current = await this.accounts.getCurrentAccountName();
28
+ const initialIndex = current ? Math.max(accounts.indexOf(current), 0) : 0;
29
+ const response = await (0, prompts_1.default)({
30
+ type: "select",
31
+ name: "account",
32
+ message: "Select account",
33
+ choices: accounts.map((name) => ({
34
+ title: current === name ? `${name} (active)` : name,
35
+ value: name,
36
+ })),
37
+ initial: initialIndex,
38
+ }, {
39
+ onCancel: () => {
40
+ throw new accounts_1.PromptCancelledError();
41
+ },
42
+ });
43
+ const picked = response.account;
44
+ if (!picked) {
45
+ throw new accounts_1.PromptCancelledError();
46
+ }
47
+ return picked;
48
+ }
49
+ }
50
+ UseCommand.description = "Switch ~/.codex/auth.json to the selected account";
51
+ UseCommand.args = {
52
+ account: core_1.Args.string({
53
+ name: "account",
54
+ required: false,
55
+ description: "Account to activate",
56
+ }),
57
+ };
58
+ exports.default = UseCommand;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const core_1 = require("@oclif/core");
5
+ void (0, core_1.run)()
6
+ .then(() => (0, core_1.flush)())
7
+ .catch(core_1.Errors.handle);
@@ -0,0 +1,15 @@
1
+ export declare class AccountService {
2
+ listAccountNames(): Promise<string[]>;
3
+ getCurrentAccountName(): Promise<string | null>;
4
+ saveAccount(rawName: string): Promise<string>;
5
+ useAccount(rawName: string): Promise<string>;
6
+ private accountFilePath;
7
+ private normalizeAccountName;
8
+ private ensureAuthFileExists;
9
+ private ensureDir;
10
+ private replaceSymlink;
11
+ private removeIfExists;
12
+ private writeCurrentName;
13
+ private readCurrentNameFile;
14
+ private pathExists;
15
+ }
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AccountService = void 0;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const promises_1 = __importDefault(require("node:fs/promises"));
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const paths_1 = require("../config/paths");
11
+ const errors_1 = require("./errors");
12
+ const ACCOUNT_NAME_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
13
+ class AccountService {
14
+ async listAccountNames() {
15
+ if (!(await this.pathExists(paths_1.accountsDir))) {
16
+ return [];
17
+ }
18
+ const entries = await promises_1.default.readdir(paths_1.accountsDir, { withFileTypes: true });
19
+ return entries
20
+ .filter((entry) => entry.isFile() && entry.name.endsWith(".json"))
21
+ .map((entry) => entry.name.replace(/\.json$/i, ""))
22
+ .sort((a, b) => a.localeCompare(b, undefined, { sensitivity: "base" }));
23
+ }
24
+ async getCurrentAccountName() {
25
+ const currentName = await this.readCurrentNameFile();
26
+ if (currentName)
27
+ return currentName;
28
+ if (!(await this.pathExists(paths_1.authPath)))
29
+ return null;
30
+ const stat = await promises_1.default.lstat(paths_1.authPath);
31
+ if (!stat.isSymbolicLink())
32
+ return null;
33
+ const rawTarget = await promises_1.default.readlink(paths_1.authPath);
34
+ const resolvedTarget = node_path_1.default.resolve(node_path_1.default.dirname(paths_1.authPath), rawTarget);
35
+ const accountsRoot = node_path_1.default.resolve(paths_1.accountsDir);
36
+ const relative = node_path_1.default.relative(accountsRoot, resolvedTarget);
37
+ if (relative.startsWith(".."))
38
+ return null;
39
+ const base = node_path_1.default.basename(resolvedTarget);
40
+ return base.replace(/\.json$/i, "");
41
+ }
42
+ async saveAccount(rawName) {
43
+ const name = this.normalizeAccountName(rawName);
44
+ await this.ensureAuthFileExists();
45
+ await this.ensureDir(paths_1.accountsDir);
46
+ const destination = this.accountFilePath(name);
47
+ await promises_1.default.copyFile(paths_1.authPath, destination);
48
+ await this.writeCurrentName(name);
49
+ return name;
50
+ }
51
+ async useAccount(rawName) {
52
+ const name = this.normalizeAccountName(rawName);
53
+ const source = this.accountFilePath(name);
54
+ if (!(await this.pathExists(source))) {
55
+ throw new errors_1.AccountNotFoundError(name);
56
+ }
57
+ await this.ensureDir(paths_1.accountsDir);
58
+ await this.ensureDir(paths_1.codexDir);
59
+ if (process.platform === "win32") {
60
+ await promises_1.default.copyFile(source, paths_1.authPath);
61
+ }
62
+ else {
63
+ await this.replaceSymlink(source, paths_1.authPath);
64
+ }
65
+ await this.writeCurrentName(name);
66
+ return name;
67
+ }
68
+ accountFilePath(name) {
69
+ return node_path_1.default.join(paths_1.accountsDir, `${name}.json`);
70
+ }
71
+ normalizeAccountName(rawName) {
72
+ if (typeof rawName !== "string") {
73
+ throw new errors_1.InvalidAccountNameError();
74
+ }
75
+ const trimmed = rawName.trim();
76
+ if (!trimmed.length) {
77
+ throw new errors_1.InvalidAccountNameError();
78
+ }
79
+ const withoutExtension = trimmed.replace(/\.json$/i, "");
80
+ if (!ACCOUNT_NAME_PATTERN.test(withoutExtension)) {
81
+ throw new errors_1.InvalidAccountNameError();
82
+ }
83
+ return withoutExtension;
84
+ }
85
+ async ensureAuthFileExists() {
86
+ if (!(await this.pathExists(paths_1.authPath))) {
87
+ throw new errors_1.AuthFileMissingError(paths_1.authPath);
88
+ }
89
+ }
90
+ async ensureDir(dirPath) {
91
+ await promises_1.default.mkdir(dirPath, { recursive: true });
92
+ }
93
+ async replaceSymlink(target, linkPath) {
94
+ await this.removeIfExists(linkPath);
95
+ const absoluteTarget = node_path_1.default.resolve(target);
96
+ await promises_1.default.symlink(absoluteTarget, linkPath);
97
+ }
98
+ async removeIfExists(target) {
99
+ try {
100
+ await promises_1.default.rm(target, { force: true });
101
+ }
102
+ catch (error) {
103
+ const err = error;
104
+ if (err.code !== "ENOENT") {
105
+ throw error;
106
+ }
107
+ }
108
+ }
109
+ async writeCurrentName(name) {
110
+ await this.ensureDir(paths_1.codexDir);
111
+ await promises_1.default.writeFile(paths_1.currentNamePath, `${name}\n`, "utf8");
112
+ }
113
+ async readCurrentNameFile() {
114
+ try {
115
+ const contents = await promises_1.default.readFile(paths_1.currentNamePath, "utf8");
116
+ const trimmed = contents.trim();
117
+ return trimmed.length ? trimmed : null;
118
+ }
119
+ catch (error) {
120
+ const err = error;
121
+ if (err.code === "ENOENT") {
122
+ return null;
123
+ }
124
+ throw error;
125
+ }
126
+ }
127
+ async pathExists(targetPath) {
128
+ try {
129
+ await promises_1.default.access(targetPath, node_fs_1.default.constants.F_OK);
130
+ return true;
131
+ }
132
+ catch {
133
+ return false;
134
+ }
135
+ }
136
+ }
137
+ exports.AccountService = AccountService;
@@ -0,0 +1,18 @@
1
+ export declare class CodexAuthError extends Error {
2
+ constructor(message: string);
3
+ }
4
+ export declare class AuthFileMissingError extends CodexAuthError {
5
+ constructor(targetPath: string);
6
+ }
7
+ export declare class AccountNotFoundError extends CodexAuthError {
8
+ constructor(accountName: string);
9
+ }
10
+ export declare class NoAccountsSavedError extends CodexAuthError {
11
+ constructor();
12
+ }
13
+ export declare class InvalidAccountNameError extends CodexAuthError {
14
+ constructor();
15
+ }
16
+ export declare class PromptCancelledError extends CodexAuthError {
17
+ constructor();
18
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PromptCancelledError = exports.InvalidAccountNameError = exports.NoAccountsSavedError = exports.AccountNotFoundError = exports.AuthFileMissingError = exports.CodexAuthError = void 0;
4
+ class CodexAuthError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = new.target.name;
8
+ }
9
+ }
10
+ exports.CodexAuthError = CodexAuthError;
11
+ class AuthFileMissingError extends CodexAuthError {
12
+ constructor(targetPath) {
13
+ super(`No Codex auth file found at ${targetPath}. ` +
14
+ `Log into Codex first so ~/.codex/auth.json exists.`);
15
+ }
16
+ }
17
+ exports.AuthFileMissingError = AuthFileMissingError;
18
+ class AccountNotFoundError extends CodexAuthError {
19
+ constructor(accountName) {
20
+ super(`No saved Codex account named "${accountName}" was found.`);
21
+ }
22
+ }
23
+ exports.AccountNotFoundError = AccountNotFoundError;
24
+ class NoAccountsSavedError extends CodexAuthError {
25
+ constructor() {
26
+ super(`No saved Codex accounts yet. Run "codex-auth save <name>" first.`);
27
+ }
28
+ }
29
+ exports.NoAccountsSavedError = NoAccountsSavedError;
30
+ class InvalidAccountNameError extends CodexAuthError {
31
+ constructor() {
32
+ super("Account names must include at least one non-space character and " +
33
+ "may contain letters, numbers, dashes, underscores, and dots.");
34
+ }
35
+ }
36
+ exports.InvalidAccountNameError = InvalidAccountNameError;
37
+ class PromptCancelledError extends CodexAuthError {
38
+ constructor() {
39
+ super("No account selected. The operation was cancelled.");
40
+ }
41
+ }
42
+ exports.PromptCancelledError = PromptCancelledError;
@@ -0,0 +1,4 @@
1
+ import { AccountService } from "./account-service";
2
+ export { AccountService } from "./account-service";
3
+ export { AccountNotFoundError, AuthFileMissingError, CodexAuthError, InvalidAccountNameError, NoAccountsSavedError, PromptCancelledError, } from "./errors";
4
+ export declare const accountService: AccountService;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.accountService = exports.PromptCancelledError = exports.NoAccountsSavedError = exports.InvalidAccountNameError = exports.CodexAuthError = exports.AuthFileMissingError = exports.AccountNotFoundError = exports.AccountService = void 0;
4
+ const account_service_1 = require("./account-service");
5
+ var account_service_2 = require("./account-service");
6
+ Object.defineProperty(exports, "AccountService", { enumerable: true, get: function () { return account_service_2.AccountService; } });
7
+ var errors_1 = require("./errors");
8
+ Object.defineProperty(exports, "AccountNotFoundError", { enumerable: true, get: function () { return errors_1.AccountNotFoundError; } });
9
+ Object.defineProperty(exports, "AuthFileMissingError", { enumerable: true, get: function () { return errors_1.AuthFileMissingError; } });
10
+ Object.defineProperty(exports, "CodexAuthError", { enumerable: true, get: function () { return errors_1.CodexAuthError; } });
11
+ Object.defineProperty(exports, "InvalidAccountNameError", { enumerable: true, get: function () { return errors_1.InvalidAccountNameError; } });
12
+ Object.defineProperty(exports, "NoAccountsSavedError", { enumerable: true, get: function () { return errors_1.NoAccountsSavedError; } });
13
+ Object.defineProperty(exports, "PromptCancelledError", { enumerable: true, get: function () { return errors_1.PromptCancelledError; } });
14
+ exports.accountService = new account_service_1.AccountService();
@@ -0,0 +1,6 @@
1
+ import { Command } from "@oclif/core";
2
+ export declare abstract class BaseCommand extends Command {
3
+ protected readonly accounts: import("./accounts").AccountService;
4
+ protected runSafe(action: () => Promise<void>): Promise<void>;
5
+ private handleError;
6
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseCommand = void 0;
4
+ const core_1 = require("@oclif/core");
5
+ const accounts_1 = require("./accounts");
6
+ class BaseCommand extends core_1.Command {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.accounts = accounts_1.accountService;
10
+ }
11
+ async runSafe(action) {
12
+ try {
13
+ await action();
14
+ }
15
+ catch (error) {
16
+ this.handleError(error);
17
+ }
18
+ }
19
+ handleError(error) {
20
+ if (error instanceof accounts_1.CodexAuthError) {
21
+ this.error(error.message);
22
+ }
23
+ throw error;
24
+ }
25
+ }
26
+ exports.BaseCommand = BaseCommand;
@@ -0,0 +1,4 @@
1
+ export declare const codexDir: string;
2
+ export declare const accountsDir: string;
3
+ export declare const authPath: string;
4
+ export declare const currentNamePath: string;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.currentNamePath = exports.authPath = exports.accountsDir = exports.codexDir = void 0;
7
+ const node_os_1 = __importDefault(require("node:os"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ exports.codexDir = node_path_1.default.join(node_os_1.default.homedir(), ".codex");
10
+ exports.accountsDir = node_path_1.default.join(exports.codexDir, "accounts");
11
+ exports.authPath = node_path_1.default.join(exports.codexDir, "auth.json");
12
+ exports.currentNamePath = node_path_1.default.join(exports.codexDir, "current");
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@imdeadpool/codex-account-switcher",
3
+ "version": "0.1.5",
4
+ "description": "A command-line tool that lets you manage and switch between multiple Codex accounts instantly, no more constant logins and logouts.",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "codex-auth": "dist/index.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "scripts": {
12
+ "build": "tsc -p tsconfig.json",
13
+ "prepublishOnly": "npm run build"
14
+ },
15
+ "engines": {
16
+ "node": ">=18"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "keywords": [
24
+ "codex",
25
+ "cli",
26
+ "auth",
27
+ "accounts",
28
+ "switch",
29
+ "tokens"
30
+ ],
31
+ "preferGlobal": true,
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/Sls0n/codex-account-switcher.git"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/Sls0n/codex-account-switcher/issues"
38
+ },
39
+ "homepage": "https://github.com/Sls0n/codex-account-switcher#readme",
40
+ "author": "Sls0n",
41
+ "dependencies": {
42
+ "@oclif/core": "^3.0.0",
43
+ "prompts": "^2.4.2",
44
+ "tslib": "^2.8.1"
45
+ },
46
+ "devDependencies": {
47
+ "@types/prompts": "^2.4.9",
48
+ "typescript": "^5.6.3"
49
+ },
50
+ "oclif": {
51
+ "bin": "codex-auth",
52
+ "commands": "./dist/commands"
53
+ }
54
+ }