claudish 1.3.0 → 1.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.
Files changed (3) hide show
  1. package/README.md +20 -16
  2. package/dist/index.js +68 -20
  3. package/package.json +1 -2
package/README.md CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  - ✅ **Cross-platform** - Works with both Node.js and Bun (v1.3.0+)
10
10
  - ✅ **Universal compatibility** - Use with `npx` or `bunx` - no installation required
11
+ - ✅ **Interactive setup** - Prompts for API key and model if not provided (zero config!)
11
12
  - ✅ **Monitor mode** - Proxy to real Anthropic API and log all traffic (for debugging)
12
13
  - ✅ **Protocol compliance** - 1:1 compatibility with Claude Code communication protocol
13
14
  - ✅ **Snapshot testing** - Comprehensive test suite with 13/13 passing tests
@@ -65,32 +66,33 @@ bun link # or: npm link
65
66
 
66
67
  ## Quick Start
67
68
 
68
- ### 1. Set up environment
69
+ ### Option 1: Interactive Mode (Easiest)
69
70
 
70
71
  ```bash
71
- # Copy example env file
72
- cp .env.example .env
72
+ # Just run it - will prompt for API key and model
73
+ claudish
73
74
 
74
- # Add your OpenRouter API key
75
- export OPENROUTER_API_KEY=sk-or-v1-...
76
-
77
- # Recommended: Set placeholder to avoid Claude Code's API key prompt
78
- export ANTHROPIC_API_KEY=sk-ant-api03-placeholder
75
+ # Enter your OpenRouter API key when prompted
76
+ # Select a model from the list
77
+ # Start coding!
79
78
  ```
80
79
 
81
- ### 2. Run claudish
80
+ ### Option 2: With Environment Variables
82
81
 
83
82
  ```bash
84
- # Basic usage (auto-approve enabled by default)
83
+ # Set up environment
84
+ export OPENROUTER_API_KEY=sk-or-v1-...
85
+ export ANTHROPIC_API_KEY=sk-ant-api03-placeholder
86
+
87
+ # Run with specific task
85
88
  claudish "implement user authentication"
86
89
 
87
- # Use specific model
90
+ # Or with specific model
88
91
  claudish --model openai/gpt-5-codex "add tests"
89
-
90
- # Fully autonomous mode (auto-approve + dangerous)
91
- claudish --dangerous "refactor codebase"
92
92
  ```
93
93
 
94
+ **Note:** In interactive mode, if `OPENROUTER_API_KEY` is not set, you'll be prompted to enter it. This makes first-time usage super simple!
95
+
94
96
  ## Usage
95
97
 
96
98
  ### Basic Syntax
@@ -119,13 +121,15 @@ claudish [OPTIONS] <claude-args...>
119
121
 
120
122
  | Variable | Description | Required |
121
123
  |----------|-------------|----------|
122
- | `OPENROUTER_API_KEY` | Your OpenRouter API key | Yes |
124
+ | `OPENROUTER_API_KEY` | Your OpenRouter API key | **Optional in interactive mode** (will prompt if not set)<br>✅ **Required in non-interactive mode** |
123
125
  | `ANTHROPIC_API_KEY` | Placeholder to prevent Claude Code dialog (not used for auth) | ✅ **Required** |
124
126
  | `CLAUDISH_MODEL` | Default model to use | ❌ No |
125
127
  | `CLAUDISH_PORT` | Default proxy port | ❌ No |
126
128
  | `CLAUDISH_ACTIVE_MODEL_NAME` | Automatically set by claudish to show active model in status line (read-only) | ❌ No |
127
129
 
128
- **Important:** You MUST set `ANTHROPIC_API_KEY=sk-ant-api03-placeholder` (or any value). Without it, Claude Code will show a dialog, and if you select "No", it will bypass the proxy and use real Anthropic API. Claudish now enforces this requirement.
130
+ **Important Notes:**
131
+ - **NEW in v1.3.0:** In interactive mode, if `OPENROUTER_API_KEY` is not set, you'll be prompted to enter it
132
+ - You MUST set `ANTHROPIC_API_KEY=sk-ant-api03-placeholder` (or any value). Without it, Claude Code will show a dialog
129
133
 
130
134
  ## Available Models
131
135
 
package/dist/index.js CHANGED
@@ -299,6 +299,9 @@ function parseArgs(args) {
299
299
  }
300
300
  i++;
301
301
  }
302
+ if ((!config.claudeArgs || config.claudeArgs.length === 0) && !config.stdin) {
303
+ config.interactive = true;
304
+ }
302
305
  if (config.monitor) {
303
306
  if (process.env.ANTHROPIC_API_KEY && process.env.ANTHROPIC_API_KEY.includes("placeholder")) {
304
307
  delete process.env.ANTHROPIC_API_KEY;
@@ -314,27 +317,19 @@ function parseArgs(args) {
314
317
  } else {
315
318
  const apiKey = process.env[ENV.OPENROUTER_API_KEY];
316
319
  if (!apiKey) {
317
- console.error("Error: OPENROUTER_API_KEY environment variable is required");
318
- console.error("Get your API key from: https://openrouter.ai/keys");
319
- process.exit(1);
320
- }
321
- config.openrouterApiKey = apiKey;
322
- if (!process.env.ANTHROPIC_API_KEY) {
323
- console.error(`
324
- Error: ANTHROPIC_API_KEY is not set`);
325
- console.error("This placeholder key is required to prevent Claude Code from prompting.");
326
- console.error("");
327
- console.error("Set it now:");
328
- console.error(" export ANTHROPIC_API_KEY='sk-ant-api03-placeholder'");
329
- console.error("");
330
- console.error("Or add it to your shell profile (~/.zshrc or ~/.bashrc) to set permanently.");
331
- console.error("");
332
- console.error("Note: This key is NOT used for auth - claudish uses OPENROUTER_API_KEY");
333
- process.exit(1);
320
+ if (!config.interactive) {
321
+ console.error("Error: OPENROUTER_API_KEY environment variable is required");
322
+ console.error("Get your API key from: https://openrouter.ai/keys");
323
+ console.error("");
324
+ console.error("Set it now:");
325
+ console.error(" export OPENROUTER_API_KEY='sk-or-v1-...'");
326
+ process.exit(1);
327
+ }
328
+ config.openrouterApiKey = undefined;
329
+ } else {
330
+ config.openrouterApiKey = apiKey;
334
331
  }
335
- }
336
- if (!config.claudeArgs || config.claudeArgs.length === 0) {
337
- config.interactive = true;
332
+ config.anthropicApiKey = process.env.ANTHROPIC_API_KEY;
338
333
  }
339
334
  if (config.quiet === undefined) {
340
335
  config.quiet = !config.interactive;
@@ -456,6 +451,55 @@ Available OpenRouter Models (in priority order):
456
451
 
457
452
  // src/simple-selector.ts
458
453
  import { createInterface } from "readline";
454
+ async function promptForApiKey() {
455
+ return new Promise((resolve) => {
456
+ console.log(`
457
+ \x1B[1m\x1B[36mOpenRouter API Key Required\x1B[0m
458
+ `);
459
+ console.log(`\x1B[2mGet your free API key from: https://openrouter.ai/keys\x1B[0m
460
+ `);
461
+ console.log("Enter your OpenRouter API key:");
462
+ console.log(`\x1B[2m(it will not be saved, only used for this session)\x1B[0m
463
+ `);
464
+ const rl = createInterface({
465
+ input: process.stdin,
466
+ output: process.stdout,
467
+ terminal: false
468
+ });
469
+ let apiKey = null;
470
+ rl.on("line", (input) => {
471
+ const trimmed = input.trim();
472
+ if (!trimmed) {
473
+ console.log("\x1B[31mError: API key cannot be empty\x1B[0m");
474
+ return;
475
+ }
476
+ if (!trimmed.startsWith("sk-or-v1-")) {
477
+ console.log("\x1B[33mWarning: OpenRouter API keys usually start with 'sk-or-v1-'\x1B[0m");
478
+ console.log("\x1B[2mContinuing anyway...\x1B[0m");
479
+ }
480
+ apiKey = trimmed;
481
+ rl.close();
482
+ });
483
+ rl.on("close", () => {
484
+ if (apiKey) {
485
+ process.stdin.pause();
486
+ process.stdin.removeAllListeners("data");
487
+ process.stdin.removeAllListeners("end");
488
+ process.stdin.removeAllListeners("error");
489
+ process.stdin.removeAllListeners("readable");
490
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
491
+ process.stdin.setRawMode(false);
492
+ }
493
+ setTimeout(() => {
494
+ resolve(apiKey);
495
+ }, 200);
496
+ } else {
497
+ console.error("\x1B[31mError: API key is required\x1B[0m");
498
+ process.exit(1);
499
+ }
500
+ });
501
+ });
502
+ }
459
503
  async function selectModelInteractively() {
460
504
  return new Promise((resolve) => {
461
505
  console.log(`
@@ -4113,6 +4157,10 @@ async function main() {
4113
4157
  console.error("Install it from: https://claude.com/claude-code");
4114
4158
  process.exit(1);
4115
4159
  }
4160
+ if (config.interactive && !config.monitor && !config.openrouterApiKey) {
4161
+ config.openrouterApiKey = await promptForApiKey();
4162
+ console.log("");
4163
+ }
4116
4164
  if (config.interactive && !config.monitor && !config.model) {
4117
4165
  config.model = await selectModelInteractively();
4118
4166
  console.log("");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "CLI tool to run Claude Code with any OpenRouter model (Grok, GPT-5, MiniMax, etc.) via local Anthropic API-compatible proxy",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,6 @@
31
31
  "devDependencies": {
32
32
  "@biomejs/biome": "^1.9.4",
33
33
  "@types/bun": "latest",
34
- "@types/react": "^19.2.2",
35
34
  "typescript": "^5.7.0"
36
35
  },
37
36
  "files": [