feat(cli): Bun-first CLI migration with 7 commands and comprehensive test suite#259
Open
darrenhinde wants to merge 5 commits intomainfrom
Open
feat(cli): Bun-first CLI migration with 7 commands and comprehensive test suite#259darrenhinde wants to merge 5 commits intomainfrom
darrenhinde wants to merge 5 commits intomainfrom
Conversation
- Replace fs-extra with Bun.file/Bun.write/node:fs/promises across all 9 source files - Fix --help fast-path so all 8 subcommands are visible - Replace tsup/tsx/vitest with bun build/bun run/bun:test - Replace __dirname with import.meta.dir; use JSON import assertion for version - Fix hardcoded OAC_VERSION in add.ts; add hashesMatch import to status.ts - Replace computeFileHash with Bun.file().bytes() in sha256.ts - Rename checkNodeVersion → checkBunVersion; parallelise doctor checks - Fix TypeScript void-inference errors in update.ts, list.ts, status.ts by replacing .catch() with let/try-catch where result is used downstream - Add ManifestError named error class; remove unsafe type casts - Add 43 bun:test unit tests (sha256, manifest, installer, version) — 0 failures
Critical bug fixes:
- ide-detect.ts: replace Bun.file(dir).exists() with stat().isDirectory()
for all directory checks — Bun.file().exists() always returns false for
directories, breaking Cursor/Windsurf/OpenCode/Claude detection entirely
- bundled.ts: add registry.json exclusion anchor to findPackageRoot() to
prevent monorepo root from matching before the CLI package root
Standards cleanup (§4.1, §5.1, §6.1, §15.3, §21.1):
- status.ts: parallelise findModifiedFiles + detectIdes with Promise.all
- apply.ts: fix duplicate warn/limit messages; remove else after return in
reportWarnings; remove redundant mkdir before Bun.write
- version.ts: remove unnecessary (pkgJson as {version?:string}) cast
- manifest.ts: remove redundant mkdir before Bun.write; remove as unknown cast
- installer.ts: remove redundant mkdir calls before Bun.write throughout
- add.ts: add comment explaining why node:fs/promises rm is used
Tests (43 → 142, +99 new tests across 4 new files):
- ide-detect.test.ts: 26 tests covering all 4 IDEs, both claude indicators,
detectIdes parallel, isIdePresent — directly validates the directory fix
- bundled.test.ts: 27 tests for classifyBundledFile, findPackageRoot,
listBundledFiles, getBundledFilePath, bundledFileExists
- config.test.ts: 25 tests for readConfig/writeConfig round-trips,
createDefaultConfig, mergeConfig, isYoloMode, isAutoBackup
- installer-update.test.ts: 14 tests covering all 5 updateFiles decision
branches (install/update/skip/yolo/dry-run) plus isProjectRoot
- sha256.test.ts: +4 tests for empty file, large file, binary content
…solution - Remove duplicate --dry-run/--yolo/--verbose from parent program; Commander.js global option stealing caused all safety flags to be silently dropped in every subcommand action callback - Fix isProjectRoot() to use stat() for .git detection; Bun.file().exists() returns false for directories, breaking oac init in standard git repos - Add OAC_PACKAGE_ROOT env var override to getPackageRoot() for dev/monorepo mode; registry.json heuristic excluded the repo root causing oac init/add/update to throw when run from source - Fix build script: remove --banner flag that caused double shebang in dist/index.js - Rewrite bin/oac.js to invoke bun instead of node (dist is bun-only target) - Refactor installer.ts let accumulators to const using Promise.all + reduce - Add MVP planning docs (00-MVP-PLAN.md, master synthesis, project breakdown)
The get_registry_key() function was always adding 's' to the type, causing 'contexts' to become 'contextss' which doesn't exist in registry.json. Now handles: - Singular forms: context → contexts, agent → agents, skill → skills - Plural forms: contexts → contexts (unchanged), agents → agents - Config stays singular - Fallback for any type ending in 's' Fixes #257
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces a complete Bun-first CLI implementation for the OAC (OpenAgents Control) package, migrating from Node.js/tsup/vitest to Bun-native tooling.
Changes Included
🚀 Major Features
bun build,bun run, andbun:testoac init- Initialize OAC in a project with bundled filesoac update- Update with SHA256-based change detectionoac add/remove- Add/remove specific components from registryoac apply- Generate IDE-specific files (Cursor, Claude, Windsurf)oac doctor- Health checks and diagnosticsoac list- Show installed componentsoac status- One-screen summary🔧 Technical Improvements
fs-extradependency - using Bun APIs +node:fs/promises__dirnamewithimport.meta.dir(Bun-native)bun:testfrom vitest📦 Package Structure
✅ Exit Criteria Met
bun run src/index.ts --versionworksbun run src/index.ts --helpshows all 7 subcommandsbun run src/index.ts doctorruns without crashingbun buildsucceedstsc --noEmitpassesfs-extrain source__dirnamein sourcevitestortsupin dependencies📚 Documentation
Testing
bun:testRelated
Note: The
.cursorrules.bakfile in the working directory is a temporary backup and not included in this PR.