clew-code 0.2.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.
package/LICENSE.md ADDED
@@ -0,0 +1,71 @@
1
+ # License Notice
2
+
3
+ ## Nature of This Repository
4
+
5
+ This repository contains an unofficial, reverse-engineered rebuild of Anthropic's Claude Code CLI. The code has been reconstructed and extended for research, local development, and self-hosted use.
6
+
7
+ This repository is not an official Anthropic product. Anthropic has not authorized, endorsed, sponsored, or approved this project.
8
+
9
+ The upstream Claude Code product is proprietary software owned by Anthropic PBC. Anthropic retains all rights in its original software, services, models, APIs, trademarks, and related materials.
10
+
11
+ ## No Claim to Anthropic IP
12
+
13
+ The contributors to this repository do not claim ownership of Anthropic's original work.
14
+
15
+ This repository does not grant any license to Anthropic's proprietary source code, binaries, models, hosted services, trademarks, trade dress, or other protected materials.
16
+
17
+ Any use of Anthropic APIs, accounts, services, or names remains subject to Anthropic's applicable terms and policies.
18
+
19
+ ## Trademarks
20
+
21
+ "Anthropic", "Claude", "Claude Code", and related marks are trademarks or registered trademarks of their respective owners.
22
+
23
+ Any reference to those names in this repository is for identification and compatibility discussion only. This project must not be presented as an official Anthropic product, distribution, partner project, or supported implementation.
24
+
25
+ ## MIT License for Contributor Modifications
26
+
27
+ Only original modifications, extensions, patches, documentation, tooling, and other contributions authored by this repository's contributors are licensed under the MIT License, to the extent the contributors have the legal right to license them.
28
+
29
+ ```
30
+ MIT License
31
+
32
+ Copyright (c) 2026 Claude Code contributors
33
+
34
+ Permission is hereby granted, free of charge, to any person obtaining a copy
35
+ of the contributor-authored modifications and original additions in this
36
+ repository, to deal in those modifications without restriction, including
37
+ without limitation the rights to use, copy, modify, merge, publish,
38
+ distribute, sublicense, and/or sell copies of those modifications, subject to
39
+ the following conditions:
40
+
41
+ The above copyright notice and this permission notice shall be included in all
42
+ copies or substantial portions of the contributor-authored modifications.
43
+
44
+ THE CONTRIBUTOR-AUTHORED MODIFICATIONS ARE PROVIDED "AS IS", WITHOUT WARRANTY
45
+ OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
46
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
47
+ NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
48
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
49
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE CONTRIBUTOR-AUTHORED
50
+ MODIFICATIONS OR THE USE OR OTHER DEALINGS IN THOSE MODIFICATIONS.
51
+ ```
52
+
53
+ ## Excluded Materials
54
+
55
+ The MIT License above does not apply to any material owned by Anthropic or any third party, including proprietary source code, compiled binaries, service credentials, model access, API access, documentation copied from proprietary sources, trademarks, or other protected materials.
56
+
57
+ ## Distribution and Use
58
+
59
+ You are responsible for evaluating whether you may clone, modify, redistribute, publish, deploy, or use this repository in your jurisdiction and under any applicable contract, platform policy, or third-party license.
60
+
61
+ Public distribution, commercial use, hosted access, or packaging of this repository may carry legal risk if the repository contains or derives from proprietary material that you do not have permission to use.
62
+
63
+ ## Contributor Responsibility
64
+
65
+ Contributors must only submit material they have the right to contribute and license.
66
+
67
+ Do not submit proprietary code, leaked code, copied source, credentials, private keys, confidential documentation, or material that violates another party's rights.
68
+
69
+ ## No Legal Advice
70
+
71
+ This notice is provided for repository documentation purposes only. It is not legal advice. Consult qualified counsel before relying on this repository for redistribution, commercial use, public hosting, or production deployment.
package/README.md ADDED
@@ -0,0 +1,356 @@
1
+ <p align="center">
2
+ <img src="https://github.com/user-attachments/assets/3447b2ee-d405-4c7f-8510-f881b969bf3d" alt="Clew" width="480" />
3
+ </p>
4
+
5
+ <p align="center">
6
+ <strong>Language:</strong>
7
+ <a href="README.md"><strong>English</strong></a> ·
8
+ <a href="readme/README.zh.md">中文 (简体)</a> ·
9
+ <a href="readme/README.th.md">ไทย</a>
10
+ </p>
11
+
12
+ # Clew 🪽
13
+
14
+ Clew is an unofficial, research-oriented CLI for AI-assisted software development.
15
+
16
+ It is a source-built reconstruction and extension project designed for local development, debugging, self-hosted workflows, and provider choice.
17
+
18
+ This repository is not an official Anthropic product, distribution, partner project, or supported implementation.
19
+
20
+ > **Disclaimer:** Anthropic, Claude, and Claude Code are trademarks of their respective owners. This project is not affiliated with, endorsed by, sponsored by, or approved by Anthropic PBC. Anthropic's official Claude Code product is proprietary software. Read [LICENSE.md](LICENSE.md) before using, modifying, redistributing, or deploying this repository.
21
+
22
+ ## What This Project Provides
23
+
24
+ | Area | Description |
25
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
26
+ | Source-built CLI | A Bun/TypeScript terminal application that can be built, tested, inspected, and modified locally. |
27
+ | Multi-provider routing | Support for multiple AI providers through provider adapters and model selection commands. |
28
+ | Developer tooling | Commands for context inspection, code review, simplification, research, plugins, MCP, LSP, sessions, and background workflows. |
29
+ | Local extensibility | Support for plugins, hooks, skills, custom tools, scheduled tasks, and project-level configuration. |
30
+ | Research use | A transparent codebase for studying AI coding agent architecture, terminal UX, provider routing, and tool execution. |
31
+
32
+ ## Features
33
+
34
+ Clew runs directly in your terminal. It can inspect and edit local codebases, execute shell commands with permissions, switch model providers, and coordinate longer-running agent workflows.
35
+
36
+ Key features:
37
+
38
+ * **Multi-provider AI routing** — Supports Anthropic, OpenAI, Google Gemini, OpenRouter, Ollama, GitHub Copilot, and OpenAI-compatible endpoints.
39
+ * **Runtime model switching** — Switch models or providers during a session using `/model`.
40
+ * **Tool-driven workflows** — Read, search, edit, and write files; execute shell commands; query LSPs; run MCP tools; and integrate browser automation.
41
+ * **Plugin hooks** — Hook into prompts, shell execution, tool calls, message display, session start, and file editing actions.
42
+ * **Dynamic skills** — Load bundled and project-level skills from `.claude/skills/`.
43
+ * **Code review tools** — Use `/code-review --fix` to review changed code and apply fixes. Use `/simplify` for cleanup-focused review.
44
+ * **Guardian auto-review** — `/guardian` routes permission requests to an LLM reviewer with circuit breaker.
45
+ * **PR management** — `/pr create`, `list`, `view`, `review`, `merge`, `status`.
46
+ * **Provider-agnostic Remote Control** — `/remote` for WebSocket-based CLI sharing without claude.ai.
47
+ * **Model picker** — Choose global or session-only model defaults.
48
+ * **Plugin marketplace support** — Includes support for `skipLfs` when downloading plugin sources.
49
+ * **Local research workflow** — Use `/research <query>` for local-first web research and scraping workflows where configured.
50
+ * **Agents and supervisor** — Manage background agents, multi-step workflows, summaries, task status, approvals, and session state.
51
+ * **Background shell commands** — Run long-lived commands with `!bg <command>`.
52
+ * **Scheduled tasks** — Create one-shot or recurring tasks through `/task`.
53
+ * **Sessions and bridge mode** — Save, resume, and coordinate development sessions.
54
+
55
+ ## Quick Start
56
+
57
+ ### Install Globally
58
+
59
+ ```bash
60
+ npm install -g clew-code
61
+ ```
62
+
63
+ Or:
64
+
65
+ ```bash
66
+ bun install -g clew-code
67
+ ```
68
+
69
+ Run the CLI inside a project directory:
70
+
71
+ ```bash
72
+ clew
73
+ ```
74
+
75
+ > The global launcher requires Bun to be installed on your machine.
76
+
77
+ ### Run From Source
78
+
79
+ ```bash
80
+ git clone https://github.com/JonusNattapong/ClewCode.git
81
+ cd claudecode
82
+
83
+ bun install
84
+ bun run build
85
+ bun run start
86
+ ```
87
+
88
+ For development:
89
+
90
+ ```bash
91
+ bun run dev
92
+ ```
93
+
94
+ ## System Requirements
95
+
96
+ * Bun 1.3 or higher
97
+ * Node.js 18 or higher
98
+ * Git
99
+ * Windows, macOS, Linux, or WSL2
100
+ * At least one supported provider API key, unless using a local provider such as Ollama
101
+
102
+ ## Provider Configuration
103
+
104
+ Set provider keys in your shell or in a local `.env` file.
105
+
106
+ ```bash
107
+ export ANTHROPIC_API_KEY=sk-ant-...
108
+ export OPENAI_API_KEY=sk-...
109
+ export GOOGLE_API_KEY=...
110
+ export OPENROUTER_API_KEY=sk-or-...
111
+ export OLLAMA_HOST=http://localhost:11434
112
+ ```
113
+
114
+ Switch models or providers inside a session:
115
+
116
+ ```text
117
+ /model
118
+ /model list
119
+ /model openai/gpt-4o
120
+ /model google/gemini-2.5-pro
121
+ ```
122
+
123
+ Provider documentation:
124
+
125
+ ```text
126
+ docs/providers.html
127
+ ```
128
+
129
+ ## Frequently Used Commands
130
+
131
+ ```text
132
+ /model Switch models or providers
133
+ /taste Open taste preference-learning menu
134
+ /status Show provider, session, and context status
135
+ /doctor Run diagnostics
136
+ /context Inspect active context usage
137
+ /compact Compress conversation history
138
+ /mcp Manage Model Context Protocol servers
139
+ /code-review Review changed code for bugs
140
+ /simplify Run cleanup-focused review
141
+ /plugin Manage plugins and hooks
142
+ /bridge Configure bridge mode
143
+ /agent Manage background agent workflows
144
+ /daemon Open autonomous daemon dashboard
145
+ /task Create or manage scheduled tasks
146
+ ```
147
+
148
+ Type `/` in the CLI prompt to view available commands.
149
+
150
+ ## Scheduled Tasks
151
+
152
+ The scheduled task system is available through `/task`.
153
+
154
+ ```text
155
+ /task
156
+ ```
157
+
158
+ Examples:
159
+
160
+ ```text
161
+ /task
162
+ Name: Server Check
163
+ Schedule: Daily
164
+ Time: 20:00
165
+ Prompt: Verify the status of local servers
166
+ Storage: Durable
167
+ ```
168
+
169
+ ```text
170
+ /task
171
+ Name: Commit Reminder
172
+ Schedule: In N minutes
173
+ Delay: 10
174
+ Prompt: Remind me to commit the code
175
+ Storage: Session-only
176
+ ```
177
+
178
+ Task behavior:
179
+
180
+ * Durable tasks are saved to `.claude/scheduled_tasks.json`.
181
+ * Session-only tasks run only during the active session.
182
+ * Recurring tasks use standard 5-field cron syntax.
183
+ * One-shot tasks are removed after they run.
184
+ * Local machine timezone is used for scheduled execution.
185
+
186
+ ## Taste
187
+
188
+ Taste is a local-first preference-learning runtime. It learns from accept, reject, edit, test, lint, and manual rules. It combines symbolic rules, semantic preference scoring, and contextual bandit optimization to adapt Clew to your coding style. It does not fine-tune the base LLM.
189
+
190
+ ```text
191
+ /taste Open interactive menu
192
+ /taste learn <rule> Add a manual rule
193
+ /taste forget <id> Remove a rule
194
+ /taste profile Show all rules
195
+ /taste events Show recent events
196
+ /taste decay Apply confidence decay
197
+ /taste eval Run self-evaluation
198
+ /taste export Export high-confidence rules
199
+ /taste import <file> Import rules from file
200
+ /taste on Enable taste
201
+ /taste off Disable taste
202
+ ```
203
+
204
+ ### Key Capabilities
205
+
206
+ - **Interactive menu** — Arrow-key navigable Dialog with 11 actions, Spinner loading for async ops
207
+ - **Edit validation** — Scans edits during permission request, warns when changes violate learned rules
208
+ - **Config live-reload** — Subscribes to `settings.json` changes via `subscribeToSettingsChanges()`
209
+ - **Status line** — `ⓘ taste: N rules` shown in PromptInputFooter alongside workflow status
210
+ - **Prompt injection** — Injects `<clew_taste>` XML block with up to 8 relevant rules into system prompt
211
+ - **Signal collection** — Fire-and-forget accept/reject/tool signals from PermissionContext and tool execution
212
+ - **Decay engine** — Gradual confidence reduction for unused rules (half-life based, default 30 days)
213
+
214
+ See [docs/taste.html](docs/taste.html) for full documentation.
215
+
216
+ ## Development
217
+
218
+ ```bash
219
+ bun run dev # Start development mode
220
+ bun run start # Run the CLI from source
221
+ bun run build # Build into dist/
222
+ bun test # Run tests
223
+ bun x tsc --noEmit # Type check
224
+ bun run lint:check # Check Biome lint rules
225
+ bun run format:check # Check Biome formatting
226
+ bun run check:ci # Run Biome CI validation
227
+ ```
228
+
229
+ Developer utilities:
230
+
231
+ ```bash
232
+ bun run preload <module> # Preload module context
233
+ bun run session <command> # Save, list, or restore session context
234
+ bun run codegraph # Generate module dependency graphs
235
+ bun run ast-grep -- <args> # Run structural AST search or rewrite
236
+ ```
237
+
238
+ ## Project Structure
239
+
240
+ ```text
241
+ src/
242
+ ├── main.tsx # Terminal UI bootstrap and main loop
243
+ ├── query.ts # Query processing and system prompt logic
244
+ ├── QueryEngine.ts # Query orchestration, caching, deduplication, and rate limits
245
+ ├── agentRuntime/ # Agent orchestration and persistent run stores
246
+ ├── commands/ # Slash command implementations
247
+ ├── tools/ # Built-in developer tools
248
+ ├── services/
249
+ │ ├── ai/ # Provider manager, adapters, normalizers, and providers.json
250
+ │ ├── mcp/ # Model Context Protocol clients
251
+ │ ├── plugins/ # Plugin lifecycle hooks and interceptors
252
+ │ ├── tools/ # Tool execution service
253
+ │ ├── lsp/ # Language Server Protocol integration
254
+ │ ├── Supervisor/ # Background agent supervisor
255
+ │ └── SessionMemory/ # Persistent session memory
256
+ ├── skills/ # Dynamic skill loader
257
+ ├── cli/ # Terminal UI contexts
258
+ ├── components/ # Terminal UI components
259
+ ├── bridge/ # WebSocket bridge
260
+ ├── coordinator/ # Multi-agent coordinator
261
+ ├── keybindings/ # Keyboard shortcut mappings
262
+ ├── state/ # Reactive stores
263
+ └── vim/ # Vim-like navigation mode
264
+ ```
265
+
266
+ ## Architecture
267
+
268
+ ```text
269
+ Terminal UI
270
+ -> Command registry and keybindings
271
+ -> Provider manager and AI adapters
272
+ -> Query engine and streaming loops
273
+ -> Tool executor service
274
+ -> Plugins, MCP, LSP, agents, session memory, and bridge
275
+ ```
276
+
277
+ ## Documentation
278
+
279
+ * [Installation](docs/installation.html)
280
+ * [Quick Start](docs/quick-start.html)
281
+ * [Configuration](docs/configuration.html)
282
+ * [AI Providers](docs/providers.html)
283
+ * [Models](docs/models.html)
284
+ * [Commands](docs/commands.html)
285
+ * [Tools](docs/tools.html)
286
+ * [Plugins](docs/plugins.html)
287
+ * [Skills](docs/skills.html)
288
+ * [Architecture](docs/architecture.html)
289
+ * [Permission Model](docs/permission-model.html)
290
+ * [Bridge Mode](docs/features/bridge-mode.html)
291
+ * [SearXNG Search](docs/features/searxng-search.html)
292
+ * [Troubleshooting](docs/troubleshooting.html)
293
+ * [Evals](docs/features/evals.html)
294
+ * [Taste](docs/taste.html)
295
+
296
+ ## Debugging
297
+
298
+ ```bash
299
+ DEBUG=1 bun run src/main.tsx
300
+ DEBUG=provider:anthropic bun run src/main.tsx
301
+ ```
302
+
303
+ ## Platform Notes
304
+
305
+ ### Windows
306
+
307
+ ```powershell
308
+ Remove-Item -Recurse -Force node_modules
309
+ bun install
310
+ bun run dev
311
+ ```
312
+
313
+ A precompiled `ripgrep` binary for Windows may be bundled under:
314
+
315
+ ```text
316
+ src/utils/vendor/ripgrep/x64-win32/rg.exe
317
+ ```
318
+
319
+ ## Contributing
320
+
321
+ Read these files before contributing:
322
+
323
+ * [CONTRIBUTING.md](CONTRIBUTING.md)
324
+ * [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
325
+ * [SECURITY.md](SECURITY.md)
326
+ * [LICENSE.md](LICENSE.md)
327
+
328
+ Do not submit proprietary code, copied source, leaked material, credentials, private keys, or content you do not have the right to license.
329
+
330
+ ## Security
331
+
332
+ Do not open public issues for security vulnerabilities.
333
+
334
+ Use the private reporting process described in [SECURITY.md](SECURITY.md).
335
+
336
+ ## Changelog
337
+
338
+ ### 0.2.1 (2026-06-05)
339
+
340
+ - **Taste system** — local-first preference-learning runtime. Interactive `/taste` menu with Spinner loading, edit validation in FileEditPermissionRequest, status line in PromptInputFooter, config live-reload via settings change subscription, XML tag `<clew_taste>` prompt injection.
341
+ - **Model picker** — `/model` now shows all models from all providers grouped by provider section.
342
+ - **Provider auto-persist** — last-used provider+model saved to `provider.json` without `--global`.
343
+ - **Security hardening** — PowerShell prefix/wildcard rules for native executables, malformed tool call guard, bash runtime 100MB output limit.
344
+ - **Guardian auto-review** — LLM-based permission reviewer with circuit breaker and `/approve` override.
345
+ - **Bridge v2** — Provider-agnostic Remote Control via WebSocket, relay client, REPL bridging.
346
+ - **PR commands** — `/pr create`, `list`, `view`, `review`, `merge`, `status`.
347
+ - **Dynamic Workflow** — Ultracode bootstrap, progress UI polling `.claude/runs/`, transcript classifier suggestion.
348
+ - Fixed blank screen (SentryErrorBoundary + TDZ in REPL.tsx), autocomplete hint duplication, ProviderManager base URL resolution for session-level overrides.
349
+
350
+ See [CHANGELOG.md](CHANGELOG.md) for full history.
351
+
352
+ ## License
353
+
354
+ See [LICENSE.md](LICENSE.md).
355
+
356
+ Only contributor-authored modifications and original additions are licensed as described in `LICENSE.md`. This repository does not grant rights to Anthropic proprietary software, services, models, trademarks, or other protected materials.
package/bin/claudevil ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import '../dist/main.js';
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ const { spawn, spawnSync } = require('child_process');
3
+ const { existsSync } = require('fs');
4
+ const path = require('path');
5
+
6
+ function resolveWindowsBunShim(candidate) {
7
+ const candidateDir = path.dirname(candidate);
8
+ const npmBunExe = path.join(candidateDir, 'node_modules', 'bun', 'bin', 'bun.exe');
9
+
10
+ if (existsSync(npmBunExe)) {
11
+ return npmBunExe;
12
+ }
13
+
14
+ return null;
15
+ }
16
+
17
+ function resolveBunCommand() {
18
+ const whichCommand = process.platform === 'win32' ? 'where' : 'which';
19
+ const result = spawnSync(whichCommand, ['bun'], {
20
+ encoding: 'utf8',
21
+ stdio: ['ignore', 'pipe', 'ignore'],
22
+ shell: false,
23
+ });
24
+
25
+ if (result.status !== 0 || !result.stdout) {
26
+ return null;
27
+ }
28
+
29
+ const candidates = result.stdout
30
+ .split(/\r?\n/)
31
+ .map(line => line.trim())
32
+ .filter(Boolean);
33
+
34
+ if (process.platform === 'win32') {
35
+ const exeCandidate = candidates.find(candidate => candidate.toLowerCase().endsWith('.exe'));
36
+ if (exeCandidate) {
37
+ return exeCandidate;
38
+ }
39
+
40
+ for (const candidate of candidates) {
41
+ const shimTarget = resolveWindowsBunShim(candidate);
42
+ if (shimTarget) {
43
+ return shimTarget;
44
+ }
45
+ }
46
+
47
+ return candidates.find(candidate => candidate.toLowerCase().endsWith('.cmd')) || candidates[0];
48
+ }
49
+
50
+ return candidates[0];
51
+ }
52
+
53
+ function printBunInstallHelp() {
54
+ const installCommand =
55
+ process.platform === 'win32'
56
+ ? 'powershell -c "irm bun.sh/install.ps1 | iex"'
57
+ : 'curl -fsSL https://bun.sh/install | bash';
58
+
59
+ console.error('Claudevil requires Bun at runtime.');
60
+ console.error('This npm package installs the launcher, but the CLI itself runs with Bun.');
61
+ console.error('');
62
+ console.error('Install Bun, then run `claudevil` again:');
63
+ console.error(` ${installCommand}`);
64
+ }
65
+
66
+ const mainJs = path.join(__dirname, '..', 'dist', 'main.js');
67
+ const bunCommand = resolveBunCommand();
68
+
69
+ if (!bunCommand) {
70
+ printBunInstallHelp();
71
+ process.exit(1);
72
+ }
73
+
74
+ try {
75
+ const child = spawn(bunCommand, [mainJs, ...process.argv.slice(2)], {
76
+ stdio: 'inherit',
77
+ shell: false,
78
+ });
79
+
80
+ child.on('error', e => {
81
+ console.error('Error executing Bun:', e.message || e);
82
+ process.exit(1);
83
+ });
84
+
85
+ child.on('exit', (code, signal) => {
86
+ if (signal) {
87
+ process.kill(process.pid, signal);
88
+ return;
89
+ }
90
+
91
+ process.exit(code ?? 0);
92
+ });
93
+ } catch (e) {
94
+ console.error('Error executing Bun:', e.message || e);
95
+ process.exit(e.status ?? 1);
96
+ }
package/bin/clew ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bun
2
+ import '../dist/main.js';
package/bin/clew.cjs ADDED
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ const { spawn, spawnSync } = require('child_process');
3
+ const { existsSync } = require('fs');
4
+ const path = require('path');
5
+
6
+ function resolveWindowsBunShim(candidate) {
7
+ const candidateDir = path.dirname(candidate);
8
+ const npmBunExe = path.join(candidateDir, 'node_modules', 'bun', 'bin', 'bun.exe');
9
+
10
+ if (existsSync(npmBunExe)) {
11
+ return npmBunExe;
12
+ }
13
+
14
+ return null;
15
+ }
16
+
17
+ function resolveBunCommand() {
18
+ const whichCommand = process.platform === 'win32' ? 'where' : 'which';
19
+ const result = spawnSync(whichCommand, ['bun'], {
20
+ encoding: 'utf8',
21
+ stdio: ['ignore', 'pipe', 'ignore'],
22
+ shell: false,
23
+ });
24
+
25
+ if (result.status !== 0 || !result.stdout) {
26
+ return null;
27
+ }
28
+
29
+ const candidates = result.stdout
30
+ .split(/\r?\n/)
31
+ .map(line => line.trim())
32
+ .filter(Boolean);
33
+
34
+ if (process.platform === 'win32') {
35
+ const exeCandidate = candidates.find(candidate => candidate.toLowerCase().endsWith('.exe'));
36
+ if (exeCandidate) {
37
+ return exeCandidate;
38
+ }
39
+
40
+ for (const candidate of candidates) {
41
+ const shimTarget = resolveWindowsBunShim(candidate);
42
+ if (shimTarget) {
43
+ return shimTarget;
44
+ }
45
+ }
46
+
47
+ return candidates.find(candidate => candidate.toLowerCase().endsWith('.cmd')) || candidates[0];
48
+ }
49
+
50
+ return candidates[0];
51
+ }
52
+
53
+ function printBunInstallHelp() {
54
+ const installCommand =
55
+ process.platform === 'win32'
56
+ ? 'powershell -c "irm bun.sh/install.ps1 | iex"'
57
+ : 'curl -fsSL https://bun.sh/install | bash';
58
+
59
+ console.error('Clew requires Bun at runtime.');
60
+ console.error('This npm package installs the launcher, but the CLI itself runs with Bun.');
61
+ console.error('');
62
+ console.error('Install Bun, then run `clew` again:');
63
+ console.error(` ${installCommand}`);
64
+ }
65
+
66
+ const mainJs = path.join(__dirname, '..', 'dist', 'main.js');
67
+ const bunCommand = resolveBunCommand();
68
+
69
+ if (!bunCommand) {
70
+ printBunInstallHelp();
71
+ process.exit(1);
72
+ }
73
+
74
+ try {
75
+ const child = spawn(bunCommand, [mainJs, ...process.argv.slice(2)], {
76
+ stdio: 'inherit',
77
+ shell: false,
78
+ });
79
+
80
+ child.on('error', e => {
81
+ console.error('Error executing Bun:', e.message || e);
82
+ process.exit(1);
83
+ });
84
+
85
+ child.on('exit', (code, signal) => {
86
+ if (signal) {
87
+ process.kill(process.pid, signal);
88
+ return;
89
+ }
90
+
91
+ process.exit(code ?? 0);
92
+ });
93
+ } catch (e) {
94
+ console.error('Error executing Bun:', e.message || e);
95
+ process.exit(e.status ?? 1);
96
+ }