-
Notifications
You must be signed in to change notification settings - Fork 0
feat(cli): add npm package wrapper for Codra CLI #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| bin/native/ |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # @codra/cli | ||
|
|
||
| npm package wrapper for the [Codra](https://github.com/talocode/codra) Rust CLI (`codra-cli` crate). Installs a global `codra` command that forwards to the native binary for your platform. | ||
|
|
||
| ## Installation (coming soon) | ||
|
|
||
| This package is **not published to npm yet**. When it is: | ||
|
|
||
| ```bash | ||
| npm install -g @codra/cli | ||
| codra --help | ||
| ``` | ||
|
|
||
| ## Local development | ||
|
|
||
| From the monorepo root (or this package directory): | ||
|
|
||
| ```bash | ||
| cd packages/codra-npm-cli | ||
| npm run build | ||
| node bin/codra.js --help | ||
| node bin/codra.js run --task summarize-context --jsonl | ||
| npm test | ||
| ``` | ||
|
|
||
| `npm run build` runs `cargo build -p codra-cli --release` and copies the release binary into `bin/native/<platform>-<arch>/`. | ||
|
|
||
| ## Supported commands | ||
|
|
||
| Same as the Rust CLI: | ||
|
|
||
| ```bash | ||
| codra run --task review-pr --jsonl | ||
| codra run --task explain-issue --jsonl | ||
| codra run --task summarize-context --jsonl | ||
| ``` | ||
|
|
||
| Invalid tasks exit non-zero. With `--jsonl`, failures emit `codra.run.failed`. | ||
|
|
||
| ## GitHub context (optional) | ||
|
|
||
| When running in GitHub Actions or with fixtures: | ||
|
|
||
| | Variable | Purpose | | ||
| |----------|---------| | ||
| | `GITHUB_ACTIONS` | Detect Actions runtime | | ||
| | `GITHUB_REPOSITORY` | Repository slug | | ||
| | `GITHUB_EVENT_NAME` | Workflow event name | | ||
| | `GITHUB_EVENT_PATH` | Path to event JSON payload | | ||
| | `GITHUB_TOKEN` | Optional API enrichment (never printed) | | ||
|
|
||
| ## Security | ||
|
|
||
| - No AI provider API calls in this CLI layer yet. | ||
| - Does not print `GITHUB_TOKEN` or other secrets in output. | ||
| - Local-first CLI foundation; wraps the existing Rust binary unchanged. | ||
|
|
||
| ## License | ||
|
|
||
| MIT — see repository [LICENSE](https://github.com/talocode/codra/blob/main/LICENSE). |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| #!/usr/bin/env node | ||
| 'use strict'; | ||
|
|
||
| const { spawnSync } = require('child_process'); | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
|
|
||
| const SUPPORTED_PLATFORMS = new Set([ | ||
| 'linux-arm64', | ||
| 'linux-x64', | ||
| 'darwin-arm64', | ||
| 'darwin-x64', | ||
| 'win32-x64', | ||
| ]); | ||
|
|
||
| function platformArchKey() { | ||
| const platform = process.platform; | ||
| const arch = process.arch; | ||
| return `${platform}-${arch}`; | ||
| } | ||
|
|
||
| function binaryFileName() { | ||
| return process.platform === 'win32' ? 'codra.exe' : 'codra'; | ||
| } | ||
|
|
||
| function resolveNativeBinary() { | ||
| const key = platformArchKey(); | ||
| const name = binaryFileName(); | ||
| const nativePath = path.join(__dirname, 'native', key, name); | ||
|
|
||
| if (!fs.existsSync(nativePath)) { | ||
| const supported = [...SUPPORTED_PLATFORMS].sort().join(', '); | ||
| process.stderr.write( | ||
| `codra: native binary not found for ${key}.\n` + | ||
| `Expected: ${nativePath}\n` + | ||
| `Supported platform keys (when built): ${supported}\n` + | ||
| `Build the package for this machine: npm run build (from packages/codra-npm-cli)\n`, | ||
| ); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| return nativePath; | ||
| } | ||
|
|
||
| function main() { | ||
| const binary = resolveNativeBinary(); | ||
| const args = process.argv.slice(2); | ||
|
|
||
| const result = spawnSync(binary, args, { | ||
| stdio: 'inherit', | ||
| env: process.env, | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| process.stderr.write(`codra: failed to run native binary: ${result.error.message}\n`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| if (result.signal) { | ||
| process.exit(1); | ||
| } | ||
|
|
||
| process.exit(result.status === null ? 1 : result.status); | ||
| } | ||
|
|
||
| main(); |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| { | ||
| "name": "@codra/cli", | ||
| "version": "0.1.0", | ||
| "description": "Codra CLI for local-first AI coding agent workflows", | ||
| "license": "MIT", | ||
| "author": "Talocode", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/talocode/codra", | ||
| "directory": "packages/codra-npm-cli" | ||
| }, | ||
| "bin": { | ||
| "codra": "./bin/codra.js" | ||
| }, | ||
| "files": [ | ||
| "bin/", | ||
| "README.md", | ||
| "package.json" | ||
| ], | ||
| "scripts": { | ||
| "build": "node scripts/build.js", | ||
| "test": "node scripts/test.js", | ||
| "pack:dry": "npm pack --dry-run" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "engines": { | ||
| "node": ">=18" | ||
| } | ||
| } |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| 'use strict'; | ||
|
|
||
| const { execSync } = require('child_process'); | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
|
|
||
| const packageRoot = path.resolve(__dirname, '..'); | ||
| const repoRoot = path.resolve(packageRoot, '../..'); | ||
|
|
||
| function platformArchKey() { | ||
| return `${process.platform}-${process.arch}`; | ||
| } | ||
|
|
||
| function binaryFileName() { | ||
| return process.platform === 'win32' ? 'codra.exe' : 'codra'; | ||
| } | ||
|
|
||
| function main() { | ||
| console.log(`[build] repo root: ${repoRoot}`); | ||
| console.log('[build] cargo build -p codra-cli --release'); | ||
|
|
||
| try { | ||
| execSync('cargo build -p codra-cli --release', { | ||
| cwd: repoRoot, | ||
| stdio: 'inherit', | ||
| }); | ||
| } catch { | ||
| console.error('[build] cargo build failed'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| const key = platformArchKey(); | ||
| const name = binaryFileName(); | ||
| const src = path.join(repoRoot, 'target', 'release', name); | ||
| const destDir = path.join(packageRoot, 'bin', 'native', key); | ||
| const dest = path.join(destDir, name); | ||
|
|
||
| if (!fs.existsSync(src)) { | ||
| console.error(`[build] release binary missing: ${src}`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| fs.mkdirSync(destDir, { recursive: true }); | ||
| fs.copyFileSync(src, dest); | ||
|
|
||
| if (process.platform !== 'win32') { | ||
| fs.chmodSync(dest, 0o755); | ||
| } | ||
|
|
||
| console.log(`[build] packaged ${key}: ${dest}`); | ||
| } | ||
|
|
||
| main(); | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| 'use strict'; | ||
|
|
||
| const { spawnSync } = require('child_process'); | ||
| const path = require('path'); | ||
|
|
||
| const packageRoot = path.resolve(__dirname, '..'); | ||
| const wrapper = path.join(packageRoot, 'bin', 'codra.js'); | ||
|
|
||
| function run(args, { expectFail = false } = {}) { | ||
| const label = ['node', 'bin/codra.js', ...args].join(' '); | ||
| console.log(`[test] ${label}`); | ||
|
|
||
| const result = spawnSync(process.execPath, [wrapper, ...args], { | ||
| cwd: packageRoot, | ||
| encoding: 'utf8', | ||
| env: process.env, | ||
| }); | ||
|
|
||
| const stdout = result.stdout || ''; | ||
| const stderr = result.stderr || ''; | ||
| const exitCode = result.status ?? 1; | ||
|
|
||
| if (result.error) { | ||
| console.error(`[test] spawn error: ${result.error.message}`); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| if (expectFail) { | ||
| if (exitCode === 0) { | ||
| console.error('[test] expected non-zero exit'); | ||
| process.exit(1); | ||
| } | ||
| } else if (exitCode !== 0) { | ||
| console.error(`[test] unexpected exit ${exitCode}`); | ||
| if (stderr) console.error(stderr); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| return { stdout, stderr, exitCode }; | ||
| } | ||
|
|
||
| function assertIncludes(haystack, needle, label) { | ||
| if (!haystack.includes(needle)) { | ||
| console.error(`[test] missing ${label}: ${needle}`); | ||
| process.exit(1); | ||
| } | ||
| } | ||
|
|
||
| function main() { | ||
| const help = run(['--help']); | ||
| assertIncludes(help.stdout + help.stderr, 'codra', 'help output'); | ||
|
|
||
| const valid = run(['run', '--task', 'summarize-context', '--jsonl']); | ||
| assertIncludes(valid.stdout, 'codra.run.started', 'run started event'); | ||
| assertIncludes(valid.stdout, 'codra.run.completed', 'run completed event'); | ||
|
|
||
| const invalid = run(['run', '--task', 'not-a-real-task', '--jsonl'], { | ||
| expectFail: true, | ||
| }); | ||
| assertIncludes(invalid.stdout, 'codra.run.failed', 'run failed event'); | ||
|
|
||
| const combined = invalid.stdout + invalid.stderr; | ||
| if (/ghp_[A-Za-z0-9]+/i.test(combined) || /github_pat_/i.test(combined)) { | ||
| console.error('[test] output appears to contain a token pattern'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| console.log('[test] all checks passed'); | ||
| } | ||
|
|
||
| main(); |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When this single
@codra/clipackage is packed afternpm run buildon one machine, only that machine'sbin/native/<platform>-<arch>/codrais copied into the tarball; I checkednpm pack --dry-runand it only includes files present underbin/. On any other supported platform, the wrapper computes a different key and exits with “native binary not found”, so a package published from a Linux CI runner would not work for macOS or Windows global installs unless the release process adds all platform binaries or uses per-platform optional packages/os/cpuconstraints.Useful? React with 👍 / 👎.