mmkal / mmkal/trpc-cli

Feature Request: Support for passthrough/arbitrary CLI flags

Open
#161 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
373
Forks
13
PR merge metrics
No merged PRs in 30d

Description

Use Case

We're building Ultracite, a CLI wrapper around Biome (a linter/formatter). We want to allow users to pass any Biome CLI flag through our commands without having to explicitly define every possible flag in our tRPC schema.

Current Behavior

When using z.record(z.string(), z.unknown()) or z.object({}).passthrough(), trpc-cli doesn't accept unknown flags. For example:

check: t.procedure
  .input(
    z.tuple([
      z.array(z.string()).optional().default([]),
      z.object({}).passthrough().optional().default({}),
    ])
  )
  .query(({ input }) => check(input))

Running mycli check --verbose results in:

error: unknown option '--verbose'

Desired Behavior

We'd like a way to accept arbitrary flags that get passed through to the underlying tool. Something like:

  1. Schema-level option: z.object({}).catchall(z.unknown()) or similar that tells trpc-cli to accept any flags
  2. Meta configuration: Add something like allowUnknownOptions: true to procedure meta
  3. createCli option: A global setting to allow passthrough for certain procedures

Workaround

Currently, we have to explicitly define every flag we want to support:

z.object({
  verbose: z.boolean().optional(),
  'diagnostic-level': z.enum(['info', 'warn', 'error']).optional(),
  'max-diagnostics': z.number().optional(),
  // ... etc
})

This works but means we can't support new Biome flags without updating our CLI.

Related

I noticed allowUnknownOption() is called in the trpc-cli source, but it seems to only apply at the program level, not for individual commands with schemas.

Proposed Solution

Perhaps something like:

check: t.procedure
  .meta({
    description: 'Run linter',
    allowUnknownOptions: true, // new option
  })
  .input(z.tuple([
    z.array(z.string()).optional(),
    z.record(z.string(), z.unknown()), // would now accept any --flag
  ]))

This would maintain type safety for known options while allowing flexibility for pass-through scenarios.

Would love to hear if this is something you'd consider adding, or if there's an existing pattern I'm missing!

Repository

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the trpc-cli handling of allowUnknownOption and compare it with the integration point shown in Ultracite's packages/cli/src/index.ts. Decide how schema-level, procedure-meta, or createCli configuration should interact with command parsing. Done means a documented, type-safe way to pass arbitrary flags for selected procedures without requiring each flag in the schema.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.