@blockrun/cc 0.5.0 → 0.6.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/README.md CHANGED
@@ -33,8 +33,21 @@ Claude Code --> brcc (local proxy) --> BlockRun API --> Any model
33
33
 
34
34
  ## Quick Start
35
35
 
36
+ ### One-line install (Linux/macOS)
37
+
38
+ ```bash
39
+ curl -fsSL https://raw.githubusercontent.com/BlockRunAI/brcc/main/install.sh | bash
40
+ ```
41
+
42
+ Installs Node.js (if missing) + Claude Code + brcc + creates wallet.
43
+
44
+ ### Manual install
45
+
36
46
  ```bash
37
- # Install
47
+ # Prerequisites: Node.js 20+ and Claude Code
48
+ curl -fsSL https://claude.ai/install.sh | bash
49
+
50
+ # Install brcc (use sudo on Linux)
38
51
  npm install -g @blockrun/cc
39
52
 
40
53
  # Create a wallet (one time)
@@ -81,14 +94,21 @@ That's it. Claude Code opens with access to 40+ models, no rate limits.
81
94
 
82
95
  Creates a wallet and shows the address for funding.
83
96
 
97
+ ```bash
98
+ brcc setup # Default: Base chain
99
+ brcc setup base # Explicit Base (Coinbase L2)
100
+ brcc setup solana # Solana chain
101
+ ```
102
+
84
103
  ```
85
- $ brcc setup
104
+ $ brcc setup base
86
105
  Wallet created!
87
106
  Address: 0xCC8c44AD3dc2A58D841c3EB26131E49b22665EF8
88
107
  Send USDC on Base to this address to fund your account.
108
+ Chain: base — saved to ~/.blockrun/
89
109
  ```
90
110
 
91
- Your wallet is saved to `~/.blockrun/` and shared with all BlockRun tools.
111
+ Your wallet is saved to `~/.blockrun/` and shared with all BlockRun tools (Python SDK, TS SDK, ClawRouter).
92
112
 
93
113
  ### `brcc start`
94
114
 
@@ -107,9 +127,56 @@ Starting Claude Code...
107
127
 
108
128
  Options:
109
129
  ```bash
110
- brcc start # Start proxy + launch Claude Code
111
- brcc start --no-launch # Proxy only (for manual Claude Code setup)
112
- brcc start -p 9000 # Custom port
130
+ brcc start # Default model (Sonnet 4.6)
131
+ brcc start --model nvidia/gpt-oss-120b # Free model
132
+ brcc start --model openai/gpt-5.4 # GPT-5.4
133
+ brcc start --model deepseek/deepseek-chat # Budget option
134
+ brcc start --no-launch # Proxy only
135
+ brcc start -p 9000 # Custom port
136
+ ```
137
+
138
+ Inside Claude Code, use `/model` to switch between Sonnet, Opus, and Haiku — each maps to the BlockRun model you configured.
139
+
140
+ ### `brcc models`
141
+
142
+ List all available models with pricing.
143
+
144
+ ```
145
+ $ brcc models
146
+ Available Models
147
+
148
+ Free Models (no USDC needed)
149
+ ──────────────────────────────────────────────────────────────────────
150
+ nvidia/gpt-oss-120b
151
+ nvidia/gpt-oss-20b
152
+
153
+ Paid Models
154
+ ──────────────────────────────────────────────────────────────────────
155
+ Model Input Output
156
+ deepseek/deepseek-chat $0.28/M $0.42/M
157
+ anthropic/claude-haiku-4.5 $1.00/M $5.00/M
158
+ openai/gpt-5.4 $2.50/M $15.00/M
159
+ anthropic/claude-sonnet-4.6 $3.00/M $15.00/M
160
+ anthropic/claude-opus-4.6 $5.00/M $25.00/M
161
+ ...
162
+ ```
163
+
164
+ ### `brcc config`
165
+
166
+ Customize model mappings for Claude Code's `/model` picker.
167
+
168
+ ```bash
169
+ # Map Claude Code's "Haiku" to a cheap model
170
+ brcc config set haiku-model deepseek/deepseek-chat
171
+
172
+ # Map "Sonnet" to GPT-5.4
173
+ brcc config set sonnet-model openai/gpt-5.4
174
+
175
+ # Set default model
176
+ brcc config set default-model nvidia/gpt-oss-120b
177
+
178
+ # View all settings
179
+ brcc config list
113
180
  ```
114
181
 
115
182
  ### `brcc balance`
@@ -0,0 +1,9 @@
1
+ export interface BrccConfig {
2
+ 'default-model'?: string;
3
+ 'sonnet-model'?: string;
4
+ 'opus-model'?: string;
5
+ 'haiku-model'?: string;
6
+ 'smart-routing'?: string;
7
+ }
8
+ export declare function loadConfig(): BrccConfig;
9
+ export declare function configCommand(action: string, keyOrUndefined?: string, value?: string): void;
@@ -0,0 +1,92 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import chalk from 'chalk';
4
+ import { BLOCKRUN_DIR } from '../config.js';
5
+ const CONFIG_FILE = path.join(BLOCKRUN_DIR, 'brcc-config.json');
6
+ const VALID_KEYS = [
7
+ 'default-model',
8
+ 'sonnet-model',
9
+ 'opus-model',
10
+ 'haiku-model',
11
+ 'smart-routing',
12
+ ];
13
+ export function loadConfig() {
14
+ try {
15
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
16
+ return JSON.parse(content);
17
+ }
18
+ catch {
19
+ return {};
20
+ }
21
+ }
22
+ function saveConfig(config) {
23
+ fs.mkdirSync(BLOCKRUN_DIR, { recursive: true });
24
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n', {
25
+ mode: 0o600,
26
+ });
27
+ }
28
+ function isValidKey(key) {
29
+ return VALID_KEYS.includes(key);
30
+ }
31
+ export function configCommand(action, keyOrUndefined, value) {
32
+ if (action === 'list') {
33
+ const config = loadConfig();
34
+ const entries = Object.entries(config);
35
+ if (entries.length === 0) {
36
+ console.log(chalk.dim('No config set. Defaults will be used.'));
37
+ console.log(chalk.dim(`\nConfig file: ${CONFIG_FILE}`));
38
+ return;
39
+ }
40
+ console.log(chalk.bold('brcc config\n'));
41
+ for (const [k, v] of entries) {
42
+ console.log(` ${chalk.cyan(k)} = ${chalk.green(v)}`);
43
+ }
44
+ console.log(chalk.dim(`\nConfig file: ${CONFIG_FILE}`));
45
+ return;
46
+ }
47
+ if (action === 'get') {
48
+ if (!keyOrUndefined) {
49
+ console.log(chalk.red('Usage: brcc config get <key>'));
50
+ process.exit(1);
51
+ }
52
+ const config = loadConfig();
53
+ const val = config[keyOrUndefined];
54
+ if (val !== undefined) {
55
+ console.log(val);
56
+ }
57
+ else {
58
+ console.log(chalk.dim('(not set)'));
59
+ }
60
+ return;
61
+ }
62
+ if (action === 'set') {
63
+ if (!keyOrUndefined || value === undefined) {
64
+ console.log(chalk.red('Usage: brcc config set <key> <value>'));
65
+ process.exit(1);
66
+ }
67
+ if (!isValidKey(keyOrUndefined)) {
68
+ console.log(chalk.red(`Unknown config key: ${keyOrUndefined}`));
69
+ console.log(`Valid keys: ${VALID_KEYS.map((k) => chalk.cyan(k)).join(', ')}`);
70
+ process.exit(1);
71
+ }
72
+ const config = loadConfig();
73
+ config[keyOrUndefined] = value;
74
+ saveConfig(config);
75
+ console.log(`${chalk.cyan(keyOrUndefined)} = ${chalk.green(value)}`);
76
+ return;
77
+ }
78
+ if (action === 'unset') {
79
+ if (!keyOrUndefined) {
80
+ console.log(chalk.red('Usage: brcc config unset <key>'));
81
+ process.exit(1);
82
+ }
83
+ const config = loadConfig();
84
+ delete config[keyOrUndefined];
85
+ saveConfig(config);
86
+ console.log(chalk.dim(`Unset ${keyOrUndefined}`));
87
+ return;
88
+ }
89
+ console.log(chalk.red(`Unknown action: ${action}`));
90
+ console.log('Usage: brcc config <set|get|unset|list> [key] [value]');
91
+ process.exit(1);
92
+ }
@@ -3,6 +3,7 @@ import chalk from 'chalk';
3
3
  import { getOrCreateWallet, getOrCreateSolanaWallet } from '@blockrun/llm';
4
4
  import { createProxy } from '../proxy/server.js';
5
5
  import { loadChain, API_URLS, DEFAULT_PROXY_PORT } from '../config.js';
6
+ import { loadConfig } from './config.js';
6
7
  export async function startCommand(options) {
7
8
  const chain = loadChain();
8
9
  const apiUrl = API_URLS[chain];
@@ -57,6 +58,10 @@ function launchServer(server, port, shouldLaunch, model) {
57
58
  const cleanEnv = { ...process.env };
58
59
  delete cleanEnv.CLAUDE_ACCESS_TOKEN;
59
60
  delete cleanEnv.CLAUDE_OAUTH_TOKEN;
61
+ const config = loadConfig();
62
+ const sonnetModel = config['sonnet-model'] || 'anthropic/claude-sonnet-4.6';
63
+ const opusModel = config['opus-model'] || 'anthropic/claude-opus-4.6';
64
+ const haikuModel = config['haiku-model'] || 'anthropic/claude-haiku-4.5';
60
65
  const claudeArgs = [];
61
66
  if (model)
62
67
  claudeArgs.push('--model', model);
@@ -66,6 +71,10 @@ function launchServer(server, port, shouldLaunch, model) {
66
71
  ...cleanEnv,
67
72
  ANTHROPIC_BASE_URL: `http://localhost:${port}/api`,
68
73
  ANTHROPIC_API_KEY: 'sk-ant-api03-brcc-proxy-00000000000000000000000000000000000000000000-00000000000000',
74
+ ANTHROPIC_DEFAULT_SONNET_MODEL: sonnetModel,
75
+ ANTHROPIC_DEFAULT_OPUS_MODEL: opusModel,
76
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: haikuModel,
77
+ ...(model ? { ANTHROPIC_MODEL: model } : {}),
69
78
  },
70
79
  });
71
80
  claude.on('error', (err) => {
package/dist/index.js CHANGED
@@ -4,11 +4,13 @@ import { setupCommand } from './commands/setup.js';
4
4
  import { startCommand } from './commands/start.js';
5
5
  import { balanceCommand } from './commands/balance.js';
6
6
  import { modelsCommand } from './commands/models.js';
7
+ import { configCommand } from './commands/config.js';
7
8
  const program = new Command();
8
9
  program
9
10
  .name('brcc')
10
- .description('BlockRun Claude Code — run Claude Code with any model, pay with USDC')
11
- .version('0.1.0');
11
+ .description('BlockRun Claude Code — run Claude Code with any model, pay with USDC.\n\n' +
12
+ 'Use /model inside Claude Code to switch between models on the fly.')
13
+ .version('0.5.0');
12
14
  program
13
15
  .command('setup [chain]')
14
16
  .description('Create a new wallet for payments (base or solana)')
@@ -17,7 +19,7 @@ program
17
19
  .command('start')
18
20
  .description('Start proxy and launch Claude Code')
19
21
  .option('-p, --port <port>', 'Proxy port', '8402')
20
- .option('-m, --model <model>', 'Model to use (e.g. openai/gpt-5.4, nvidia/gpt-oss-120b)')
22
+ .option('-m, --model <model>', 'Default model (e.g. openai/gpt-5.4, anthropic/claude-sonnet-4.6)')
21
23
  .option('--no-launch', 'Start proxy only, do not launch Claude Code')
22
24
  .action(startCommand);
23
25
  program
@@ -28,4 +30,9 @@ program
28
30
  .command('balance')
29
31
  .description('Check wallet USDC balance')
30
32
  .action(balanceCommand);
33
+ program
34
+ .command('config <action> [key] [value]')
35
+ .description('Manage brcc config (set, get, unset, list)\n' +
36
+ 'Keys: default-model, sonnet-model, opus-model, haiku-model, smart-routing')
37
+ .action(configCommand);
31
38
  program.parse();
@@ -7,3 +7,10 @@ export interface ProxyOptions {
7
7
  modelOverride?: string;
8
8
  }
9
9
  export declare function createProxy(options: ProxyOptions): http.Server;
10
+ type RequestCategory = 'simple' | 'code' | 'default';
11
+ interface ClassifiedRequest {
12
+ category: RequestCategory;
13
+ suggestedModel?: string;
14
+ }
15
+ export declare function classifyRequest(body: string): ClassifiedRequest;
16
+ export {};
@@ -149,6 +149,38 @@ async function handleSolanaPayment(response, url, method, headers, body, private
149
149
  body: body || undefined,
150
150
  });
151
151
  }
152
+ export function classifyRequest(body) {
153
+ try {
154
+ const parsed = JSON.parse(body);
155
+ const messages = parsed.messages;
156
+ if (!Array.isArray(messages) || messages.length === 0) {
157
+ return { category: 'default' };
158
+ }
159
+ const lastMessage = messages[messages.length - 1];
160
+ let content = '';
161
+ if (typeof lastMessage.content === 'string') {
162
+ content = lastMessage.content;
163
+ }
164
+ else if (Array.isArray(lastMessage.content)) {
165
+ content = lastMessage.content
166
+ .filter((b) => b.type === 'text' && b.text)
167
+ .map((b) => b.text)
168
+ .join('\n');
169
+ }
170
+ if (content.includes('```') || content.includes('function ') ||
171
+ content.includes('class ') || content.includes('import ') ||
172
+ content.includes('def ') || content.includes('const ')) {
173
+ return { category: 'code' };
174
+ }
175
+ if (content.length < 100) {
176
+ return { category: 'simple' };
177
+ }
178
+ return { category: 'default' };
179
+ }
180
+ catch {
181
+ return { category: 'default' };
182
+ }
183
+ }
152
184
  // ======================================================================
153
185
  // Shared helpers
154
186
  // ======================================================================
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/cc",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Run Claude Code with any model — no rate limits, no account locks, no phone verification. Pay per use with USDC.",
5
5
  "type": "module",
6
6
  "bin": {