···11+# Clink Feature Gaps Found During @bomb.sh/tools Migration
22+33+## Already Implemented (in this migration)
44+55+These changes were made directly to clink during the migration and need to be committed upstream.
66+77+### 1. `remaining` args in HandlerContext
88+**Problem:** The trie walker computes remaining/unconsumed args but dropped them before calling the handler. CLI tools commonly need to pass through unknown flags to underlying commands (e.g., `bsh build --dts` passes `--dts` through to tsdown).
99+1010+**Changes made:**
1111+- `src/api.ts`: Added `remaining: string[]` to `HandlerContext` type, `defineCommand` handler signature, and `exec()` function
1212+- `src/framework/build/manifest.ts`: Updated `generateBin()` to pass `remaining` array to `command.handler()`
1313+- `src/commands/exec.ts`: Rewrote to avoid parsing flags (they belong to target command), threads raw passthrough args into `remaining`
1414+- `src/commands/index.ts`: Passes `match.remaining` through to `exec()`
1515+1616+### 2. Public `tools.exec` API (powered by tinyexec)
1717+**Problem:** The `Exec` class was internal-only (used by `git` and `pm`). Command handlers had no way to shell out to arbitrary binaries.
1818+1919+**Changes made:**
2020+- `src/framework/tools/exec.ts`: Replaced custom `spawn`-based implementation with `tinyexec`. Added automatic `node_modules/.bin` PATH prepending (like `zx`'s `preferLocal`). Added `stream()` method returning `AsyncIterable<string>` for line-by-line output processing.
2121+- `src/framework/tools/index.ts`: Added `exec: Exec` to public `Tools` type and lazy loader
2222+- `package.json`: Added `tinyexec` dependency
2323+2424+### 3. Flag passthrough in `clink exec`
2525+**Problem:** `clink exec format --check` parsed `--check` via `@bomb.sh/args`, consuming it as an option instead of passing it through to the target command. This meant passthrough flags were silently swallowed.
2626+2727+**Changes made:**
2828+- `src/commands/exec.ts`: Removed `@bomb.sh/args` parsing. Now splits argv into positional segments (for routing) and everything else (passthrough). Flags are never parsed — they belong to the target command.
2929+3030+## Remaining Gaps (nice-to-have)
3131+3232+### 4. Binary path resolution helper
3333+**Problem:** CLI tools that wrap other CLI tools need to resolve `.bin` paths relative to their own package (not the consumer's project). After bundling, `import.meta.url`-based resolution may point to the wrong location.
3434+3535+**Current workaround:** The new `Exec` class automatically prepends `node_modules/.bin` to PATH, so bare command names (`oxlint`, `tsdown`, etc.) resolve correctly. This covers the common case.
3636+3737+**Edge case not covered:** When a CLI package needs binaries from its *own* `node_modules` (not the consumer's), the PATH prepending uses `session.cwd` which points to the consumer's project. For the tools use case this works because the binaries are direct dependencies, but a more robust solution would walk up from the CLI package's install location.
3838+3939+**Proposed API (if needed):**
4040+```typescript
4141+// Resolve .bin path relative to a specific package
4242+const oxlint = tools.exec.bin('oxlint');
4343+await tools.exec.runOrThrow(oxlint, args);
4444+```
4545+4646+### 5. No-command help text
4747+**Problem:** Running `bsh` with no arguments shows `Unknown command:` and exits. The old implementation listed available commands. The generated `bin.js` has no awareness of what commands exist for help text.
4848+4949+**Proposed:** Generate a help handler in `bin.js` that lists available commands from the trie when no args are provided.