@john2026/cluadex 1.1.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 ADDED
@@ -0,0 +1,282 @@
1
+ # cluadex
2
+
3
+ <img width="1700" height="460" alt="github-header-banner (3)" src="https://github.com/user-attachments/assets/33a60056-a756-4030-8737-14076d69c3d4" />
4
+
5
+
6
+ cluadex is a fork of the Claude Code source that adds a full OpenAI-compatible provider shim, NVIDIA AI (NIM) support, a smart multi-provider router, a Telegram gateway, and local inference via Ollama and Atomic Chat. Every Claude Code tool works — bash, file ops, grep, glob, agents, MCP, tasks — powered by whatever model you choose.
7
+
8
+ **Author:** karen john
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install -g @john2026/cluadex
16
+ ```
17
+
18
+ ```bash
19
+ cluadex
20
+ ```
21
+
22
+ On first run, if no provider is configured, Claudex will prompt you to set one up via `/provider`. No Anthropic account required.
23
+
24
+ ---
25
+
26
+ ## Fastest Start
27
+
28
+ Pick a provider, set three env vars, run.
29
+
30
+ ### NVIDIA AI — free key, best models
31
+
32
+ ```bash
33
+ export CLAUDE_CODE_USE_NVIDIA=1
34
+ export NVIDIA_API_KEY=nvapi-your-key
35
+ export NVIDIA_MODEL=moonshotai/kimi-k2-instruct
36
+ cluadex
37
+ ```
38
+
39
+ Free key at [build.nvidia.com](https://build.nvidia.com/).
40
+
41
+ ### OpenAI
42
+
43
+ ```bash
44
+ export CLAUDE_CODE_USE_OPENAI=1
45
+ export OPENAI_API_KEY=sk-your-key
46
+ export OPENAI_MODEL=gpt-4o
47
+ cluadex
48
+ ```
49
+
50
+ ### Google Gemini — free key
51
+
52
+ ```bash
53
+ export CLAUDE_CODE_USE_GEMINI=1
54
+ export GEMINI_API_KEY=your-key
55
+ export GEMINI_MODEL=gemini-2.0-flash
56
+ cluadex
57
+ ```
58
+
59
+ Free key at [aistudio.google.com/apikey](https://aistudio.google.com/apikey).
60
+
61
+ ### Ollama — fully local, no key
62
+
63
+ ```bash
64
+ ollama pull llama3.1:8b
65
+ export CLAUDE_CODE_USE_OPENAI=1
66
+ export OPENAI_BASE_URL=http://localhost:11434/v1
67
+ export OPENAI_MODEL=llama3.1:8b
68
+ cluadex
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Guides
74
+
75
+ | Audience | Guide |
76
+ |---|---|
77
+ | New to terminals | [Non-Technical Setup](docs/non-technical-setup.md) |
78
+ | Windows | [Windows Quick Start](docs/quick-start-windows.md) |
79
+ | macOS / Linux | [macOS / Linux Quick Start](docs/quick-start-mac-linux.md) |
80
+ | Android (Termux) | [Android Install](ANDROID_INSTALL.md) |
81
+ | Source builds, profiles, diagnostics | [Advanced Setup](docs/advanced-setup.md) |
82
+ | Daily Ollama workflow | [Playbook](PLAYBOOK.md) |
83
+ | Telegram bot | [Telegram Gateway](telegram-gateway/README.md) |
84
+
85
+ ---
86
+
87
+ ## Supported Providers
88
+
89
+ | Provider | Env flag | Key var |
90
+ |---|---|---|
91
+ | NVIDIA AI (NIM) | `CLAUDE_CODE_USE_NVIDIA=1` | `NVIDIA_API_KEY` |
92
+ | OpenAI / any OpenAI-compatible | `CLAUDE_CODE_USE_OPENAI=1` | `OPENAI_API_KEY` |
93
+ | Google Gemini | `CLAUDE_CODE_USE_GEMINI=1` | `GEMINI_API_KEY` |
94
+ | GitHub Models | `CLAUDE_CODE_USE_GITHUB=1` | `GITHUB_TOKEN` |
95
+ | Amazon Bedrock | `CLAUDE_CODE_USE_BEDROCK=1` | AWS credentials |
96
+ | Google Vertex AI | `CLAUDE_CODE_USE_VERTEX=1` | GCP credentials |
97
+ | Microsoft Foundry | `CLAUDE_CODE_USE_FOUNDRY=1` | `ANTHROPIC_FOUNDRY_API_KEY` |
98
+ | Ollama (local) | `CLAUDE_CODE_USE_OPENAI=1` + localhost URL | none |
99
+ | Atomic Chat (Apple Silicon) | `CLAUDE_CODE_USE_OPENAI=1` + 127.0.0.1:1337 | none |
100
+ | Anthropic (default) | none | `ANTHROPIC_API_KEY` |
101
+
102
+ Any OpenAI-compatible endpoint works: DeepSeek, Groq, Mistral, Together AI, OpenRouter, LM Studio, Azure OpenAI, and more.
103
+
104
+ ---
105
+
106
+ ## NVIDIA AI Models
107
+
108
+ | Model | Best for |
109
+ |---|---|
110
+ | `moonshotai/kimi-k2-instruct` | Reasoning, coding (default) |
111
+ | `nvidia/llama-3.1-nemotron-ultra-253b-v1` | Flagship quality |
112
+ | `meta/llama-3.3-70b-instruct` | Balanced speed/quality |
113
+ | `meta/llama-3.1-8b-instruct` | Fast, lightweight |
114
+ | `deepseek-ai/deepseek-r1` | Deep reasoning |
115
+ | `qwen/qwen3-235b-a22b` | Large MoE |
116
+ | `mistralai/mistral-large-2-instruct` | Instruction following |
117
+
118
+ ---
119
+
120
+ ## Startup Themes
121
+
122
+ Set `CLAUDEX_THEME` to change the banner color scheme:
123
+
124
+ | Theme | Colors |
125
+ |---|---|
126
+ | `sunset` | warm orange → rust (default) |
127
+ | `ocean` | deep teal → electric cyan |
128
+ | `aurora` | green → violet |
129
+ | `neon` | hot pink → electric blue |
130
+ | `mono` | white → grey |
131
+
132
+ ```bash
133
+ export CLAUDEX_THEME=ocean
134
+ cluadex
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Profile Launcher
140
+
141
+ Save a provider profile once, launch with one command:
142
+
143
+ ```bash
144
+ # save a profile (also works via /provider inside the CLI)
145
+ bun run profile:init -- --provider nvidia --api-key nvapi-...
146
+ bun run profile:init -- --provider openai --api-key sk-...
147
+ bun run profile:init -- --provider ollama --model llama3.1:8b
148
+
149
+ # launch from saved profile
150
+ bun run dev:profile
151
+
152
+ # provider-specific launchers
153
+ bun run dev:nvidia
154
+ bun run dev:openai
155
+ bun run dev:ollama
156
+ bun run dev:gemini
157
+ bun run dev:codex
158
+ bun run dev:atomic-chat
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Smart Router
164
+
165
+ Benchmarks all configured providers on startup and routes each request to the fastest, cheapest, healthiest option:
166
+
167
+ ```bash
168
+ export ROUTER_MODE=smart
169
+ export ROUTER_STRATEGY=balanced # latency | cost | balanced
170
+ cluadex
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Telegram Gateway
176
+
177
+ Use Claudex through a Telegram bot. Each user gets an isolated session.
178
+
179
+ ```bash
180
+ # configure (one time)
181
+ cluadex telegram setup --token 123456:ABC --provider nvidia
182
+
183
+ # allow yourself
184
+ cluadex telegram permit 987654321
185
+
186
+ # start the gateway
187
+ cluadex telegram start
188
+ ```
189
+
190
+ Or manage from inside the CLI:
191
+
192
+ ```
193
+ /telegram setup --token 123456:ABC --provider nvidia
194
+ /telegram permit 987654321
195
+ /telegram status
196
+ ```
197
+
198
+ Full guide: [telegram-gateway/README.md](telegram-gateway/README.md)
199
+
200
+ ---
201
+
202
+ ## What Works
203
+
204
+ - All tools: Bash, FileRead, FileWrite, FileEdit, Glob, Grep, WebFetch, WebSearch, Agent, MCP, LSP, NotebookEdit, Tasks
205
+ - Real-time token streaming
206
+ - Multi-step tool chains
207
+ - Base64 and URL image inputs (vision models)
208
+ - Slash commands: /commit, /review, /compact, /diff, /doctor, /provider, /telegram, etc.
209
+ - Sub-agents via AgentTool
210
+ - Persistent memory
211
+
212
+ ## What's Different from Upstream
213
+
214
+ - No Anthropic extended thinking (OpenAI models use different reasoning)
215
+ - No prompt caching (Anthropic-specific)
216
+ - No Anthropic beta headers
217
+ - Token output defaults to 32K — models that cap lower are handled gracefully
218
+ - First-run skips Anthropic login if a provider profile is saved
219
+
220
+ ---
221
+
222
+ ## Web Search
223
+
224
+ `WebSearch` is disabled by default for non-Anthropic providers. Set a [Firecrawl](https://firecrawl.dev) key to enable it:
225
+
226
+ ```bash
227
+ export FIRECRAWL_API_KEY=your-key
228
+ ```
229
+
230
+ Free tier includes 500 credits. With this set, `WebSearch` works for all providers and `WebFetch` handles JS-rendered pages.
231
+
232
+ ---
233
+
234
+ ## How the Shim Works
235
+
236
+ ```
237
+ Claude Code Tool System
238
+
239
+
240
+ Anthropic SDK interface (duck-typed)
241
+
242
+
243
+ openaiShim.ts ◄── translates formats
244
+
245
+
246
+ OpenAI Chat Completions API
247
+
248
+
249
+ Any compatible model
250
+ ```
251
+
252
+ ---
253
+
254
+ ## Model Quality Reference
255
+
256
+ | Model | Tool Calling | Code | Speed |
257
+ |---|---|---|---|
258
+ | GPT-4o | Excellent | Excellent | Fast |
259
+ | Kimi K2 (NVIDIA) | Excellent | Excellent | Fast |
260
+ | DeepSeek-V3 | Great | Great | Fast |
261
+ | Gemini 2.0 Flash | Great | Good | Very Fast |
262
+ | Llama 3.3 70B | Good | Good | Medium |
263
+ | Mistral Large | Good | Good | Fast |
264
+ | GPT-4o-mini | Good | Good | Very Fast |
265
+ | Qwen 2.5 72B | Good | Good | Medium |
266
+ | Models < 7B | Limited | Limited | Very Fast |
267
+
268
+ ---
269
+
270
+ ## VS Code Extension
271
+
272
+ Install the bundled extension from `vscode-extension/openclaude-vscode` for one-click terminal launch and the `Claudex Terminal Black` theme.
273
+
274
+ ---
275
+
276
+ ## Origin
277
+
278
+ Fork of the Claude Code source snapshot that became publicly accessible via an npm source map exposure on March 31, 2026. The original source is the property of Anthropic. This project is not affiliated with or endorsed by Anthropic.
279
+
280
+ ## License
281
+
282
+ Educational and research use. Original source subject to Anthropic's terms. Shim additions and new provider integrations are public domain.
package/bin/cluadex ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Claudex — Claude Code with any LLM
5
+ *
6
+ * If dist/cli.mjs exists (built), run that.
7
+ * Otherwise, tell the user to build first or use `bun run dev`.
8
+ */
9
+
10
+ import { existsSync } from 'fs'
11
+ import { join, dirname } from 'path'
12
+ import { fileURLToPath, pathToFileURL } from 'url'
13
+
14
+ const __dirname = dirname(fileURLToPath(import.meta.url))
15
+ const distPath = join(__dirname, '..', 'dist', 'cli.mjs')
16
+
17
+ if (existsSync(distPath)) {
18
+ await import(pathToFileURL(distPath).href)
19
+ } else {
20
+ console.error(`
21
+ cluadex: dist/cli.mjs not found.
22
+
23
+ Build first:
24
+ bun run build
25
+
26
+ Or run directly with Bun:
27
+ bun run dev
28
+
29
+ See README.md for setup instructions.
30
+ `)
31
+ process.exit(1)
32
+ }
@@ -0,0 +1,188 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * claudex telegram — manage the Claudex Telegram gateway
4
+ *
5
+ * Usage:
6
+ * claudex telegram setup --token <token> --provider <provider>
7
+ * claudex telegram permit <user-id>
8
+ * claudex telegram revoke <user-id>
9
+ * claudex telegram status
10
+ * claudex telegram start
11
+ */
12
+
13
+ import { existsSync } from 'node:fs'
14
+ import { homedir } from 'node:os'
15
+ import { join, dirname } from 'node:path'
16
+ import { fileURLToPath } from 'node:url'
17
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'
18
+ import { spawn } from 'node:child_process'
19
+
20
+ const __dirname = dirname(fileURLToPath(import.meta.url))
21
+ const CONFIG_DIR = join(homedir(), '.claudex')
22
+ const CONFIG_PATH = join(CONFIG_DIR, 'telegram.json')
23
+
24
+ function loadCfg() {
25
+ if (!existsSync(CONFIG_PATH)) return null
26
+ try { return JSON.parse(readFileSync(CONFIG_PATH, 'utf8')) } catch { return null }
27
+ }
28
+
29
+ function saveCfg(cfg) {
30
+ if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true })
31
+ writeFileSync(CONFIG_PATH, JSON.stringify(cfg, null, 2), { encoding: 'utf8', mode: 0o600 })
32
+ }
33
+
34
+ function parseArg(name) {
35
+ const args = process.argv.slice(3)
36
+ const eqForm = args.find(a => a.startsWith(`${name}=`))
37
+ if (eqForm) return eqForm.split('=').slice(1).join('=')
38
+ const idx = args.indexOf(name)
39
+ if (idx !== -1 && args[idx + 1] && !args[idx + 1].startsWith('--')) return args[idx + 1]
40
+ return null
41
+ }
42
+
43
+ const sub = process.argv[2]
44
+
45
+ switch (sub) {
46
+ case 'setup': {
47
+ const token = parseArg('--token')
48
+ const provider = parseArg('--provider') ?? 'openai'
49
+ const timeout = parseInt(parseArg('--timeout') ?? '300000', 10)
50
+ const maxSess = parseInt(parseArg('--max-sessions') ?? '10', 10)
51
+
52
+ if (!token) {
53
+ console.error('Usage: claudex telegram setup --token <bot-token> --provider <openai|nvidia|gemini|ollama>')
54
+ console.error('')
55
+ console.error('Get a bot token from @BotFather on Telegram.')
56
+ process.exit(1)
57
+ }
58
+
59
+ const cfg = {
60
+ botToken: token,
61
+ allowedIds: loadCfg()?.allowedIds ?? [],
62
+ provider,
63
+ idleTimeoutMs: timeout,
64
+ maxSessions: maxSess,
65
+ createdAt: loadCfg()?.createdAt ?? new Date().toISOString(),
66
+ updatedAt: new Date().toISOString(),
67
+ }
68
+ saveCfg(cfg)
69
+ console.log(`✅ Config saved: ${CONFIG_PATH}`)
70
+ console.log(` Provider: ${provider}`)
71
+ console.log(` Token: ${token.slice(0, 8)}…`)
72
+ console.log(` Timeout: ${Math.round(timeout / 60000)} min`)
73
+ console.log(` Sessions: max ${maxSess}`)
74
+ console.log('')
75
+ console.log('Next steps:')
76
+ console.log(' claudex telegram permit <your-telegram-id>')
77
+ console.log(' claudex telegram start')
78
+ console.log('')
79
+ console.log('Find your Telegram ID by messaging @userinfobot')
80
+ break
81
+ }
82
+
83
+ case 'permit': {
84
+ const idStr = process.argv[3]
85
+ const id = parseInt(idStr, 10)
86
+ if (!idStr || isNaN(id)) {
87
+ console.error('Usage: claudex telegram permit <telegram-user-id>')
88
+ console.error('')
89
+ console.error('Find your ID by messaging @userinfobot on Telegram.')
90
+ process.exit(1)
91
+ }
92
+ const cfg = loadCfg()
93
+ if (!cfg) {
94
+ console.error('❌ No config found. Run: claudex telegram setup --token <token>')
95
+ process.exit(1)
96
+ }
97
+ if (cfg.allowedIds.includes(id)) {
98
+ console.log(`ℹ️ User ${id} is already permitted.`)
99
+ } else {
100
+ cfg.allowedIds.push(id)
101
+ cfg.updatedAt = new Date().toISOString()
102
+ saveCfg(cfg)
103
+ console.log(`✅ Permitted user ${id}`)
104
+ console.log(` Total allowed: ${cfg.allowedIds.length}`)
105
+ }
106
+ break
107
+ }
108
+
109
+ case 'revoke': {
110
+ const idStr = process.argv[3]
111
+ const id = parseInt(idStr, 10)
112
+ if (!idStr || isNaN(id)) {
113
+ console.error('Usage: claudex telegram revoke <telegram-user-id>')
114
+ process.exit(1)
115
+ }
116
+ const cfg = loadCfg()
117
+ if (!cfg) { console.error('❌ No config found.'); process.exit(1) }
118
+ const before = cfg.allowedIds.length
119
+ cfg.allowedIds = cfg.allowedIds.filter(x => x !== id)
120
+ if (cfg.allowedIds.length < before) {
121
+ cfg.updatedAt = new Date().toISOString()
122
+ saveCfg(cfg)
123
+ console.log(`✅ Revoked user ${id}`)
124
+ } else {
125
+ console.log(`ℹ️ User ${id} was not in the allowed list.`)
126
+ }
127
+ break
128
+ }
129
+
130
+ case 'status': {
131
+ const cfg = loadCfg()
132
+ if (!cfg) {
133
+ console.log('❌ No Telegram gateway configured.')
134
+ console.log('')
135
+ console.log('Run: claudex telegram setup --token <token> --provider <provider>')
136
+ } else {
137
+ console.log('📡 Telegram Gateway Config')
138
+ console.log(` Config: ${CONFIG_PATH}`)
139
+ console.log(` Token: ${cfg.botToken.slice(0, 8)}…`)
140
+ console.log(` Provider: ${cfg.provider}`)
141
+ console.log(` Allowed: ${cfg.allowedIds.length === 0 ? 'open (no whitelist)' : cfg.allowedIds.join(', ')}`)
142
+ console.log(` Timeout: ${Math.round(cfg.idleTimeoutMs / 60000)} min`)
143
+ console.log(` Sessions: max ${cfg.maxSessions}`)
144
+ console.log(` Updated: ${cfg.updatedAt}`)
145
+ }
146
+ break
147
+ }
148
+
149
+ case 'start': {
150
+ const cfg = loadCfg()
151
+ if (!cfg) {
152
+ console.error('❌ No config found. Run: claudex telegram setup --token <token>')
153
+ process.exit(1)
154
+ }
155
+ console.log('🚀 Starting Claudex Telegram Gateway…')
156
+ console.log(` Provider: ${cfg.provider}`)
157
+ console.log(` Allowed: ${cfg.allowedIds.length === 0 ? 'open' : cfg.allowedIds.join(', ')}`)
158
+ console.log('')
159
+
160
+ const botPath = join(__dirname, '..', 'telegram-gateway', 'bot.ts')
161
+ const child = spawn('bun', ['run', botPath], {
162
+ stdio: 'inherit',
163
+ env: { ...process.env, TELEGRAM_BOT_TOKEN: cfg.botToken },
164
+ })
165
+ child.on('exit', code => process.exit(code ?? 0))
166
+ break
167
+ }
168
+
169
+ default: {
170
+ console.log('claudex telegram — Telegram gateway management')
171
+ console.log('')
172
+ console.log('Commands:')
173
+ console.log(' claudex telegram setup --token <token> --provider <provider>')
174
+ console.log(' configure the gateway')
175
+ console.log(' claudex telegram permit <id> allow a Telegram user ID')
176
+ console.log(' claudex telegram revoke <id> remove a Telegram user ID')
177
+ console.log(' claudex telegram status show current config')
178
+ console.log(' claudex telegram start start the gateway')
179
+ console.log('')
180
+ console.log('Providers: openai, nvidia, gemini, ollama, codex')
181
+ console.log('')
182
+ console.log('Example:')
183
+ console.log(' claudex telegram setup --token 123456:ABC --provider nvidia')
184
+ console.log(' claudex telegram permit 987654321')
185
+ console.log(' claudex telegram start')
186
+ break
187
+ }
188
+ }
@@ -0,0 +1,7 @@
1
+ import { join } from 'path'
2
+ import { pathToFileURL } from 'url'
3
+
4
+ export function getDistImportSpecifier(baseDir) {
5
+ const distPath = join(baseDir, '..', 'dist', 'cli.mjs')
6
+ return pathToFileURL(distPath).href
7
+ }
@@ -0,0 +1,13 @@
1
+ import assert from 'node:assert/strict'
2
+ import test from 'node:test'
3
+
4
+ import { getDistImportSpecifier } from './import-specifier.mjs'
5
+
6
+ test('builds a file URL import specifier for dist/cli.mjs', () => {
7
+ const specifier = getDistImportSpecifier('C:\\repo\\bin')
8
+
9
+ assert.equal(
10
+ specifier,
11
+ 'file:///C:/repo/dist/cli.mjs',
12
+ )
13
+ })