Skip to content

feat(codegen): add unified multi-target CLI architecture#729

Open
pyramation wants to merge 9 commits intomainfrom
devin/1771361112-unified-multi-target-cli
Open

feat(codegen): add unified multi-target CLI architecture#729
pyramation wants to merge 9 commits intomainfrom
devin/1771361112-unified-multi-target-cli

Conversation

@pyramation
Copy link
Contributor

@pyramation pyramation commented Feb 17, 2026

feat(codegen): add unified multi-target CLI architecture

Summary

Adds a unified multi-target CLI generator that produces a single CLI for projects with multiple GraphQL API endpoints (e.g., auth.localhost, members.localhost, app.localhost). Instead of generating separate CLIs per target, this generates one CLI with target-namespaced commands (auth:user list, members:member create, app:car get).

Key pieces:

  • resolveBuiltinNames() — collision detection that auto-renames builtin commands when they clash with target names (e.g., authcredentials, contextenv), with user-configurable overrides via builtinNames config
  • Multi-target executor — routes to the correct ORM client per target, resolves per-target endpoints from appstash context
  • Multi-target command maptarget:command namespacing for all schema-derived commands; builtin commands (context, auth/credentials) remain top-level
  • Multi-target context commandcontext create prompts for per-target endpoints with defaults baked from config
  • --save-token flag — auth target mutations can auto-save tokens to credentials store
  • generateMulti() wiring — new unifiedCli option that skips per-target CLI generation, collects pipeline data, and generates a single unified CLI
  • Multi-target docs generation — README, AGENTS.md, MCP tools, and skills files generated for unified CLI with target-namespaced examples and collision-aware builtin command names

This PR also includes the prior work from PRs #725 (CLI codegen) and #728 (docs generation) which this branch builds on.

Updates since last revision

  • Renamed infraNamesbuiltinNames across the entire codebase (BuiltinNames interface, resolveBuiltinNames() function, CliConfig.builtinNames property, all generators, all tests). This is a purely mechanical rename for API clarity — "builtin" better communicates that these are the built-in commands that ship with every generated CLI, as opposed to the schema-derived ones.

  • Added multi-target documentation generators that produce docs reflecting the unified CLI's target-namespaced command structure:

    • generateMultiTargetReadme() — README.md showing target:command syntax, per-target endpoint setup via context create, and collision-renamed builtin commands
    • generateMultiTargetAgentsDocs() — AGENTS.md structured for LLM consumption with per-target tool definitions and multi-target workflows
    • getMultiTargetCliMcpTools() — MCP tool definitions for all targets with target-prefixed tool names
    • generateMultiTargetSkills() — per-target skill files with target-prefixed file names

    These are wired into generateMulti() in generate.ts — when useUnifiedCli is enabled and docsConfig is present, docs are written alongside the generated CLI code. 5 new snapshot tests added (284 tests total, 118 snapshots).

Review & Testing Checklist for Human

  • Verify generated code actually compiles: The snapshot tests show generated TypeScript, but it has never been executed. Try running the codegen against a real multi-target schema and tsc the output. Check imports resolve correctly (especially ../../executor paths from commands/auth/user.ts).
  • Test collision detection edge cases: What happens if a user sets builtinNames: { auth: 'credentials' } but also has a target named credentials? The current code doesn't detect secondary collisions. Also verify the default renaming works (authcredentials, contextenv).
  • Verify skipCli / runOrm logic change: In generate.ts, the condition for runOrm changed from runReactQuery || runCli || ... to runReactQuery || !!config.cli || .... This means ORM is now generated even when skipCli: true is passed (which is correct for multi-target, but verify it doesn't break single-target behavior).
  • Check appstash dependency: The generated executor calls store.getTargetEndpoint(targetName) which was added in dev-utils PR Move req object and ApiModule to server/src/types #64. Verify that PR is merged and published (appstash@0.5.0 or similar) before merging this.
  • Test isAuthTarget detection: The code hardcodes isAuthTarget = name === 'auth' in generateMulti(). This means only targets literally named auth get --save-token on mutations. Consider if this should be configurable or detected differently.
  • Verify multi-target docs accuracy: The docs generators read docsConfig from the first target (configs[names[0]]?.docs), assuming all targets share the same docs config. Test with a real multi-target project to ensure docs correctly show target-namespaced commands, collision-renamed builtin commands, and per-target endpoint setup instructions.

Notes

- Add cli config option (CliConfig | boolean) to GraphQLSDKConfigTarget
- Add komoji dependency for toKebabCase casing
- Create CLI generator orchestrator (cli/index.ts)
- Create arg-mapper: converts CleanTypeRef to inquirerer Question[]
- Create infra-generator: context + auth commands via Babel AST
- Create executor-generator: ORM client init with appstash credentials
- Create table-command-generator: per-table CRUD using ORM methods
- Create custom-command-generator: per-operation using ORM methods
- Create command-map-generator: command registry (Record<string, Function>)
- Wire CLI generation into generate.ts alongside ORM/React Query
- Update root barrel to include CLI exports

Architecture: CLI -> ORM -> GraphQL (not CLI -> raw GraphQL)
CLI commands: prompt for args -> call ORM method -> print JSON result
Uses appstash@0.4.0 config-store for context/credential management
- Add cli-generator.test.ts with 13 tests covering all generated files
- Snapshot executor, context, auth, table commands, custom commands, command map
- Verify ORM method calls in table and custom commands
- Verify appstash config-store usage in executor
- Fix: runOrm now includes runCli so ORM is auto-enabled when CLI is enabled
- Add docs-generator.ts that produces README.md (overview, setup, commands)
  and COMMANDS.md (man-page style reference with synopsis, options, examples)
- Wire into CLI orchestrator so docs are always generated alongside commands
- Update snapshot tests: 15 tests, 10 snapshots covering all generated files
…CP, Skills)

- Add DocsConfig interface: { readme, agents, mcp, skills } with boolean flags
- Defaults: readme + agents on, mcp + skills opt-in. docs: true enables all.
- generateAgentsDocs(): structured AGENTS.md for LLM consumption with TOOL
  sections, INPUT/OUTPUT schemas, WORKFLOWS, and ERROR HANDLING
- generateMcpConfig(): mcp.json with typed inputSchema per command (JSON Schema)
- generateSkills(): per-command .md skill files for agent systems
- Wire into cli/index.ts orchestrator with config-driven conditional generation
- 22 tests, 17 snapshots covering all formats and config combinations
…rget support

- Move docs config to top-level GraphQLSDKConfigTarget (removed from CliConfig)
- Create shared docs-utils.ts with common utilities
- Add ORM docs generator (README, AGENTS.md, MCP tools, skills)
- Add React Query hooks docs generator (README, AGENTS.md, MCP tools, skills)
- Add per-target README and combined MCP config generators
- Add root-root README for multi-target configs
- Add generateMulti() to core for multi-target orchestration
- Update CLI entry point to use core generateMulti()
- Wire all docs generation into generate.ts
- 32 tests, 31 snapshots covering all doc formats
- Add InfraNames config to CliConfig for collision detection
- Add multi-target executor generator with baked endpoints and target routing
- Add target-prefixed table/custom command generators
- Add multi-target command map generator with target:command namespacing
- Add multi-target context command with per-target endpoint prompts
- Add generateAuthCommandWithName for custom auth command naming
- Add resolveInfraNames() for automatic collision detection (auth->credentials, context->env)
- Add generateMultiTargetCli() orchestrator
- Wire into generateMulti() with unifiedCli option
- Add --save-token flag on auth target custom operations
- Add snapshot tests for multi-target CLI (8 new snapshots)
- Add unit tests for resolveInfraNames collision detection
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

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