feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(cli): add --input-json for passing options as JSON - #232

Merged
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support
Apr 24, 2026
Merged

feat(cli): add --input-json for passing options as JSON#232
wyattjoh merged 7 commits into
mainfrom
rafa-thayto/json-support

Conversation

@rafa-thayto

@rafa-thaytorafa-thayto commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds a global --input-json <json|@file> flag. Keys convert from camelCase/snake_case to kebab-case and expand into argv flags before Commander parses, so any existing flag can come from JSON instead of a shell-escaped string.
  • Built for AI-agent and scripted invocations where passing a JSON object is cleaner than composing a command line.

Behavior

JSONExpansion
"str" / number--flag <value>
true--flag
false / nullomitted
["a","b"]--flag a --flag b (empty arrays omit)
{…} (nested)rejected — invalid_json, exit 2

Placement. Put --input-json after the leaf subcommand. Before a subcommand, expanded flags land on the root program, so only root options (--mode, --verbose) work there — subcommand flags like --json / --app error as unknown. Explicit flags after --input-json override its values (last-flag-wins).

Flags only. Positional arguments (e.g. the <name> in clerk apps create <name>, the path in clerk api <path>) cannot come from JSON — pass them on the command line as usual.

clerk init --input-json '{"framework":"next","yes":true}'
clerk config pull --input-json '{"keys":["auth_email","session"]}'
clerk init --input-json @init-opts.json

Test plan

  • bun run format:check, bun run lint, bun run typecheck
  • bun run test — 81 files, all passing
  • 41 unit tests (lib/input-json.test.ts) cover key conversion, expansion rules, @file reads, error paths
  • 25 integration tests (test/integration/input-json.test.ts) cover init, doctor, api (positional args), apps list, config pull/patch/schema (nested subcommands + array flags), precedence, and placement (both working and erroring cases)
  • Changeset: clerk minor bump

Docs

  • New --input-json section in skills/clerk/references/agent-mode.md (expansion table, placement rule, error codes).
  • Pointer in skills/clerk/SKILL.md.
  • Root README.md help block regenerated.

@changeset-bot

changeset-botBot commented Apr 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 42b0a88

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
NameType
clerkMinor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from 80caea3 to 82a71cdCompareApril 23, 2026 20:41
@rafa-thayto
rafa-thayto marked this pull request as ready for review April 23, 2026 20:50
@coderabbitai

coderabbitaiBot commented Apr 23, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@wyattjoh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 48 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 48 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4ac20d2c-71fd-44cd-b8e4-aa96f14ebd66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e79e2a and 42b0a88.

📒 Files selected for processing (4)
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • test/e2e/lib/dev-server.ts
  • test/e2e/lib/fixture-test.ts
📝 Walkthrough

Walkthrough

This pull request introduces a --input-json CLI flag that enables passing command options via JSON input. The feature accepts inline JSON objects, file references using @path/to/file.json, or stdin via -. JSON keys are converted from camelCase/snake_case to kebab-case flag names. Value handling expands arrays into repeated flags, emits bare flags for boolean true, and omits flags for false and null values. The implementation integrates into the argv preprocessing pipeline before Commander's argument parsing and includes comprehensive unit and integration test coverage alongside documentation updates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Key areas for review

  • CLI integration logic (packages/cli-core/src/cli-program.ts): The refactored runProgram function introduces argv preprocessing via resolveArgv() helper. Verify that the new control flow correctly handles both test-provided args and process.argv paths, and that the type changes to the from option are consistent.

  • JSON parsing and expansion (packages/cli-core/src/lib/input-json.ts): Review the expandInputJson and toKebabCase implementations for correctness of JSON-to-flag conversion logic, file/stdin handling, and error classification. Confirm that flag placement (splice vs. append) properly preserves argument precedence.

  • Test coverage: The unit and integration test files are extensive (+369 and +270 lines respectively). Spot-check representative test cases to validate coverage of primary paths, edge cases (empty objects/arrays, nested objects, missing files), and error scenarios.

  • Documentation alignment: Verify that agent-mode documentation in skills/clerk/references/agent-mode.md accurately reflects implementation behavior, particularly around placement constraints and error exit codes.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 52.94% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Title check✅ PassedThe title clearly and specifically summarizes the main feature: adding a --input-json flag for passing options as JSON, which is the core objective of the PR.
Description check✅ PassedThe description comprehensively explains the feature, including behavior, placement rules, examples, test coverage, and documentation updates—all directly related to the changeset.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@wyattjohwyattjoh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think it's possible for us to support stdin as well? That way the agent can just pipe to it.

Expands JSON objects into argv flags before Commander parses them, so any
command can receive structured options from AI agents or scripts. Accepts
inline JSON or `@path/to/file.json`; camelCase/snake_case keys convert to
kebab-case; arrays produce repeated flags; false/null are omitted; nested
objects are rejected.
Add stdin support so agents can pipe JSON options directly:
echo '{"framework":"next","yes":true}' | clerk init
Three new input sources:
- `--input-json -` explicitly reads from stdin
- Piped stdin auto-detected when --input-json flag is absent
and stdin is not a TTY
- Existing inline JSON and @file paths remain unchanged
Adds 8 subprocess-based unit tests that exercise both explicit
and auto-detected stdin paths, including error cases.
@rafa-thayto
rafa-thaytoforce-pushed the rafa-thayto/json-support branch from d53462f to e0ebf01CompareApril 24, 2026 12:21

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/cli-core/src/lib/input-json.ts`:
- Around line 122-160: The auto-stdin branch in expandInputJson treats any
non-TTY as piped input and calls readStdin(), which throws when stdin is empty
and breaks CI/background runs; change expandInputJson so that when
hasStdinPipe() is true it calls readStdin() but treats an empty string/EOF as a
no-op (do not throw or mutate argv) — only preserve the current behavior of
erroring when the explicit --input-json value is "-" (the
requireValue/resolveJsonValue path for INPUT_JSON_FLAG must still error on empty
stdin). Implement this by checking the result of readStdin() (or catching its
specific "no json" error) and returning the original argv unchanged when stdin
is empty; keep references: expandInputJson, hasStdinPipe, readStdin,
resolveJsonValue, INPUT_JSON_FLAG.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d00de3eb-c596-40aa-b99d-13e4e0c51885

📥 Commits

Reviewing files that changed from the base of the PR and between 69aa38a and 8e79e2a.

📒 Files selected for processing (8)
  • .changeset/input-json-flag.md
  • README.md
  • packages/cli-core/src/cli-program.ts
  • packages/cli-core/src/lib/input-json.test.ts
  • packages/cli-core/src/lib/input-json.ts
  • packages/cli-core/src/test/integration/input-json.test.ts
  • skills/clerk/SKILL.md
  • skills/clerk/references/agent-mode.md

Comment threadpackages/cli-core/src/lib/input-json.ts
@wyattjoh
wyattjoh merged commit 303af7e into mainApr 24, 2026
10 checks passed
@wyattjoh
wyattjoh deleted the rafa-thayto/json-support branch April 24, 2026 19:09
@github-actionsgithub-actionsBot mentioned this pull request Apr 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@rafa-thayto@wyattjoh