codemaxxing 0.1.4 → 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.
@@ -13,4 +13,4 @@
13
13
  * codemaxxing auth copilot — GitHub Copilot device flow
14
14
  * codemaxxing auth api-key <name> <key> — Save API key directly
15
15
  */
16
- export {};
16
+ export declare function main(): Promise<void>;
package/dist/auth-cli.js CHANGED
@@ -14,8 +14,8 @@
14
14
  * codemaxxing auth api-key <name> <key> — Save API key directly
15
15
  */
16
16
  import { PROVIDERS, getCredentials, removeCredential, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow, saveApiKey, detectAvailableAuth, } from "./utils/auth.js";
17
- const command = process.argv[2] ?? "login";
18
- async function main() {
17
+ export async function main() {
18
+ const command = process.argv[2] ?? "login";
19
19
  switch (command) {
20
20
  case "login": {
21
21
  console.log("\n💪 Codemaxxing Authentication\n");
@@ -259,7 +259,10 @@ Examples:
259
259
  process.exit(1);
260
260
  }
261
261
  }
262
- main().catch((err) => {
263
- console.error(`Error: ${err.message}`);
264
- process.exit(1);
265
- });
262
+ // Run main if this is the main module
263
+ if (typeof require !== "undefined" && require.main === module) {
264
+ main().catch((err) => {
265
+ console.error(`Error: ${err.message}`);
266
+ process.exit(1);
267
+ });
268
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Codemaxxing CLI entry point
4
+ * Routes subcommands (login, auth) to auth-cli, everything else to the TUI
5
+ */
6
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Codemaxxing CLI entry point
4
+ * Routes subcommands (login, auth) to auth-cli, everything else to the TUI
5
+ */
6
+ import { spawn } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
8
+ import { dirname, join } from "node:path";
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = dirname(__filename);
11
+ const subcmd = process.argv[2];
12
+ if (subcmd === "login" || subcmd === "auth") {
13
+ // Route to auth CLI
14
+ const authScript = join(__dirname, "auth-cli.js");
15
+ const args = subcmd === "login"
16
+ ? [authScript, "login", ...process.argv.slice(3)]
17
+ : [authScript, ...process.argv.slice(3)];
18
+ const child = spawn(process.execPath, args, {
19
+ stdio: "inherit",
20
+ cwd: process.cwd(),
21
+ });
22
+ child.on("exit", (code) => process.exit(code ?? 0));
23
+ }
24
+ else {
25
+ // Route to TUI
26
+ const tuiScript = join(__dirname, "index.js");
27
+ const child = spawn(process.execPath, [tuiScript, ...process.argv.slice(2)], {
28
+ stdio: "inherit",
29
+ cwd: process.cwd(),
30
+ });
31
+ child.on("exit", (code) => process.exit(code ?? 0));
32
+ }
package/dist/index.js CHANGED
@@ -10,7 +10,8 @@ import { listSessions, getSession, loadMessages } from "./utils/sessions.js";
10
10
  import { execSync } from "child_process";
11
11
  import { isGitRepo, getBranch, getStatus, getDiff, undoLastCommit } from "./utils/git.js";
12
12
  import { getTheme, listThemes, THEMES, DEFAULT_THEME } from "./themes.js";
13
- const VERSION = "0.1.0";
13
+ import { PROVIDERS, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow } from "./utils/auth.js";
14
+ const VERSION = "0.1.5";
14
15
  // ── Helpers ──
15
16
  function formatTimeAgo(date) {
16
17
  const secs = Math.floor((Date.now() - date.getTime()) / 1000);
@@ -29,6 +30,7 @@ function formatTimeAgo(date) {
29
30
  const SLASH_COMMANDS = [
30
31
  { cmd: "/help", desc: "show commands" },
31
32
  { cmd: "/login", desc: "set up authentication" },
33
+ { cmd: "/login", desc: "set up authentication" },
32
34
  { cmd: "/map", desc: "show repository map" },
33
35
  { cmd: "/reset", desc: "clear conversation" },
34
36
  { cmd: "/context", desc: "show message count" },
@@ -105,6 +107,8 @@ function App() {
105
107
  const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
106
108
  const [themePicker, setThemePicker] = useState(false);
107
109
  const [themePickerIndex, setThemePickerIndex] = useState(0);
110
+ const [loginPicker, setLoginPicker] = useState(false);
111
+ const [loginPickerIndex, setLoginPickerIndex] = useState(0);
108
112
  const [approval, setApproval] = useState(null);
109
113
  // Listen for paste events from stdin interceptor
110
114
  useEffect(() => {
@@ -277,25 +281,8 @@ function App() {
277
281
  return;
278
282
  }
279
283
  if (trimmed === "/login" || trimmed === "/auth") {
280
- addMsg("info", [
281
- "💪 Authentication Setup",
282
- "",
283
- "Run 'codemaxxing login' in a new terminal to set up:",
284
- " • OpenRouter OAuth (browser login, 200+ models)",
285
- " • Anthropic via Claude Code (your Pro/Max subscription)",
286
- " • ChatGPT via Codex CLI (your Plus/Pro subscription)",
287
- " • Qwen CLI (your Qwen access)",
288
- " • GitHub Copilot (device flow)",
289
- " • Manual API keys for any provider",
290
- "",
291
- "Commands:",
292
- " codemaxxing login — interactive setup",
293
- " codemaxxing auth list — see saved credentials",
294
- " codemaxxing auth openrouter — OpenRouter OAuth",
295
- " codemaxxing auth anthropic — Anthropic subscription",
296
- " codemaxxing auth openai — ChatGPT subscription",
297
- " codemaxxing auth copilot — GitHub Copilot",
298
- ].join("\n"));
284
+ setLoginPicker(true);
285
+ setLoginPickerIndex(0);
299
286
  return;
300
287
  }
301
288
  if (trimmed === "/help") {
@@ -511,6 +498,92 @@ function App() {
511
498
  return;
512
499
  }
513
500
  }
501
+ // Login picker navigation
502
+ if (loginPicker) {
503
+ const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
504
+ if (key.upArrow) {
505
+ setLoginPickerIndex((prev) => (prev - 1 + loginProviders.length) % loginProviders.length);
506
+ return;
507
+ }
508
+ if (key.downArrow) {
509
+ setLoginPickerIndex((prev) => (prev + 1) % loginProviders.length);
510
+ return;
511
+ }
512
+ if (key.return) {
513
+ const selected = loginProviders[loginPickerIndex];
514
+ setLoginPicker(false);
515
+ if (selected.id === "openrouter") {
516
+ addMsg("info", "Starting OpenRouter OAuth — opening browser...");
517
+ setLoading(true);
518
+ setSpinnerMsg("Waiting for authorization...");
519
+ openRouterOAuth((msg) => addMsg("info", msg))
520
+ .then((cred) => {
521
+ addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
522
+ addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
523
+ setLoading(false);
524
+ })
525
+ .catch((err) => {
526
+ addMsg("error", `OAuth failed: ${err.message}`);
527
+ setLoading(false);
528
+ });
529
+ }
530
+ else if (selected.id === "anthropic") {
531
+ addMsg("info", "Starting Anthropic setup-token flow...");
532
+ setLoading(true);
533
+ setSpinnerMsg("Waiting for Claude Code auth...");
534
+ anthropicSetupToken((msg) => addMsg("info", msg))
535
+ .then((cred) => {
536
+ addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
537
+ setLoading(false);
538
+ })
539
+ .catch((err) => {
540
+ addMsg("error", `Anthropic auth failed: ${err.message}`);
541
+ setLoading(false);
542
+ });
543
+ }
544
+ else if (selected.id === "openai") {
545
+ const imported = importCodexToken((msg) => addMsg("info", msg));
546
+ if (imported) {
547
+ addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
548
+ }
549
+ else {
550
+ addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
551
+ }
552
+ }
553
+ else if (selected.id === "qwen") {
554
+ const imported = importQwenToken((msg) => addMsg("info", msg));
555
+ if (imported) {
556
+ addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
557
+ }
558
+ else {
559
+ addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
560
+ }
561
+ }
562
+ else if (selected.id === "copilot") {
563
+ addMsg("info", "Starting GitHub Copilot device flow...");
564
+ setLoading(true);
565
+ setSpinnerMsg("Waiting for GitHub authorization...");
566
+ copilotDeviceFlow((msg) => addMsg("info", msg))
567
+ .then(() => {
568
+ addMsg("info", `✅ GitHub Copilot authenticated!`);
569
+ setLoading(false);
570
+ })
571
+ .catch((err) => {
572
+ addMsg("error", `Copilot auth failed: ${err.message}`);
573
+ setLoading(false);
574
+ });
575
+ }
576
+ else {
577
+ addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
578
+ }
579
+ return;
580
+ }
581
+ if (key.escape) {
582
+ setLoginPicker(false);
583
+ return;
584
+ }
585
+ return;
586
+ }
514
587
  // Theme picker navigation
515
588
  if (themePicker) {
516
589
  const themeKeys = listThemes();
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "codemaxxing",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Open-source terminal coding agent. Connect any LLM. Max your code.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "codemaxxing": "./dist/index.js",
7
+ "codemaxxing": "./dist/cli.js",
8
8
  "codemaxxing-auth": "./dist/auth-cli.js"
9
9
  },
10
10
  "type": "module",
package/src/auth-cli.ts CHANGED
@@ -28,9 +28,9 @@ import {
28
28
  detectAvailableAuth,
29
29
  } from "./utils/auth.js";
30
30
 
31
- const command = process.argv[2] ?? "login";
31
+ export async function main() {
32
+ const command = process.argv[2] ?? "login";
32
33
 
33
- async function main() {
34
34
  switch (command) {
35
35
  case "login": {
36
36
  console.log("\n💪 Codemaxxing Authentication\n");
@@ -280,7 +280,10 @@ Examples:
280
280
  }
281
281
  }
282
282
 
283
- main().catch((err) => {
284
- console.error(`Error: ${err.message}`);
285
- process.exit(1);
286
- });
283
+ // Run main if this is the main module
284
+ if (typeof require !== "undefined" && require.main === module) {
285
+ main().catch((err) => {
286
+ console.error(`Error: ${err.message}`);
287
+ process.exit(1);
288
+ });
289
+ }
package/src/cli.ts ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Codemaxxing CLI entry point
5
+ * Routes subcommands (login, auth) to auth-cli, everything else to the TUI
6
+ */
7
+
8
+ import { spawn } from "node:child_process";
9
+ import { fileURLToPath } from "node:url";
10
+ import { dirname, join } from "node:path";
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = dirname(__filename);
14
+
15
+ const subcmd = process.argv[2];
16
+
17
+ if (subcmd === "login" || subcmd === "auth") {
18
+ // Route to auth CLI
19
+ const authScript = join(__dirname, "auth-cli.js");
20
+ const args = subcmd === "login"
21
+ ? [authScript, "login", ...process.argv.slice(3)]
22
+ : [authScript, ...process.argv.slice(3)];
23
+
24
+ const child = spawn(process.execPath, args, {
25
+ stdio: "inherit",
26
+ cwd: process.cwd(),
27
+ });
28
+
29
+ child.on("exit", (code) => process.exit(code ?? 0));
30
+ } else {
31
+ // Route to TUI
32
+ const tuiScript = join(__dirname, "index.js");
33
+ const child = spawn(process.execPath, [tuiScript, ...process.argv.slice(2)], {
34
+ stdio: "inherit",
35
+ cwd: process.cwd(),
36
+ });
37
+
38
+ child.on("exit", (code) => process.exit(code ?? 0));
39
+ }
package/src/index.tsx CHANGED
@@ -10,8 +10,9 @@ import { listSessions, getSession, loadMessages } from "./utils/sessions.js";
10
10
  import { execSync } from "child_process";
11
11
  import { isGitRepo, getBranch, getStatus, getDiff, undoLastCommit } from "./utils/git.js";
12
12
  import { getTheme, listThemes, THEMES, DEFAULT_THEME, type Theme } from "./themes.js";
13
+ import { PROVIDERS, getCredentials, openRouterOAuth, anthropicSetupToken, importCodexToken, importQwenToken, copilotDeviceFlow, saveApiKey } from "./utils/auth.js";
13
14
 
14
- const VERSION = "0.1.0";
15
+ const VERSION = "0.1.5";
15
16
 
16
17
  // ── Helpers ──
17
18
  function formatTimeAgo(date: Date): string {
@@ -29,6 +30,7 @@ function formatTimeAgo(date: Date): string {
29
30
  const SLASH_COMMANDS = [
30
31
  { cmd: "/help", desc: "show commands" },
31
32
  { cmd: "/login", desc: "set up authentication" },
33
+ { cmd: "/login", desc: "set up authentication" },
32
34
  { cmd: "/map", desc: "show repository map" },
33
35
  { cmd: "/reset", desc: "clear conversation" },
34
36
  { cmd: "/context", desc: "show message count" },
@@ -134,6 +136,8 @@ function App() {
134
136
  const [sessionPickerIndex, setSessionPickerIndex] = useState(0);
135
137
  const [themePicker, setThemePicker] = useState(false);
136
138
  const [themePickerIndex, setThemePickerIndex] = useState(0);
139
+ const [loginPicker, setLoginPicker] = useState(false);
140
+ const [loginPickerIndex, setLoginPickerIndex] = useState(0);
137
141
  const [approval, setApproval] = useState<{
138
142
  tool: string;
139
143
  args: Record<string, unknown>;
@@ -325,25 +329,8 @@ function App() {
325
329
  return;
326
330
  }
327
331
  if (trimmed === "/login" || trimmed === "/auth") {
328
- addMsg("info", [
329
- "💪 Authentication Setup",
330
- "",
331
- "Run 'codemaxxing login' in a new terminal to set up:",
332
- " • OpenRouter OAuth (browser login, 200+ models)",
333
- " • Anthropic via Claude Code (your Pro/Max subscription)",
334
- " • ChatGPT via Codex CLI (your Plus/Pro subscription)",
335
- " • Qwen CLI (your Qwen access)",
336
- " • GitHub Copilot (device flow)",
337
- " • Manual API keys for any provider",
338
- "",
339
- "Commands:",
340
- " codemaxxing login — interactive setup",
341
- " codemaxxing auth list — see saved credentials",
342
- " codemaxxing auth openrouter — OpenRouter OAuth",
343
- " codemaxxing auth anthropic — Anthropic subscription",
344
- " codemaxxing auth openai — ChatGPT subscription",
345
- " codemaxxing auth copilot — GitHub Copilot",
346
- ].join("\n"));
332
+ setLoginPicker(true);
333
+ setLoginPickerIndex(0);
347
334
  return;
348
335
  }
349
336
  if (trimmed === "/help") {
@@ -557,6 +544,87 @@ function App() {
557
544
  }
558
545
  }
559
546
 
547
+ // Login picker navigation
548
+ if (loginPicker) {
549
+ const loginProviders = PROVIDERS.filter((p) => p.id !== "local");
550
+ if (key.upArrow) {
551
+ setLoginPickerIndex((prev: number) => (prev - 1 + loginProviders.length) % loginProviders.length);
552
+ return;
553
+ }
554
+ if (key.downArrow) {
555
+ setLoginPickerIndex((prev: number) => (prev + 1) % loginProviders.length);
556
+ return;
557
+ }
558
+ if (key.return) {
559
+ const selected = loginProviders[loginPickerIndex];
560
+ setLoginPicker(false);
561
+
562
+ if (selected.id === "openrouter") {
563
+ addMsg("info", "Starting OpenRouter OAuth — opening browser...");
564
+ setLoading(true);
565
+ setSpinnerMsg("Waiting for authorization...");
566
+ openRouterOAuth((msg: string) => addMsg("info", msg))
567
+ .then((cred) => {
568
+ addMsg("info", `✅ OpenRouter authenticated! You now have access to 200+ models.`);
569
+ addMsg("info", `Switch with: /model anthropic/claude-sonnet-4`);
570
+ setLoading(false);
571
+ })
572
+ .catch((err: any) => {
573
+ addMsg("error", `OAuth failed: ${err.message}`);
574
+ setLoading(false);
575
+ });
576
+ } else if (selected.id === "anthropic") {
577
+ addMsg("info", "Starting Anthropic setup-token flow...");
578
+ setLoading(true);
579
+ setSpinnerMsg("Waiting for Claude Code auth...");
580
+ anthropicSetupToken((msg: string) => addMsg("info", msg))
581
+ .then((cred) => {
582
+ addMsg("info", `✅ Anthropic authenticated! (${cred.label})`);
583
+ setLoading(false);
584
+ })
585
+ .catch((err: any) => {
586
+ addMsg("error", `Anthropic auth failed: ${err.message}`);
587
+ setLoading(false);
588
+ });
589
+ } else if (selected.id === "openai") {
590
+ const imported = importCodexToken((msg: string) => addMsg("info", msg));
591
+ if (imported) {
592
+ addMsg("info", `✅ Imported Codex credentials! (${imported.label})`);
593
+ } else {
594
+ addMsg("info", "No Codex CLI found. Run: codemaxxing auth api-key openai <your-key>");
595
+ }
596
+ } else if (selected.id === "qwen") {
597
+ const imported = importQwenToken((msg: string) => addMsg("info", msg));
598
+ if (imported) {
599
+ addMsg("info", `✅ Imported Qwen credentials! (${imported.label})`);
600
+ } else {
601
+ addMsg("info", "No Qwen CLI found. Run: codemaxxing auth api-key qwen <your-key>");
602
+ }
603
+ } else if (selected.id === "copilot") {
604
+ addMsg("info", "Starting GitHub Copilot device flow...");
605
+ setLoading(true);
606
+ setSpinnerMsg("Waiting for GitHub authorization...");
607
+ copilotDeviceFlow((msg: string) => addMsg("info", msg))
608
+ .then(() => {
609
+ addMsg("info", `✅ GitHub Copilot authenticated!`);
610
+ setLoading(false);
611
+ })
612
+ .catch((err: any) => {
613
+ addMsg("error", `Copilot auth failed: ${err.message}`);
614
+ setLoading(false);
615
+ });
616
+ } else {
617
+ addMsg("info", `Run: codemaxxing auth api-key ${selected.id} <your-key>\n Get key at: ${selected.consoleUrl ?? selected.baseUrl}`);
618
+ }
619
+ return;
620
+ }
621
+ if (key.escape) {
622
+ setLoginPicker(false);
623
+ return;
624
+ }
625
+ return;
626
+ }
627
+
560
628
  // Theme picker navigation
561
629
  if (themePicker) {
562
630
  const themeKeys = listThemes();