CLAUDE.md@packages/pm ยท diff
git:20260709.434e49a to git:20260731.f7d38d0
45 added, 58 removed. Audit B to B.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
- This is a CLI utility built with Bun and TypeScript. Bun is used as the JavaScript runtime, package manager, bundler, and test runner.
+ This is a CLI utility built with TypeScript. It is **portable** and runs under both Bun and Node.js/Electron. Bun remains the development toolchain (package manager, task runner, test runner, and bundler), but the application code uses only Node.js built-ins so it can be packaged for end users without requiring the Bun runtime.
## Runtime & Tooling
- **Always use Bun instead of Node.js, npm, pnpm, or other tools:**
+ **Bun is used for development only:**
- - Runtime: `bun <file>` (not `node` or `ts-node`)
- - Package management: `bun install` (not `npm install` or `yarn install`)
- - Scripts: `bun run <script>` (not `npm run`)
- - Testing: `bun test` (not `jest` or `vitest`)
- - Bundling: `bun build <file>` (not `webpack` or `vite`)
+ - Package management: `bun install` (not npm install or yarn install)
+ - Scripts: `bun run <script>` (not npm run)
+ - Testing: `bun test` (not jest or vitest)
+ - Bundling: `bun build <file>` (not webpack or vite)
+ - Local execution: `bun run index.ts`
- ## Development Commands
+ **The application code itself runs under plain Node.js or Electron:**
- - **Install dependencies**: `bun install`
- - **Run the application**: `bun run index.ts`
- - **Run with hot reload**: `bun --hot index.ts`
- - **Type checking**: Use TypeScript compiler with strict mode enabled
+ - File I/O: `node:fs/promises` (readFile, writeFile, access, mkdir) via `lib/runtime/fs.ts`
+ - Shell commands: Avoid `Bun.$`; use `node:fs/promises` mkdir or `child_process` if necessary
+ - Environment variables: `process.env` (no dotenv dependency)
+ - Command-line arguments: `process.argv` via `lib/runtime/args.ts`
+ - Path operations: `node:path` and `node:url` via `lib/runtime/path.ts`
+ - Stdin prompts: `node:readline` via `lib/runtime/stdin.ts`
+ - Process management: `process.exit()`, `process.stdout`, `process.stderr`, `process.stdin`
- ## Bun-Specific APIs for CLI Development
+ ## CLI Development Patterns
- When writing code for this CLI utility, prefer Bun's built-in APIs over npm packages:
+ ### File Operations
- - **File I/O**: `Bun.file()` and `Bun.write()` instead of `node:fs` readFile/writeFile
- - **Shell commands**: `Bun.$\`command\`` instead of `execa` or `child_process`
- - **Environment variables**: Automatically loaded from `.env` (no need for `dotenv`)
- - **Command-line arguments**: `Bun.argv` or `process.argv`
- - **Process management**: `process.exit()`, `process.stdout`, `process.stderr`, `process.stdin`
- - **Path operations**: Use `node:path` for cross-platform path handling
- - **SQLite** (if needed): `bun:sqlite` instead of `better-sqlite3`
+ Always use the centralized runtime helpers rather than `Bun.file()` or `Bun.write()`:
- ## TypeScript Configuration
+ ```ts
+ import { readFile, writeFile, pathExists, mkdir } from "./runtime/fs.js";
- The project uses strict TypeScript settings:
- - Target: ESNext
- - Module: Preserve (bundler mode)
- - JSX: react-jsx
- - Strict mode enabled with additional checks:
- - `noFallthroughCasesInSwitch`
- - `noUncheckedIndexedAccess`
- - `noImplicitOverride`
+ const content = await readFile("path/to/file.txt");
+ await writeFile("output.txt", content);
+ const exists = await pathExists("path/to/check");
+ await mkdir("new/dir");
+ ```
- ## CLI Development Patterns
+ ### Path Resolution
- ### Reading User Input
+ Replace `import.meta.dir` with the portable `getModuleDir(import.meta.url)`:
+
```ts
- // Read from stdin
- const input = await Bun.stdin.text()
+ import { getModuleDir } from "./runtime/path.js";
- // Or line by line
- for await (const line of Bun.stdin.stream()) {
- console.log(line)
- }
+ const __dirname = getModuleDir(import.meta.url);
```
- ### File Operations
- ```ts
- // Reading files
- const file = Bun.file("path/to/file.txt")
- const contents = await file.text()
-
- // Writing files
- await Bun.write("output.txt", "content")
+ ### Command-line Arguments
- // Check if file exists
- const exists = await file.exists()
- ```
+ Use the args helper instead of `Bun.argv`:
- ### Shell Commands
```ts
- // Execute shell commands with Bun's shell
- const result = await Bun.$`ls -la`
- console.log(result.stdout.toString())
+ import { getArgs } from "./runtime/args.js";
+
+ const args = getArgs(); // equivalent to process.argv.slice(2)
```
- ### Command-line Arguments
+ ### Reading User Input
+
+ Use the cross-platform stdin helper (works in Node, Bun, and Electron):
+
```ts
- // Access arguments
- const args = Bun.argv.slice(2) // Skip 'bun' and script name
+ import { askConfirm } from "./runtime/stdin.js";
+
+ const confirmed = await askConfirm("Continue?");
```
### Exit Codes
+
Use appropriate exit codes for success (0) and errors (non-zero).
- ## Additional Resources
+ ## Build Output
- For detailed Bun API documentation, refer to `node_modules/bun-types/docs/**/*.md`.
+ The `bun run build` command targets **Node.js** (`--target=node`) so the resulting `dist/index.js` runs under plain Node.js without Bun installed. External dependencies (`ink`, `react`, `ink-scroll-view`) are left as externals and resolved at runtime.