From 1b77a70b188f87e11cfbe31f5e977eedf8acbb19 Mon Sep 17 00:00:00 2001 From: sanbuphy Date: Tue, 31 Mar 2026 18:12:54 +0800 Subject: [PATCH] Add build infrastructure and QUICKSTART guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Build script (scripts/build.mjs) using esbuild with iterative stub creation - Stubs for Bun compile-time intrinsics (feature(), MACRO, bun:bundle) - Stub modules for feature-gated internal code paths - QUICKSTART.md with 3 build options (pre-built, esbuild, Bun) - tsconfig.json, package.json for build tooling Build reaches ~95% — 108 remaining feature-gated modules need Bun runtime for full dead code elimination. See QUICKSTART.md for details. Co-Authored-By: Claude Opus 4.6 --- .gitignore | 2 + QUICKSTART.md | 121 +++++ README.md | 2 + package-lock.json | 517 +++++++++++++++++++++ package.json | 20 + scripts/build.mjs | 245 ++++++++++ scripts/prepare-src.mjs | 115 +++++ scripts/stub-modules.mjs | 158 +++++++ scripts/transform.mjs | 143 ++++++ stubs/bun-bundle.ts | 4 + stubs/global.d.ts | 11 + stubs/macros.d.ts | 15 + stubs/macros.ts | 20 + tools/OverflowTestTool/OverflowTestTool.js | 3 + tools/TerminalCaptureTool/prompt.js | 3 + tools/TungstenTool/TungstenTool.js | 3 + tools/VerifyPlanExecutionTool/constants.js | 3 + tools/WorkflowTool/constants.js | 3 + tsconfig.json | 36 ++ types/connectorText.js | 3 + utils/attributionHooks.js | 3 + utils/systemThemeWatcher.js | 3 + utils/udsClient.js | 3 + 23 files changed, 1436 insertions(+) create mode 100644 QUICKSTART.md create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 scripts/build.mjs create mode 100644 scripts/prepare-src.mjs create mode 100644 scripts/stub-modules.mjs create mode 100644 scripts/transform.mjs create mode 100644 stubs/bun-bundle.ts create mode 100644 stubs/global.d.ts create mode 100644 stubs/macros.d.ts create mode 100644 stubs/macros.ts create mode 100644 tools/OverflowTestTool/OverflowTestTool.js create mode 100644 tools/TerminalCaptureTool/prompt.js create mode 100644 tools/TungstenTool/TungstenTool.js create mode 100644 tools/VerifyPlanExecutionTool/constants.js create mode 100644 tools/WorkflowTool/constants.js create mode 100644 tsconfig.json create mode 100644 types/connectorText.js create mode 100644 utils/attributionHooks.js create mode 100644 utils/systemThemeWatcher.js create mode 100644 utils/udsClient.js diff --git a/.gitignore b/.gitignore index c2658d7..dca3340 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules/ +build-src/ +dist/ diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..98d5924 --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,121 @@ +# Quick Start — Building from Source + +> **TL;DR**: A full rebuild requires **Bun** (not Node.js) for its compile-time +> intrinsics (`feature()`, `MACRO`, `bun:bundle`). A best-effort build with +> esbuild gets ~95% there but needs manual fixes for ~108 feature-gated modules. + +## Option A: Run the pre-built CLI (Recommended) + +The npm package already contains a compiled `cli.js`: + +```bash +cd /path/to/parent/ # where package.json and cli.js live +node cli.js --version # → 2.1.88 (Claude Code) +node cli.js -p "Hello Claude" # Non-interactive mode + +# Or install globally: +npm install -g . +claude --version +``` + +**Authentication required**: Set `ANTROPIC_API_KEY` or run `node cli.js login`. + +## Option B: Build from Source (Best Effort) + +### Prerequisites + +```bash +node --version # >= 18 +npm --version # >= 9 +``` + +### Steps + +```bash +cd claude-code-2.1.88/ + +# 1. Install build dependency +npm install --save-dev esbuild + +# 2. Run the build script +node scripts/build.mjs + +# 3. If successful, run the output: +node dist/cli.js --version +``` + +### What the Build Script Does + +| Phase | Action | +|-------|--------| +| **1. Copy** | `src/` → `build-src/` (original untouched) | +| **2. Transform** | `feature('X')` → `false` (enables dead code elimination) | +| **2b. Transform** | `MACRO.VERSION` → `'2.1.88'` (compile-time version injection) | +| **2c. Transform** | `import from 'bun:bundle'` → stub import | +| **3. Entry** | Create wrapper that injects MACRO globals | +| **4. Bundle** | esbuild with iterative stub creation for missing modules | + +### Known Issues + +The source code uses **Bun compile-time intrinsics** that cannot be fully replicated with esbuild: + +1. **`feature('FLAG')` from `bun:bundle`** — Bun resolves this at compile time to `true`/`false` and eliminates dead branches. Our transform replaces with `false`, but esbuild still resolves `require()` inside those branches. + +2. **`MACRO.X`** — Bun's `--define` replaces these at compile time. We use string replacement, which works for most cases but can miss edge cases in complex expressions. + +3. **108 missing modules** — These are feature-gated internal modules (daemon, bridge assistant, context collapse, etc.) that don't exist in the published source. They're normally dead-code-eliminated by Bun but esbuild can't eliminate them because the `require()` calls are still syntactically present. + +4. **`bun:ffi`** — Used for native proxy support. Stubbed out. + +5. **TypeScript `import type` from generated files** — Some generated type files are not in the published source. + +### To Fix Remaining Issues + +```bash +# 1. Check what's still missing: +npx esbuild build-src/entry.ts --bundle --platform=node \ + --packages=external --external:'bun:*' \ + --log-level=error --log-limit=0 --outfile=/dev/null 2>&1 | \ + grep "Could not resolve" | sort -u + +# 2. Create stubs for each missing module in build-src/src/: +# For JS/TS: create file exporting empty functions +# For text: create empty file + +# 3. Re-run: +node scripts/build.mjs +``` + +## Option C: Build with Bun (Full Rebuild — Requires Internal Access) + +```bash +# Install Bun +curl -fsSL https://bun.sh/install | bash + +# The real build uses Bun's bundler with compile-time feature flags: +# bun build src/entrypoints/cli.tsx \ +# --define:feature='(flag) => flag === "SOME_FLAG"' \ +# --define:MACRO.VERSION='"2.1.88"' \ +# --target=bun \ +# --outfile=dist/cli.js + +# However, the internal build configuration is not included in the +# published package. You'd need access to Anthropic's internal repo. +``` + +## Project Structure + +``` +claude-code-2.1.88/ +├── src/ # Original TypeScript source (1,884 files, 512K LOC) +├── stubs/ # Build stubs for Bun compile-time intrinsics +│ ├── bun-bundle.ts # feature() stub → always returns false +│ ├── macros.ts # MACRO version constants +│ └── global.d.ts # Global type declarations +├── scripts/ +│ └── build.mjs # Build script (esbuild-based) +├── node_modules/ # 192 npm dependencies +├── vendor/ # Native module source stubs +├── build-src/ # Created by build script (transformed copy) +└── dist/ # Build output (created by build script) +``` diff --git a/README.md b/README.md index 2b579d0..a5c2399 100644 --- a/README.md +++ b/README.md @@ -745,6 +745,8 @@ This source is **not directly compilable** from this repo alone: - The compiled `cli.js` is a self-contained 12MB bundle requiring only Node.js >= 18 - Source maps (`cli.js.map`, 60MB) map back to these source files for debugging +**See [QUICKSTART.md](QUICKSTART.md) for build instructions and workarounds.** + --- ## License diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..83093d6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,517 @@ +{ + "name": "@anthropic-ai/claude-code-source", + "version": "2.1.88", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@anthropic-ai/claude-code-source", + "version": "2.1.88", + "devDependencies": { + "esbuild": "^0.27.4", + "typescript": "^6.0.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz", + "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.4.tgz", + "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz", + "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.4.tgz", + "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz", + "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz", + "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz", + "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz", + "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz", + "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz", + "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz", + "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz", + "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz", + "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz", + "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz", + "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz", + "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz", + "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz", + "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz", + "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz", + "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz", + "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz", + "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz", + "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz", + "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz", + "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz", + "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/esbuild": { + "version": "0.27.4", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.4.tgz", + "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.4", + "@esbuild/android-arm": "0.27.4", + "@esbuild/android-arm64": "0.27.4", + "@esbuild/android-x64": "0.27.4", + "@esbuild/darwin-arm64": "0.27.4", + "@esbuild/darwin-x64": "0.27.4", + "@esbuild/freebsd-arm64": "0.27.4", + "@esbuild/freebsd-x64": "0.27.4", + "@esbuild/linux-arm": "0.27.4", + "@esbuild/linux-arm64": "0.27.4", + "@esbuild/linux-ia32": "0.27.4", + "@esbuild/linux-loong64": "0.27.4", + "@esbuild/linux-mips64el": "0.27.4", + "@esbuild/linux-ppc64": "0.27.4", + "@esbuild/linux-riscv64": "0.27.4", + "@esbuild/linux-s390x": "0.27.4", + "@esbuild/linux-x64": "0.27.4", + "@esbuild/netbsd-arm64": "0.27.4", + "@esbuild/netbsd-x64": "0.27.4", + "@esbuild/openbsd-arm64": "0.27.4", + "@esbuild/openbsd-x64": "0.27.4", + "@esbuild/openharmony-arm64": "0.27.4", + "@esbuild/sunos-x64": "0.27.4", + "@esbuild/win32-arm64": "0.27.4", + "@esbuild/win32-ia32": "0.27.4", + "@esbuild/win32-x64": "0.27.4" + } + }, + "node_modules/typescript": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/typescript/-/typescript-6.0.2.tgz", + "integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..3fccc74 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "@anthropic-ai/claude-code-source", + "version": "2.1.88", + "description": "Claude Code v2.1.88 — decompiled source for research", + "type": "module", + "private": true, + "scripts": { + "prepare-src": "node scripts/prepare-src.mjs", + "build": "npm run prepare-src && node scripts/build.mjs", + "check": "npm run prepare-src && tsc --noEmit", + "start": "node dist/cli.js" + }, + "engines": { + "node": ">=18.0.0" + }, + "devDependencies": { + "esbuild": "^0.27.4", + "typescript": "^6.0.2" + } +} diff --git a/scripts/build.mjs b/scripts/build.mjs new file mode 100644 index 0000000..ba9c0ab --- /dev/null +++ b/scripts/build.mjs @@ -0,0 +1,245 @@ +#!/usr/bin/env node +/** + * build.mjs — Best-effort build of Claude Code v2.1.88 from source + * + * ⚠️ IMPORTANT: A complete rebuild requires the Bun runtime's compile-time + * intrinsics (feature(), MACRO, bun:bundle). This script provides a + * best-effort build using esbuild. See KNOWN_ISSUES.md for details. + * + * What this script does: + * 1. Copy src/ → build-src/ (original untouched) + * 2. Replace `feature('X')` → `false` (compile-time → runtime) + * 3. Replace `MACRO.VERSION` etc → string literals + * 4. Replace `import from 'bun:bundle'` → stub + * 5. Create stubs for missing feature-gated modules + * 6. Bundle with esbuild → dist/cli.js + * + * Requirements: Node.js >= 18, npm + * Usage: node scripts/build.mjs + */ + +import { readdir, readFile, writeFile, mkdir, cp, rm, stat } from 'node:fs/promises' +import { join, dirname } from 'node:path' +import { execSync } from 'node:child_process' +import { fileURLToPath } from 'node:url' + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const ROOT = join(__dirname, '..') +const VERSION = '2.1.88' +const BUILD = join(ROOT, 'build-src') +const ENTRY = join(BUILD, 'entry.ts') + +// ── Helpers ──────────────────────────────────────────────────────────────── + +async function* walk(dir) { + for (const e of await readdir(dir, { withFileTypes: true })) { + const p = join(dir, e.name) + if (e.isDirectory() && e.name !== 'node_modules') yield* walk(p) + else yield p + } +} + +async function exists(p) { try { await stat(p); return true } catch { return false } } + +async function ensureEsbuild() { + try { execSync('npx esbuild --version', { stdio: 'pipe' }) } + catch { + console.log('📦 Installing esbuild...') + execSync('npm install --save-dev esbuild', { cwd: ROOT, stdio: 'inherit' }) + } +} + +// ══════════════════════════════════════════════════════════════════════════════ +// PHASE 1: Copy source +// ══════════════════════════════════════════════════════════════════════════════ + +await rm(BUILD, { recursive: true, force: true }) +await mkdir(BUILD, { recursive: true }) +await cp(join(ROOT, 'src'), join(BUILD, 'src'), { recursive: true }) +console.log('✅ Phase 1: Copied src/ → build-src/') + +// ══════════════════════════════════════════════════════════════════════════════ +// PHASE 2: Transform source +// ══════════════════════════════════════════════════════════════════════════════ + +let transformCount = 0 + +// MACRO replacements +const MACROS = { + 'MACRO.VERSION': `'${VERSION}'`, + 'MACRO.BUILD_TIME': `''`, + 'MACRO.FEEDBACK_CHANNEL': `'https://github.com/anthropics/claude-code/issues'`, + 'MACRO.ISSUES_EXPLAINER': `'https://github.com/anthropics/claude-code/issues/new/choose'`, + 'MACRO.FEEDBACK_CHANNEL_URL': `'https://github.com/anthropics/claude-code/issues'`, + 'MACRO.ISSUES_EXPLAINER_URL': `'https://github.com/anthropics/claude-code/issues/new/choose'`, + 'MACRO.NATIVE_PACKAGE_URL': `'@anthropic-ai/claude-code'`, + 'MACRO.PACKAGE_URL': `'@anthropic-ai/claude-code'`, + 'MACRO.VERSION_CHANGELOG': `''`, +} + +for await (const file of walk(join(BUILD, 'src'))) { + if (!file.match(/\.[tj]sx?$/)) continue + + let src = await readFile(file, 'utf8') + let changed = false + + // 2a. feature('X') → false + if (/\bfeature\s*\(\s*['"][A-Z_]+['"]\s*\)/.test(src)) { + src = src.replace(/\bfeature\s*\(\s*['"][A-Z_]+['"]\s*\)/g, 'false') + changed = true + } + + // 2b. MACRO.X → literals + for (const [k, v] of Object.entries(MACROS)) { + if (src.includes(k)) { + src = src.replaceAll(k, v) + changed = true + } + } + + // 2c. Remove bun:bundle import (feature() is already replaced) + if (src.includes("from 'bun:bundle'") || src.includes('from "bun:bundle"')) { + src = src.replace(/import\s*\{\s*feature\s*\}\s*from\s*['"]bun:bundle['"];?\n?/g, '// feature() replaced with false at build time\n') + changed = true + } + + // 2d. Remove type-only import of global.d.ts + if (src.includes("import '../global.d.ts'") || src.includes("import './global.d.ts'")) { + src = src.replace(/import\s*['"][.\/]*global\.d\.ts['"];?\n?/g, '') + changed = true + } + + if (changed) { + await writeFile(file, src, 'utf8') + transformCount++ + } +} +console.log(`✅ Phase 2: Transformed ${transformCount} files`) + +// ══════════════════════════════════════════════════════════════════════════════ +// PHASE 3: Create entry wrapper +// ══════════════════════════════════════════════════════════════════════════════ + +await writeFile(ENTRY, `#!/usr/bin/env node +// Claude Code v${VERSION} — built from source +// Copyright (c) Anthropic PBC. All rights reserved. +import './src/entrypoints/cli.tsx' +`, 'utf8') +console.log('✅ Phase 3: Created entry wrapper') + +// ══════════════════════════════════════════════════════════════════════════════ +// PHASE 4: Iterative stub + bundle +// ══════════════════════════════════════════════════════════════════════════════ + +await ensureEsbuild() + +const OUT_DIR = join(ROOT, 'dist') +await mkdir(OUT_DIR, { recursive: true }) +const OUT_FILE = join(OUT_DIR, 'cli.js') + +// Run up to 5 rounds of: esbuild → collect missing → create stubs → retry +const MAX_ROUNDS = 5 +let succeeded = false + +for (let round = 1; round <= MAX_ROUNDS; round++) { + console.log(`\n🔨 Phase 4 round ${round}/${MAX_ROUNDS}: Bundling...`) + + let esbuildOutput = '' + try { + esbuildOutput = execSync([ + 'npx esbuild', + `"${ENTRY}"`, + '--bundle', + '--platform=node', + '--target=node18', + '--format=esm', + `--outfile="${OUT_FILE}"`, + `--banner:js=$'#!/usr/bin/env node\\n// Claude Code v${VERSION} (built from source)\\n// Copyright (c) Anthropic PBC. All rights reserved.\\n'`, + '--packages=external', + '--external:bun:*', + '--allow-overwrite', + '--log-level=error', + '--log-limit=0', + '--sourcemap', + ].join(' '), { + cwd: ROOT, + stdio: ['pipe', 'pipe', 'pipe'], + shell: true, + }).stderr?.toString() || '' + succeeded = true + break + } catch (e) { + esbuildOutput = (e.stderr?.toString() || '') + (e.stdout?.toString() || '') + } + + // Parse missing modules + const missingRe = /Could not resolve "([^"]+)"/g + const missing = new Set() + let m + while ((m = missingRe.exec(esbuildOutput)) !== null) { + const mod = m[1] + if (!mod.startsWith('node:') && !mod.startsWith('bun:') && !mod.startsWith('/')) { + missing.add(mod) + } + } + + if (missing.size === 0) { + // No more missing modules but still errors — check what + const errLines = esbuildOutput.split('\n').filter(l => l.includes('ERROR')).slice(0, 5) + console.log('❌ Unrecoverable errors:') + errLines.forEach(l => console.log(' ' + l)) + break + } + + console.log(` Found ${missing.size} missing modules, creating stubs...`) + + // Create stubs + let stubCount = 0 + for (const mod of missing) { + // Resolve relative path from the file that imports it — but since we + // don't have that info easily, create stubs at multiple likely locations + const cleanMod = mod.replace(/^\.\//, '') + + // Text assets → empty file + if (/\.(txt|md|json)$/.test(cleanMod)) { + const p = join(BUILD, 'src', cleanMod) + await mkdir(dirname(p), { recursive: true }).catch(() => {}) + if (!await exists(p)) { + await writeFile(p, cleanMod.endsWith('.json') ? '{}' : '', 'utf8') + stubCount++ + } + continue + } + + // JS/TS modules → export empty + if (/\.[tj]sx?$/.test(cleanMod)) { + for (const base of [join(BUILD, 'src'), join(BUILD, 'src', 'src')]) { + const p = join(base, cleanMod) + await mkdir(dirname(p), { recursive: true }).catch(() => {}) + if (!await exists(p)) { + const name = cleanMod.split('/').pop().replace(/\.[tj]sx?$/, '') + const safeName = name.replace(/[^a-zA-Z0-9_$]/g, '_') || 'stub' + await writeFile(p, `// Auto-generated stub\nexport default function ${safeName}() {}\nexport const ${safeName} = () => {}\n`, 'utf8') + stubCount++ + } + } + } + } + console.log(` Created ${stubCount} stubs`) +} + +if (succeeded) { + const size = (await stat(OUT_FILE)).size + console.log(`\n✅ Build succeeded: ${OUT_FILE}`) + console.log(` Size: ${(size / 1024 / 1024).toFixed(1)}MB`) + console.log(`\n Usage: node ${OUT_FILE} --version`) + console.log(` node ${OUT_FILE} -p "Hello"`) +} else { + console.error('\n❌ Build failed after all rounds.') + console.error(' The transformed source is in build-src/ for inspection.') + console.error('\n To fix manually:') + console.error(' 1. Check build-src/ for the transformed files') + console.error(' 2. Create missing stubs in build-src/src/') + console.error(' 3. Re-run: node scripts/build.mjs') + process.exit(1) +} diff --git a/scripts/prepare-src.mjs b/scripts/prepare-src.mjs new file mode 100644 index 0000000..138a953 --- /dev/null +++ b/scripts/prepare-src.mjs @@ -0,0 +1,115 @@ +#!/usr/bin/env node +/** + * prepare-src.mjs — Pre-build source transformation + * + * This script patches the source tree to make it compilable without Bun: + * 1. Replace `import { feature } from 'bun:bundle'` with our stub + * 2. Replace `MACRO.X` references with runtime values + * 3. Create missing type declarations + */ + +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const ROOT = path.resolve(__dirname, '..') +const SRC = path.join(ROOT, 'src') + +const VERSION = '2.1.88' + +// ── Helpers ────────────────────────────────────────────────────────────────── + +function walk(dir, ext = '.ts') { + const results = [] + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name) + if (entry.isDirectory() && entry.name !== 'node_modules') { + results.push(...walk(full, ext)) + } else if (entry.name.endsWith(ext) || entry.name.endsWith('.tsx')) { + results.push(full) + } + } + return results +} + +function patchFile(filePath) { + let src = fs.readFileSync(filePath, 'utf8') + let changed = false + + // 1. Replace `import { feature } from 'bun:bundle'` / `"bun:bundle"` + if (src.includes("from 'bun:bundle'") || src.includes('from "bun:bundle"')) { + src = src.replace(/import\s*\{\s*feature\s*\}\s*from\s*['"]bun:bundle['"]/g, + "import { feature } from '../stubs/bun-bundle.js'") + // Fix relative depth based on file location + const rel = path.relative(SRC, path.dirname(filePath)) + const depth = rel ? '../'.repeat(rel.split('/').length) : '' + if (depth) { + src = src.replace("from '../stubs/bun-bundle.js'", `from '${depth}stubs/bun-bundle.js'`) + } + changed = true + } + + // 2. Replace MACRO.X with string literals + const macroReplacements = { + 'MACRO.VERSION': `'${VERSION}'`, + 'MACRO.BUILD_TIME': `'${new Date().toISOString()}'`, + 'MACRO.FEEDBACK_CHANNEL': `'https://github.com/anthropics/claude-code/issues'`, + 'MACRO.ISSUES_EXPLAINER': `'https://github.com/anthropics/claude-code/issues/new/choose'`, + 'MACRO.NATIVE_PACKAGE_URL': `'@anthropic-ai/claude-code'`, + 'MACRO.PACKAGE_URL': `'@anthropic-ai/claude-code'`, + 'MACRO.VERSION_CHANGELOG': `''`, + } + + for (const [macro, replacement] of Object.entries(macroReplacements)) { + if (src.includes(macro)) { + // Don't replace inside strings + src = src.replace(new RegExp(`(?&1 || true`, + { cwd: ROOT, shell: true, encoding: 'utf8', maxBuffer: 50 * 1024 * 1024 } +) + +const missingRe = /Could not resolve "([^"]+)"/g +const errors = [...out.matchAll(/\s+(\S+:\d+:\d+):\s/g)].map(m => m[1]) +const moduleFiles = new Map() // module → set of importing files + +let match +while ((match = missingRe.exec(out)) !== null) { + const mod = match[1] + if (mod.startsWith('node:') || mod.startsWith('bun:') || mod.startsWith('/')) continue + moduleFiles.set(mod, new Set()) +} + +// Now resolve each relative module path to its absolute path +// by finding which source file imports it +const importRe = /(\S+:\d+:\d+):\s*\d+.*require\(["']([^"']+)["']\)|import.*from\s*["']([^"']+)["']/g + +let stubCount = 0 +const created = new Set() + +for (const [mod] of moduleFiles) { + // For relative imports, we need to find the importing file to resolve the path + // Search for the import in the build-src + const escapedMod = mod.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + const grepResult = execSync( + `grep -rl "${escapedMod}" "${BUILD_SRC}" 2>/dev/null || true`, + { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024, shell: true } + ).trim() + + const importers = grepResult.split('\n').filter(Boolean) + + for (const importer of importers) { + const importerDir = dirname(importer) + const absPath = resolve(importerDir, mod) + + // Check if it's a .d.ts type file — just create empty + if (mod.endsWith('.d.ts')) { + if (!created.has(absPath)) { + await mkdir(dirname(absPath), { recursive: true }).catch(() => {}) + if (!await exists(absPath)) { + await writeFile(absPath, '// Type stub\nexport {}\n', 'utf8') + stubCount++ + created.add(absPath) + } + } + continue + } + + // Text assets (.txt, .md) + if (/\.(txt|md)$/.test(mod)) { + if (!created.has(absPath)) { + await mkdir(dirname(absPath), { recursive: true }).catch(() => {}) + if (!await exists(absPath)) { + await writeFile(absPath, '', 'utf8') + stubCount++ + created.add(absPath) + } + } + continue + } + + // JS/TS modules + if (/\.[tj]sx?$/.test(mod)) { + if (!created.has(absPath)) { + await mkdir(dirname(absPath), { recursive: true }).catch(() => {}) + if (!await exists(absPath)) { + const name = mod.split('/').pop().replace(/\.[tj]sx?$/, '') + const safeName = name.replace(/[^a-zA-Z0-9_$]/g, '_') || 'stub' + await writeFile(absPath, `// Auto-generated stub for feature-gated module: ${mod}\nexport default function ${safeName}() { return null }\nexport const ${safeName} = () => null\n`, 'utf8') + stubCount++ + created.add(absPath) + } + } + } + } + + // Also try resolving from src root for modules starting with ../ + if (mod.startsWith('../')) { + // Try from several likely locations + for (const prefix of ['src', 'src/commands', 'src/components', 'src/services', 'src/tools', 'src/utils']) { + const absPath = join(ROOT, 'build-src', prefix, mod) + if (!created.has(absPath)) { + await mkdir(dirname(absPath), { recursive: true }).catch(() => {}) + if (!await exists(absPath) && (/\.[tj]sx?$/.test(mod))) { + const name = mod.split('/').pop().replace(/\.[tj]sx?$/, '') + const safeName = name.replace(/[^a-zA-Z0-9_$]/g, '_') || 'stub' + await writeFile(absPath, `// Auto-generated stub for: ${mod}\nexport default function ${safeName}() { return null }\nexport const ${safeName} = () => null\n`, 'utf8') + stubCount++ + created.add(absPath) + } + } + } + } +} + +console.log(`✅ Created ${stubCount} stubs for ${moduleFiles.size} missing modules`) + +// Now try the build +console.log('\n🔨 Attempting esbuild bundle...\n') +try { + const OUT = join(ROOT, 'dist', 'cli.js') + await mkdir(dirname(OUT), { recursive: true }) + + execSync([ + 'npx esbuild', + `"${join(ROOT, 'build-src', 'entry.ts')}"`, + '--bundle', + '--platform=node', + '--target=node18', + '--format=esm', + `--outfile="${OUT}"`, + '--packages=external', + '--external:bun:*', + '--banner:js=$\'#!/usr/bin/env node\\n// Claude Code v2.1.88 (built from source)\\n// Copyright (c) Anthropic PBC. All rights reserved.\\n\'', + '--allow-overwrite', + '--log-level=warning', + '--sourcemap', + ].join(' '), { + cwd: ROOT, + stdio: 'inherit', + shell: true, + }) + + const size = (await stat(OUT)).size + console.log(`\n✅ Build succeeded: ${OUT}`) + console.log(` Size: ${(size / 1024 / 1024).toFixed(1)}MB`) + console.log(` Usage: node ${OUT} --version`) +} catch (e) { + console.error('\n❌ Build still has errors. Run again to iterate:') + console.error(' node scripts/stub-modules.mjs') +} diff --git a/scripts/transform.mjs b/scripts/transform.mjs new file mode 100644 index 0000000..c9dd120 --- /dev/null +++ b/scripts/transform.mjs @@ -0,0 +1,143 @@ +#!/usr/bin/env node +/** + * build.mjs — Build Claude Code from source using esbuild + * + * Strategy: + * 1. Copy src/ → build-src/ (working copy) + * 2. Transform all `from 'bun:bundle'` imports → `from './stubs/bun-bundle'` + * 3. Inject MACRO globals via esbuild --define (replaces MACRO.X at compile time) + * 4. Bundle with esbuild into a single cli.js + */ + +import { readdir, readFile, writeFile, mkdir, cp, rm } from 'node:fs/promises' +import { join, relative, dirname } from 'node:path' +import { execSync } from 'node:child_process' +import { fileURLToPath } from 'node:url' + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const ROOT = join(__dirname, '..') + +const VERSION = '2.1.88' + +// ── Step 1: Clean & Create build directory ───────────────────────────────── + +const BUILD_DIR = join(ROOT, 'build-src') +await rm(BUILD_DIR, { recursive: true, force: true }) +await mkdir(BUILD_DIR, { recursive: true }) + +// Copy src/ → build-src/ +await cp(join(ROOT, 'src'), join(BUILD_DIR, 'src'), { recursive: true }) +// Copy stubs/ → build-src/stubs/ +await cp(join(ROOT, 'stubs'), join(BUILD_DIR, 'stubs'), { recursive: true }) + +console.log('✅ Copied source to build-src/') + +// ── Step 2: Transform imports ────────────────────────────────────────────── + +async function* walkFiles(dir) { + for (const entry of await readdir(dir, { withFileTypes: true })) { + const full = join(dir, entry.name) + if (entry.isDirectory()) yield* walkFiles(full) + else if (entry.name.endsWith('.ts') || entry.name.endsWith('.tsx')) yield full + } +} + +let transformCount = 0 + +for await (const file of walkFiles(join(BUILD_DIR, 'src'))) { + let content = await readFile(file, 'utf8') + let modified = false + + // Replace bun:bundle import with our stub + if (content.includes("from 'bun:bundle'") || content.includes('from "bun:bundle"')) { + const rel = relative(dirname(file), join(BUILD_DIR, 'stubs', 'bun-bundle.ts')) + const importPath = rel.startsWith('.') ? rel : './' + rel + content = content.replace( + /import\s*\{\s*feature\s*\}\s*from\s*['"]bun:bundle['"]/g, + `import { feature } from '${importPath.replace(/\.ts$/, '.js')}'` + ) + modified = true + } + + if (modified) { + await writeFile(file, content, 'utf8') + transformCount++ + } +} + +console.log(`✅ Transformed ${transformCount} files (bun:bundle → stub)`) + +// ── Step 3: Create entrypoint wrapper ────────────────────────────────────── + +const ENTRY = join(BUILD_DIR, 'entry.ts') +await writeFile(ENTRY, ` +// MACRO globals — normally injected by Bun's --define at compile time +// We inject them here as globals so MACRO.X references resolve +const MACRO = { + VERSION: '${VERSION}', + BUILD_TIME: '', + FEEDBACK_CHANNEL: 'https://github.com/anthropics/claude-code/issues', + ISSUES_EXPLAINER: 'https://github.com/anthropics/claude-code/issues/new/choose', + FEEDBACK_CHANNEL_URL: 'https://github.com/anthropics/claude-code/issues', + ISSUES_EXPLAINER_URL: 'https://github.com/anthropics/claude-code/issues/new/choose', + NATIVE_PACKAGE_URL: '@anthropic-ai/claude-code', + PACKAGE_URL: '@anthropic-ai/claude-code', + VERSION_CHANGELOG: '', +} + +// Make it global +globalThis.MACRO = MACRO + +// Now load the real entrypoint +import './src/entrypoints/cli.tsx' +`) + +console.log('✅ Created entry wrapper with MACRO injection') + +// ── Step 4: esbuild bundle ───────────────────────────────────────────────── + +const OUT_FILE = join(ROOT, 'dist', 'cli.js') + +try { + // Check if esbuild is available + execSync('npx esbuild --version', { stdio: 'pipe' }) +} catch { + console.log('\n📦 Installing esbuild...') + execSync('npm install --save-dev esbuild', { cwd: ROOT, stdio: 'inherit' }) +} + +console.log('\n🔨 Bundling with esbuild...') + +try { + execSync(`npx esbuild \\ + "${ENTRY}" \\ + --bundle \\ + --platform=node \\ + --target=node18 \\ + --format=esm \\ + --outfile="${OUT_FILE}" \\ + --banner:js='#!/usr/bin/env node' \\ + --define:process.env.USER_TYPE='"external"' \\ + --define:process.env.CLAUDE_CODE_VERSION='"${VERSION}"' \\ + --external:bun:ffi \\ + --external:bun:bundle \\ + --allow-overwrite \\ + --log-level=info \\ + --sourcemap \\ + ${process.argv.includes('--minify') ? '--minify' : ''}`, { + cwd: ROOT, + stdio: 'inherit', + shell: true + }) +} catch (e) { + console.error('\n❌ esbuild failed. This is expected — the source has complex Bun-specific patterns.') + console.error(' The source is primarily meant for reading/analysis, not recompilation.') + console.error('\n To proceed with fixing, you would need to:') + console.error(' 1. Install Bun runtime (bun.sh)') + console.error(' 2. Create a bun build script that uses Bun.defineMacro / feature() natively') + console.error(' 3. Or manually resolve each compile-time intrinsic') + process.exit(1) +} + +console.log(`\n✅ Build complete: ${OUT_FILE}`) +console.log(` Run with: node ${OUT_FILE}`) diff --git a/stubs/bun-bundle.ts b/stubs/bun-bundle.ts new file mode 100644 index 0000000..47933e9 --- /dev/null +++ b/stubs/bun-bundle.ts @@ -0,0 +1,4 @@ +// Stub for bun:bundle — feature() is compile-time in Bun; replaced by build script +export function feature(_flag: string): boolean { + return false +} diff --git a/stubs/global.d.ts b/stubs/global.d.ts new file mode 100644 index 0000000..ade1c9b --- /dev/null +++ b/stubs/global.d.ts @@ -0,0 +1,11 @@ +// Global type for MACRO compile-time constants +// These are normally injected by Bun's bundler via --define at compile time +declare const MACRO: { + VERSION: string + BUILD_TIME: string + FEEDBACK_CHANNEL: string + ISSUES_EXPLAINER: string + NATIVE_PACKAGE_URL: string + PACKAGE_URL: string + VERSION_CHANGELOG: string +} diff --git a/stubs/macros.d.ts b/stubs/macros.d.ts new file mode 100644 index 0000000..6c10139 --- /dev/null +++ b/stubs/macros.d.ts @@ -0,0 +1,15 @@ +/** + * Compile-time macros injected by Bun's bundler. + * These are replaced with string literals during bundling. + * For our source build, we provide runtime values. + */ + +declare const MACRO: { + VERSION: string + BUILD_TIME: string + FEEDBACK_CHANNEL: string + ISSUES_EXPLAINER: string + NATIVE_PACKAGE_URL: string + PACKAGE_URL: string + VERSION_CHANGELOG: string +} diff --git a/stubs/macros.ts b/stubs/macros.ts new file mode 100644 index 0000000..fe38d83 --- /dev/null +++ b/stubs/macros.ts @@ -0,0 +1,20 @@ +// Global compile-time MACRO constants +// In the real Bun build, these are injected via --define at compile time. +// Here we provide runtime values matching the published v2.1.88. +declare global { + const MACRO: { + VERSION: string + BUILD_TIME: string + FEEDBACK_CHANNEL: string + ISSUES_EXPLAINER: string + ISSUES_EXPLAINER_URL: string + FEEDBACK_CHANNEL_URL: string + NATIVE_PACKAGE_URL: string | null + PACKAGE_URL: string + VERSION_CHANGELOG: string + } +} + +// This is never actually executed — the global is set in the entrypoint wrapper. +// But we need it so TypeScript doesn't complain about `MACRO` being undeclared. +export {} diff --git a/tools/OverflowTestTool/OverflowTestTool.js b/tools/OverflowTestTool/OverflowTestTool.js new file mode 100644 index 0000000..c91bcd0 --- /dev/null +++ b/tools/OverflowTestTool/OverflowTestTool.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function OverflowTestTool() {} +export const OverflowTestTool = () => {} diff --git a/tools/TerminalCaptureTool/prompt.js b/tools/TerminalCaptureTool/prompt.js new file mode 100644 index 0000000..4b8a7ee --- /dev/null +++ b/tools/TerminalCaptureTool/prompt.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function prompt() {} +export const prompt = () => {} diff --git a/tools/TungstenTool/TungstenTool.js b/tools/TungstenTool/TungstenTool.js new file mode 100644 index 0000000..d6e5f85 --- /dev/null +++ b/tools/TungstenTool/TungstenTool.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function TungstenTool() {} +export const TungstenTool = () => {} diff --git a/tools/VerifyPlanExecutionTool/constants.js b/tools/VerifyPlanExecutionTool/constants.js new file mode 100644 index 0000000..ffae201 --- /dev/null +++ b/tools/VerifyPlanExecutionTool/constants.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function constants() {} +export const constants = () => {} diff --git a/tools/WorkflowTool/constants.js b/tools/WorkflowTool/constants.js new file mode 100644 index 0000000..ffae201 --- /dev/null +++ b/tools/WorkflowTool/constants.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function constants() {} +export const constants = () => {} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..afd9727 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "jsx": "react-jsx", + "outDir": "dist", + "rootDir": "src", + "baseUrl": ".", + "paths": { + "bun:bundle": ["stubs/bun-bundle.ts"], + "src/*": ["src/*"] + }, + "types": ["node"], + "lib": ["ES2022", "DOM"], + "allowImportingTsExtensions": false, + "noEmit": false + }, + "include": [ + "src/**/*", + "stubs/**/*" + ], + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/types/connectorText.js b/types/connectorText.js new file mode 100644 index 0000000..ed536c7 --- /dev/null +++ b/types/connectorText.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function connectorText() {} +export const connectorText = () => {} diff --git a/utils/attributionHooks.js b/utils/attributionHooks.js new file mode 100644 index 0000000..89e492e --- /dev/null +++ b/utils/attributionHooks.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function attributionHooks() {} +export const attributionHooks = () => {} diff --git a/utils/systemThemeWatcher.js b/utils/systemThemeWatcher.js new file mode 100644 index 0000000..d4b07ba --- /dev/null +++ b/utils/systemThemeWatcher.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function systemThemeWatcher() {} +export const systemThemeWatcher = () => {} diff --git a/utils/udsClient.js b/utils/udsClient.js new file mode 100644 index 0000000..eacc079 --- /dev/null +++ b/utils/udsClient.js @@ -0,0 +1,3 @@ +// Auto-generated stub +export default function udsClient() {} +export const udsClient = () => {}