Skip to content

feat: add --input, --describe, --fields global flags for AI agent CLI ergonomics#1119

Merged
jhaynie merged 7 commits intomainfrom
task/cli-improvements
Mar 5, 2026
Merged

feat: add --input, --describe, --fields global flags for AI agent CLI ergonomics#1119
jhaynie merged 7 commits intomainfrom
task/cli-improvements

Conversation

@jhaynie
Copy link
Member

@jhaynie jhaynie commented Mar 5, 2026

Summary

Adds three new global flags and four agent promotion channels to make the Agentuity CLI significantly more ergonomic for AI agents, inspired by Rewrite Your CLI for AI Agents.

New Global Flags

--input [JSON]

Pass all command options as a single JSON blob instead of individual flags:

# Instead of:
agentuity deploy --project my-proj --env production --force
# Agents can do:
agentuity deploy --input '{"project":"my-proj","env":"production","force":true}'
  • JSON keys use camelCase (matching Zod schema field names)
  • Lower precedence than explicit CLI flags — explicit flags always win
  • Validates against the command's Zod schema with helpful error messages

--describe

Returns a machine-readable JSON schema of any command's options:

agentuity cloud kv set --describe
# Returns JSON with command name, description, options (type, required, default, choices), and examples
  • Returns early before auth/project resolution — agents can introspect without credentials
  • Works on both subcommands and top-level parent commands
  • Powered by existing Zod schemas via extractCommandSchema() / extractSubcommandSchema()

--fields

Post-filter --json output to specific fields with dot-notation support:

agentuity project list --json --fields "name,id,config.region"
  • Supports dot-notation for nested field access
  • Comma-separated field list
  • Single interception point in outputJSON() — works for all commands automatically

Agent Promotion (4 Channels)

To help AI agents discover these capabilities:

  1. One-time stderr hint — First time an agent runs a command, a brief hint about --input, --describe, --fields is printed to stderr (doesn't interfere with --json stdout). Cached per-agent in SQLite so it only appears once.
  2. Validation error hints — When input validation fails, error messages now include structured hints about --describe and --input flags.
  3. ai-help section — New "Agent-Optimized I/O" section in agentuity ai help output with a structured guide to all flags.
  4. Intro prompt update — Best practices in agentuity ai intro expanded from 4 to 7 items, covering --input, --describe, --fields, and --validate.

Bug Fixes (found during review)

  • filterFields(): Added else { break; } when an intermediate dot-notation path segment is missing (prevents undefined property access)
  • buildValidationInput(): Added guard for JSON.parse('null') — rejects non-object JSON values (null, arrays, primitives)
  • Fixed indentation regression in cli.ts at first buildValidationInputAsync call site

Files Changed

File Changes
packages/cli/src/types.ts Added input, describe, fields to GlobalOptions
packages/cli/src/cli.ts Flag registration, --describe handler, --input threading, agent hints
packages/cli/src/schema-parser.ts inputJson merge logic with precedence + null guard
packages/cli/src/output.ts filterFields() with dot-notation, integrated into outputJSON()
packages/cli/src/schema-generator.ts Exported extractCommandSchema() + extractSubcommandSchema()
packages/cli/src/ai-help.ts New buildAgentOptimizedIO() section
packages/cli/src/cmd/ai/intro.ts Updated best practices (7 items, was 4)
packages/cli/src/cache/agent-intro.ts hasAgentSeenInputHint() / markAgentInputHintSeen()
packages/cli/src/cache/index.ts Exported new cache functions

Testing

  • bun run typecheck passes clean
  • bun run build passes clean

Summary by CodeRabbit

  • New Features

    • Added --input, --describe, and --fields CLI options for agent-friendly JSON input, command schema introspection, and filtered JSON output
    • CLI can emit command/subcommand schemas (describe mode) and limit JSON output via dot-notation fields
    • AI help now includes an Agent-Optimized Input/Output section and one-time agent hints
  • Documentation

    • Updated agent best practices with examples for --input, --describe, --fields, and validation
  • Bug Fixes

    • Improved validation to error early on missing request arguments
  • Chores

    • Added a pre-commit style check to enforce code formatting before commits

… ergonomics

Add three new global flags to improve CLI usability for AI agents:

- --input [JSON]: Pass all command options as a single JSON blob, with lower
  precedence than explicit CLI flags so they always win
- --describe: Return machine-readable JSON schema of any command's options,
  returning early before auth/project resolution so agents can introspect
  without credentials
- --fields: Post-filter --json output to specific fields with dot-notation
  support via a single outputJSON() interception point

Also implement four agent promotion channels to educate AI agents about
these capabilities:
- One-time stderr hint (cached per-agent in SQLite)
- Structured I/O hints in validation error messages
- Agent-optimized I/O section in ai-help output
- Updated best practices in the intro prompt (7 items, was 4)

Inspired by https://justin.poehnelt.com/posts/rewrite-your-cli-for-ai-agents/
@agentuity-agent
Copy link

agentuity-agent bot commented Mar 5, 2026

The latest Agentuity deployment details. Learn more about Agentuity.

Project Deployment Preview Updated (UTC)
docs 🟢 Ready Preview Mar 05, 2026 4:36 PM

@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 36b0ad18-60b6-4094-994c-f1a8c712facb

📥 Commits

Reviewing files that changed from the base of the PR and between 22e3687 and 760c44b.

📒 Files selected for processing (1)
  • packages/core/src/services/db/stats.ts
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Standalone Agent Test
  • GitHub Check: Storage CLI Tests
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Template Integration Tests
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Queue SDK Tests
  • GitHub Check: Postgres SSL Integration Test
  • GitHub Check: Pack & Upload
🧰 Additional context used
📓 Path-based instructions (3)
packages/core/src/**/*.ts

📄 CodeRabbit inference engine (packages/core/AGENTS.md)

packages/core/src/**/*.ts: Use TypeScript for all code in the @agentuity/core package
Prefer interfaces for public API definitions in @agentuity/core
Use generic types for reusable type utilities in @agentuity/core
Ensure no side effects in exports - all exports must be pure functions or types with no global mutations
Ensure code is compatible with both Browser and Node/Bun runtime environments

Files:

  • packages/core/src/services/db/stats.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome as code formatter with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5

Files:

  • packages/core/src/services/db/stats.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript Strict mode with ESNext target and bundler moduleResolution
Use StructuredError from @agentuity/core for error handling

Files:

  • packages/core/src/services/db/stats.ts
🧠 Learnings (1)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/core/src/services/db/stats.ts
🧬 Code graph analysis (1)
packages/core/src/services/db/stats.ts (2)
packages/core/src/services/api.ts (1)
  • request (308-370)
packages/core/src/services/db/index.ts (1)
  • DbInvalidArgumentError (42-42)
🔇 Additional comments (1)
packages/core/src/services/db/stats.ts (1)

87-93: LGTM!

This defensive guard correctly prevents a runtime error when destructuring a null/undefined request object. The error structure is consistent with the existing validation pattern below (lines 97-103), and providing undefined for orgId and region is appropriate since these values aren't accessible when the request itself is missing.


📝 Walkthrough

Walkthrough

Adds agent-focused CLI features: three new options (--input, --describe, --fields), JSON input merging into validation, schema introspection exports, output field filtering, agent hint caching, AI help/introduction updates, a Husky pre-commit hook, and a small DB validation guard.

Changes

Cohort / File(s) Summary
AI help & intro
packages/cli/src/ai-help.ts, packages/cli/src/cmd/ai/intro.ts
Adds an "Agent-Optimized Input/Output" section to AI help and updates the intro/best-practices text to document --input, --describe, --fields, and related usage examples.
CLI surface & runtime
packages/cli/src/cli.ts, packages/cli/src/types.ts
Adds GlobalOptions fields input?: string, describe?: boolean, fields?: string; implements --describe mode, forwards agent JSON input into validation calls, emits one-time agent hints, and extends CLI option definitions.
Validation & schema parsing
packages/cli/src/schema-parser.ts, packages/cli/src/schema-generator.ts
Extends buildValidationInput/buildValidationInputAsync to accept an optional inputJson parameter and merge/validate JSON input; introduces parse/type errors. Exports schema extractors and adds input/describe/fields to generated CLI schema.
Output filtering
packages/cli/src/output.ts
Adds filterFields helper and updates outputJSON to support options.fields, filtering output by comma-separated dot-notation fields and applying recursively.
Agent hint persistence (cache)
packages/cli/src/cache/agent-intro.ts, packages/cli/src/cache/index.ts
Adds lazy-created SQLite table agent_input_hint_seen, plus hasAgentSeenInputHint(agentId) and markAgentInputHintSeen(agentId) exports. Operations are guarded and non-blocking on error.
Schema & extraction helpers
packages/cli/src/schema-generator.ts
Makes command/subcommand schema extractors exported and adds internal helper to consolidate schema field extraction.
Pre-commit & tooling
.husky/pre-commit, package.json
Adds Husky pre-commit hook (.husky/pre-commit) running staged biome checks, adds root prepare script and husky devDependency.
Core DB validation
packages/core/src/services/db/stats.ts
Adds an early argument validation in dbLogStats to throw DbInvalidArgumentError when request is falsy.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


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

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

📦 Canary Packages Published

version: 1.0.34-760c44b

Packages
Package Version URL
@agentuity/auth 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-auth-1.0.34-760c44b.tgz
@agentuity/server 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-server-1.0.34-760c44b.tgz
@agentuity/runtime 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-runtime-1.0.34-760c44b.tgz
@agentuity/pi 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-pi-1.0.34-760c44b.tgz
@agentuity/cli 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-cli-1.0.34-760c44b.tgz
@agentuity/drizzle 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-drizzle-1.0.34-760c44b.tgz
@agentuity/evals 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-evals-1.0.34-760c44b.tgz
@agentuity/schema 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-schema-1.0.34-760c44b.tgz
@agentuity/frontend 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-frontend-1.0.34-760c44b.tgz
@agentuity/react 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-react-1.0.34-760c44b.tgz
@agentuity/opencode 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-opencode-1.0.34-760c44b.tgz
@agentuity/claude-code 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-claude-code-1.0.34-760c44b.tgz
@agentuity/core 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-core-1.0.34-760c44b.tgz
@agentuity/postgres 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-postgres-1.0.34-760c44b.tgz
@agentuity/workbench 1.0.34-760c44b https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-workbench-1.0.34-760c44b.tgz
Install

Add to your package.json:

{
  "dependencies": {
    "@agentuity/auth": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-auth-1.0.34-760c44b.tgz",
    "@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-server-1.0.34-760c44b.tgz",
    "@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-runtime-1.0.34-760c44b.tgz",
    "@agentuity/pi": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-pi-1.0.34-760c44b.tgz",
    "@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-cli-1.0.34-760c44b.tgz",
    "@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-drizzle-1.0.34-760c44b.tgz",
    "@agentuity/evals": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-evals-1.0.34-760c44b.tgz",
    "@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-schema-1.0.34-760c44b.tgz",
    "@agentuity/frontend": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-frontend-1.0.34-760c44b.tgz",
    "@agentuity/react": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-react-1.0.34-760c44b.tgz",
    "@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-opencode-1.0.34-760c44b.tgz",
    "@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-claude-code-1.0.34-760c44b.tgz",
    "@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-core-1.0.34-760c44b.tgz",
    "@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-postgres-1.0.34-760c44b.tgz",
    "@agentuity/workbench": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-workbench-1.0.34-760c44b.tgz"
  }
}

Or install directly:

bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-auth-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-server-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-runtime-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-pi-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-cli-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-drizzle-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-evals-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-schema-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-frontend-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-react-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-opencode-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-claude-code-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-core-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-postgres-1.0.34-760c44b.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.34-760c44b/agentuity-workbench-1.0.34-760c44b.tgz

jhaynie added 2 commits March 4, 2026 23:29
Install husky v9 and configure a pre-commit hook that runs
'bunx biome check --write --staged' to auto-fix formatting
before each commit. Uses biome's native --staged support so
lint-staged is not needed.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/schema-generator.ts (1)

81-164: ⚠️ Potential issue | 🟠 Major

Top-level command schema extraction is incomplete.

extractCommandSchema() omits def.schema parsing for arguments/options/response, so --describe for top-level commands can return partial schemas compared to subcommands.

🛠️ Proposed fix
 export function extractCommandSchema(def: CommandDefinition): SchemaCommand {
@@
 	// Extract requires/optional
 	// eslint-disable-next-line `@typescript-eslint/no-explicit-any`
 	const d = def as any;
@@
 	if (d.optional) {
 		schema.optional = {
 			auth: d.optional.auth === true || typeof d.optional.auth === 'string',
 			project: d.optional.project === true,
 			org: d.optional.org === true,
 			region: d.optional.region === true,
 		};
 	}
+
+	// Extract args and options from schema if available
+	if (d.schema) {
+		const schemas = d.schema as CommandSchemas;
+
+		if (schemas.args) {
+			const parsedArgs = parseArgsSchema(schemas.args);
+			schema.arguments = parsedArgs.metadata.map((arg) => ({
+				name: arg.name,
+				type: arg.variadic ? 'array' : 'string',
+				required: !arg.optional,
+				variadic: arg.variadic,
+			}));
+		}
+
+		if (schemas.options) {
+			const parsedOptions = parseOptionsSchema(schemas.options);
+			schema.options = parsedOptions.map((opt) => ({
+				name: opt.name,
+				type: opt.type,
+				required: !opt.hasDefault,
+				default: opt.defaultValue,
+				description: opt.description,
+			}));
+		}
+
+		if (schemas.response) {
+			schema.response = z.toJSONSchema(schemas.response);
+		}
+	}
@@
 	return schema;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/schema-generator.ts` around lines 81 - 164,
extractCommandSchema currently ignores def.schema so top-level commands miss
arguments/options/response in --describe; update extractCommandSchema (and
SchemaCommand assembly) to parse def.schema the same way subcommands do by
applying the same extraction logic used in extractSubcommandSchema to def.schema
(cast def as any to access .schema if needed) and populate schema.arguments,
schema.options, and schema.response accordingly (or refactor the shared parsing
into a helper and call it from both extractSubcommandSchema and
extractCommandSchema). Ensure you reference extractSubcommandSchema, def.schema,
SchemaCommand, and SubcommandDefinition when locating and modifying the code.
🤖 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/src/cli.ts`:
- Around line 1233-1240: The --describe path currently only runs for leaf
subcommands (in the baseCtx.options.describe block) and misses non-leaf
command-group nodes; update registerSubcommand(...) to check
baseCtx.options.describe (or the same options object used there) before the
early-return branch for command groups and invoke the same flow: import or call
extractSubcommandSchema(subcommand) then call outputJSON(schema) and return so
command-group invocations produce schema output too; ensure you use the same
symbols extractSubcommandSchema, outputJSON, and subcommand as in the existing
describe handling.

In `@packages/cli/src/cmd/ai/intro.ts`:
- Around line 65-71: Update the help text block (the paragraph that includes the
getCommand examples) to explicitly state that keys passed to --input must use
the camelCase schema keys shown by the command's --describe output (not flag
names), e.g., clarify "JSON keys must be the camelCase schema keys from
--describe" and mention that CLI flags still take precedence; this text lives in
the intro/help string near getCommand('cloud sandbox create...') in
packages/cli/src/cmd/ai/intro.ts.

In `@packages/cli/src/schema-parser.ts`:
- Around line 452-460: Replace the two occurrences of throwing plain Error in
the JSON --input validation block with StructuredError from `@agentuity/core`: add
an import for StructuredError and throw new StructuredError(...) instead of new
Error, preserving the original human message (including e.message for the parse
error case) and attach minimal metadata (e.g., { flag: '--input', errorType:
'json_parse' } for the parse failure and { flag: '--input', expected: 'object',
actual: parsed === null ? 'null' : Array.isArray(parsed) ? 'array' : typeof
parsed } for the type check). The changes should be made in the JSON parsing
section that uses variables parsed and e (the parse catch) so both throw sites
use StructuredError consistently.

---

Outside diff comments:
In `@packages/cli/src/schema-generator.ts`:
- Around line 81-164: extractCommandSchema currently ignores def.schema so
top-level commands miss arguments/options/response in --describe; update
extractCommandSchema (and SchemaCommand assembly) to parse def.schema the same
way subcommands do by applying the same extraction logic used in
extractSubcommandSchema to def.schema (cast def as any to access .schema if
needed) and populate schema.arguments, schema.options, and schema.response
accordingly (or refactor the shared parsing into a helper and call it from both
extractSubcommandSchema and extractCommandSchema). Ensure you reference
extractSubcommandSchema, def.schema, SchemaCommand, and SubcommandDefinition
when locating and modifying the code.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ab0e3cb1-750f-462f-bd79-35ed21947895

📥 Commits

Reviewing files that changed from the base of the PR and between 09effbd and 211f5bc.

📒 Files selected for processing (9)
  • packages/cli/src/ai-help.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/cache/index.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/output.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/types.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Standalone Agent Test
  • GitHub Check: Template Integration Tests
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Postgres SSL Integration Test
  • GitHub Check: Build
  • GitHub Check: Pack & Upload
🧰 Additional context used
📓 Path-based instructions (4)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cache/index.ts
  • packages/cli/src/output.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/types.ts
  • packages/cli/src/ai-help.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome as code formatter with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5

Files:

  • packages/cli/src/cache/index.ts
  • packages/cli/src/output.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/types.ts
  • packages/cli/src/ai-help.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript Strict mode with ESNext target and bundler moduleResolution
Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cache/index.ts
  • packages/cli/src/output.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/types.ts
  • packages/cli/src/ai-help.ts
**/index.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use named exports from package index.ts files

Files:

  • packages/cli/src/cache/index.ts
🧠 Learnings (2)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cache/index.ts
  • packages/cli/src/output.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/types.ts
  • packages/cli/src/ai-help.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cache/index.ts
  • packages/cli/src/output.ts
  • packages/cli/src/cache/agent-intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/types.ts
  • packages/cli/src/ai-help.ts
🧬 Code graph analysis (2)
packages/cli/src/schema-generator.ts (1)
packages/cli/src/types.ts (2)
  • CommandDefinition (691-706)
  • SubcommandDefinition (708-720)
packages/cli/src/cmd/ai/intro.ts (1)
packages/cli/src/index.ts (1)
  • getCommand (94-94)
🔇 Additional comments (11)
packages/cli/src/cmd/ai/intro.ts (2)

34-38: Nice discoverability improvement for --describe.

Surfacing ${getCommand('<command> --describe')} in the first command block makes introspection much easier to discover.


72-102: Great expansion of the AI-agent best-practices flow.

The added guidance for --describe, --fields, and --validate is clear and aligns well with the new CLI ergonomics.

packages/cli/src/cache/index.ts (1)

15-20: Named re-export update is clean and consistent.

packages/cli/src/types.ts (1)

313-315: Global option type additions are correctly modeled.

packages/cli/src/output.ts (1)

66-103: --fields filtering integration is solid and safely guarded.

Also applies to: 109-115

packages/cli/src/ai-help.ts (1)

94-95: Agent-optimized help section is well integrated and actionable.

Also applies to: 131-189

packages/cli/src/cache/agent-intro.ts (1)

63-115: Lazy, non-blocking hint tracking implementation looks good.

packages/cli/src/schema-generator.ts (1)

413-432: New global schema options are wired correctly.

packages/cli/src/cli.ts (3)

531-537: Global CLI flag wiring for agent I/O is clear and consistent.


294-301: Agent-targeted validation suggestions are a good UX improvement.


1454-1460: --input propagation into validation paths is correctly applied across auth modes.

Also applies to: 1748-1756, 2018-2026

- Add --describe support for command-group nodes (non-leaf subcommands)
  that were missed due to early return in registerSubcommand()
- Clarify --input help text: keys must be camelCase schema keys from
  --describe output, not kebab-case flag names (e.g. dryRun not --dry-run)
- Replace plain Error with StructuredError for --input JSON validation
  (InputJSONParseError, InputJSONTypeError) per codebase conventions
- Extract shared applySchemaFields() helper so extractCommandSchema also
  parses def.schema for args/options/response (was only in subcommand)
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/cli/src/cli.ts (1)

2224-2231: ⚠️ Potential issue | 🟠 Major

--describe is still missing for top-level command groups without handlers.

This block only covers commands where cmdDef.handler exists. For command-group nodes (no handler), action still falls back to help instead of schema output.

Proposed fix
-			} else {
-				cmd.action(() => cmd.help());
-			}
+			} else {
+				cmd.action(async () => {
+					if (baseCtx.options.describe) {
+						const { extractCommandSchema } = await import('./schema-generator');
+						const schema = extractCommandSchema(cmdDef);
+						const { outputJSON } = await import('./output');
+						outputJSON(schema);
+						return;
+					}
+					cmd.help();
+				});
+			}
🧹 Nitpick comments (1)
packages/cli/src/schema-parser.ts (1)

488-490: Avoid reparsing option schema metadata during JSON merge.

parseOptionsSchema() is invoked again in the merge block; reusing the earlier parsed metadata avoids duplicate work and repeated default-function evaluation.

Refactor sketch
 export function buildValidationInput(
@@
 ): { args: Record<string, unknown>; options: Record<string, unknown> } {
 	const result = { args: {} as Record<string, unknown>, options: {} as Record<string, unknown> };
+	let parsedOptionsMeta: ParsedOption[] | undefined;
@@
 	if (schemas.options) {
-		const parsed = parseOptionsSchema(schemas.options);
-		for (const opt of parsed) {
+		parsedOptionsMeta = parseOptionsSchema(schemas.options);
+		for (const opt of parsedOptionsMeta) {
@@
-		if (schemas.options) {
-			const optsMeta = parseOptionsSchema(schemas.options);
-			for (const opt of optsMeta) {
+		if (schemas.options && parsedOptionsMeta) {
+			for (const opt of parsedOptionsMeta) {
 				if (result.options[opt.name] === undefined && parsed[opt.name] !== undefined) {
 					result.options[opt.name] = parsed[opt.name];
 				}
 			}
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/schema-parser.ts` around lines 488 - 490, The merge block is
reparsing option metadata by calling parseOptionsSchema(schemas.options) again,
causing duplicate work and repeated evaluation of default functions; reuse the
previously computed optsMeta (from the initial parse when schemas.options
exists) inside the merge/merge loop instead of invoking parseOptionsSchema a
second time. Locate the code that currently calls parseOptionsSchema again in
the merge branch and replace that call with the existing optsMeta variable so
defaults and metadata are only evaluated once.
🤖 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/src/schema-parser.ts`:
- Line 458: The current truthy check "if (inputJson)" skips validation for an
explicit empty --input ('') and should instead treat an empty string as input to
be parsed (and thus error). Change the conditional that uses the variable
inputJson in schema-parser.ts to an explicit presence check (e.g., check
inputJson !== undefined or typeof inputJson !== 'undefined') so that empty
strings are passed into the JSON parsing/validation logic (the block guarded by
the if) and will produce a parse/type error as intended.

---

Nitpick comments:
In `@packages/cli/src/schema-parser.ts`:
- Around line 488-490: The merge block is reparsing option metadata by calling
parseOptionsSchema(schemas.options) again, causing duplicate work and repeated
evaluation of default functions; reuse the previously computed optsMeta (from
the initial parse when schemas.options exists) inside the merge/merge loop
instead of invoking parseOptionsSchema a second time. Locate the code that
currently calls parseOptionsSchema again in the merge branch and replace that
call with the existing optsMeta variable so defaults and metadata are only
evaluated once.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec0a7cf7-5068-493b-9558-e2b3ee77e95c

📥 Commits

Reviewing files that changed from the base of the PR and between a4dd794 and ee96366.

📒 Files selected for processing (4)
  • packages/cli/src/cli.ts
  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/schema-generator.ts
  • packages/cli/src/schema-parser.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/cli/src/schema-generator.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Agentuity Deployment
  • GitHub Check: Storage CLI Tests
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Pack & Upload
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Build
  • GitHub Check: Postgres SSL Integration Test
  • GitHub Check: Queue SDK Tests
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Template Integration Tests
🧰 Additional context used
📓 Path-based instructions (3)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/schema-parser.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome as code formatter with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5

Files:

  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/schema-parser.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript Strict mode with ESNext target and bundler moduleResolution
Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/schema-parser.ts
🧠 Learnings (2)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/schema-parser.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/cmd/ai/intro.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/schema-parser.ts
🧬 Code graph analysis (2)
packages/cli/src/cli.ts (5)
packages/cli/src/agent-detection.ts (1)
  • getExecutingAgent (560-569)
packages/cli/src/schema-generator.ts (2)
  • extractSubcommandSchema (208-302)
  • extractCommandSchema (112-203)
packages/cli/src/output.ts (1)
  • outputJSON (108-116)
packages/cli/src/cache/agent-intro.ts (2)
  • hasAgentSeenInputHint (87-99)
  • markAgentInputHintSeen (105-115)
packages/cli/src/schema-parser.ts (1)
  • buildValidationInputAsync (505-533)
packages/cli/src/schema-parser.ts (1)
packages/core/src/error.ts (1)
  • StructuredError (291-388)
🔇 Additional comments (2)
packages/cli/src/cmd/ai/intro.ts (1)

65-83: Clear, actionable guidance for agent workflows.

The --input/--describe/--fields instructions are precise, and the camelCase + precedence clarification removes ambiguity.

packages/cli/src/cli.ts (1)

1466-1472: Nice consistency: --input is wired through all schema-validation paths.

Passing baseCtx.options.input in each auth branch keeps behavior uniform regardless of command prerequisites.

Also applies to: 1760-1768, 2030-2038

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/cli/src/schema-parser.ts (1)

488-493: Avoid re-running parseOptionsSchema() during JSON merge.

parseOptionsSchema() is called earlier and again here. Since that helper evaluates function defaults, this can repeat non-pure default factories and adds unnecessary work. Cache parsed option metadata once and reuse it in both loops.

♻️ Proposed refactor
 export function buildValidationInput(
 	schemas: CommandSchemas,
 	rawArgs: unknown[],
 	rawOptions: Record<string, unknown>,
 	_options?: { usesStdin?: boolean },
 	inputJson?: string
 ): { args: Record<string, unknown>; options: Record<string, unknown> } {
 	const result = { args: {} as Record<string, unknown>, options: {} as Record<string, unknown> };
+	const parsedOptions = schemas.options ? parseOptionsSchema(schemas.options) : undefined;

@@
-	if (schemas.options) {
-		const parsed = parseOptionsSchema(schemas.options);
-		for (const opt of parsed) {
+	if (parsedOptions) {
+		for (const opt of parsedOptions) {
@@
-		if (schemas.options) {
-			const optsMeta = parseOptionsSchema(schemas.options);
-			for (const opt of optsMeta) {
+		if (parsedOptions) {
+			for (const opt of parsedOptions) {
 				if (result.options[opt.name] === undefined && parsed[opt.name] !== undefined) {
 					result.options[opt.name] = parsed[opt.name];
 				}
 			}
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/schema-parser.ts` around lines 488 - 493, The code calls
parseOptionsSchema(schemas.options) twice which re-evaluates function defaults;
instead compute and cache the parsed metadata once (e.g., const cachedOptsMeta =
parseOptionsSchema(schemas.options)) before the merge loops and reuse
cachedOptsMeta in both places so you don't re-run parseOptionsSchema; update the
loop that currently declares optsMeta to iterate over cachedOptsMeta and ensure
any other usage in this function references the same cached variable (affecting
parseOptionsSchema, optsMeta, result.options and parsed).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/cli/src/schema-parser.ts`:
- Around line 488-493: The code calls parseOptionsSchema(schemas.options) twice
which re-evaluates function defaults; instead compute and cache the parsed
metadata once (e.g., const cachedOptsMeta = parseOptionsSchema(schemas.options))
before the merge loops and reuse cachedOptsMeta in both places so you don't
re-run parseOptionsSchema; update the loop that currently declares optsMeta to
iterate over cachedOptsMeta and ensure any other usage in this function
references the same cached variable (affecting parseOptionsSchema, optsMeta,
result.options and parsed).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8fb2f13d-6a57-4f97-a60f-e740a6eca827

📥 Commits

Reviewing files that changed from the base of the PR and between ee96366 and 22e3687.

📒 Files selected for processing (1)
  • packages/cli/src/schema-parser.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: Agentuity Deployment
  • GitHub Check: Storage CLI Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Queue SDK Tests
  • GitHub Check: Template Integration Tests
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Standalone Agent Test
  • GitHub Check: Build
  • GitHub Check: Postgres SSL Integration Test
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Pack & Upload
🧰 Additional context used
📓 Path-based instructions (3)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/schema-parser.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use Biome as code formatter with tabs (width 3), single quotes, semicolons, lineWidth 100, and trailingCommas es5

Files:

  • packages/cli/src/schema-parser.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use TypeScript Strict mode with ESNext target and bundler moduleResolution
Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/schema-parser.ts
🧠 Learnings (2)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/schema-parser.ts
📚 Learning: 2026-02-17T14:23:15.448Z
Learnt from: potofpie
Repo: agentuity/sdk PR: 974
File: packages/cli/src/cmd/git/account/list.ts:39-40
Timestamp: 2026-02-17T14:23:15.448Z
Learning: In the Agentuity CLI framework (packages/cli), when a subcommand declares requires: { auth: true }, the framework will automatically call requireAuth() before invoking the handler. Do not call requireAuth(ctx) manually inside command handlers. This applies to all TypeScript command files under packages/cli/src, including paths like packages/cli/src/cmd/git/account/list.ts.

Applied to files:

  • packages/cli/src/schema-parser.ts
🧬 Code graph analysis (1)
packages/cli/src/schema-parser.ts (1)
packages/core/src/error.ts (1)
  • StructuredError (291-388)
🔇 Additional comments (3)
packages/cli/src/schema-parser.ts (3)

3-13: Good adoption of typed StructuredError constructors.

This is a solid improvement for consistent CLI error semantics and machine-readable failure handling.
As per coding guidelines, "Use StructuredError from @agentuity/core for error handling".


458-477: --input parsing guard and non-object rejection look correct.

Using inputJson !== undefined plus explicit null/array/type rejection gives the expected behavior for empty strings and invalid JSON shapes.


509-513: Async path correctly forwards inputJson into shared validation logic.

This keeps sync/async behavior aligned and avoids duplicate parsing implementations.

@jhaynie jhaynie merged commit e21c1bf into main Mar 5, 2026
17 of 18 checks passed
@jhaynie jhaynie deleted the task/cli-improvements branch March 5, 2026 17:22
Sign up for free to 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.

1 participant