**Typo in Nested Subcommand Shows Help Instead of Error**
Typo in nested subcommand shows help instead of error
When there's a typo in a level-2 subcommand (3-level nesting), @effect/cli shows the help menu of the first subcommand instead of throwing a CommandMismatch error. Reproduction:
Expected output:
Invalid subcommand for git - use one of 'database', 'remote'
Note: Changing subcommand order [remote, database] shows help for remote instead.
When there's a typo in a level-2 subcommand (3-level nesting), @effect/cli shows the help menu of the first subcommand instead of throwing a CommandMismatch error. Reproduction:
import { Command, Options } from "@effect/cli"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
import { Console, Effect } from "effect"
// Level 3: database update/sync commands
const databaseUpdate = Command.make("update", { noPush: Options.boolean("no-push").pipe(Options.optional) })
.pipe(Command.withHandler(({ noPush }) =>
Console.log(`Running 'git database update' with --no-push=${noPush}`)
))
const databaseSync = Command.make("sync")
.pipe(Command.withHandler(() =>
Console.log("Running 'git database sync'")
))
// Level 2: database commands with subcommands (no handler, like uzu update)
const database = Command.make("database").pipe(
Command.withSubcommands([databaseUpdate, databaseSync])
)
// Level 2: remote commands (no further subcommands)
const remoteAdd = Command.make("add")
.pipe(Command.withHandler(() => Console.log("Running 'git remote add'")))
const remote = Command.make("remote").pipe(
Command.withSubcommands([remoteAdd])
)
// Level 1: main command with subcommands
const git = Command.make("git").pipe(
Command.withSubcommands([database, remote])
)
const cli = Command.run(git, {
name: "Git Nested Test",
version: "1.0.0"
})
Effect.suspend(() => cli(process.argv))
.pipe(
Effect.provide(NodeContext.layer),
NodeRuntime.runMain
)
# Typo: "databas" instead of "database"
tsx examples/test-typo.ts databas update --no-push
Actual output: Shows help menu for database (first subcommand):
Git 1.0.0
USAGE
$ database
...
COMMANDS
- update [--no-push]
- syncimport { Command, Options } from "@effect/cli"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
import { Console, Effect } from "effect"
// Level 3: database update/sync commands
const databaseUpdate = Command.make("update", { noPush: Options.boolean("no-push").pipe(Options.optional) })
.pipe(Command.withHandler(({ noPush }) =>
Console.log(`Running 'git database update' with --no-push=${noPush}`)
))
const databaseSync = Command.make("sync")
.pipe(Command.withHandler(() =>
Console.log("Running 'git database sync'")
))
// Level 2: database commands with subcommands (no handler, like uzu update)
const database = Command.make("database").pipe(
Command.withSubcommands([databaseUpdate, databaseSync])
)
// Level 2: remote commands (no further subcommands)
const remoteAdd = Command.make("add")
.pipe(Command.withHandler(() => Console.log("Running 'git remote add'")))
const remote = Command.make("remote").pipe(
Command.withSubcommands([remoteAdd])
)
// Level 1: main command with subcommands
const git = Command.make("git").pipe(
Command.withSubcommands([database, remote])
)
const cli = Command.run(git, {
name: "Git Nested Test",
version: "1.0.0"
})
Effect.suspend(() => cli(process.argv))
.pipe(
Effect.provide(NodeContext.layer),
NodeRuntime.runMain
)
# Typo: "databas" instead of "database"
tsx examples/test-typo.ts databas update --no-push
Actual output: Shows help menu for database (first subcommand):
Git 1.0.0
USAGE
$ database
...
COMMANDS
- update [--no-push]
- syncExpected output:
Invalid subcommand for git - use one of 'database', 'remote'
Note: Changing subcommand order [remote, database] shows help for remote instead.
