Skip to content

feat(args): support optional positional arguments - #572

Merged
kazupon merged 2 commits into
mainfrom
feat/optional-positional-args
Jun 10, 2026
Merged

kazupon merged 2 commits into
mainfrom
feat/optional-positional-args

Conversation

@kazupon

@kazupon kazupon commented Jun 10, 2026 •

Copy link
Copy Markdown
Owner

Summary

Update Gunshi to args-tokens v0.26.0 and expose optional positional argument support.

The renderer now marks optional/defaulted positional args with square brackets, tests cover raw schemas and unrequired(positional()), and docs/API references describe required/default behavior and usage output.

close #571

Summary by CodeRabbit

  • New Features

    • Added support for optional positional arguments.
    • Enhanced usage display with improved bracket notation: required positionals use angle brackets (<...>), optional positionals use square brackets ([<...>]).
  • Documentation

    • Updated guides and examples to reflect optional positional argument configuration and behavior.
  • Tests

    • Added test coverage for optional positional arguments and their parsing behavior.
  • Chores

    • Updated args-tokens dependency to ^0.26.0.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@kazupon, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 14 minutes and 26 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 019646a4-0bec-4b73-8bca-947b41ee5987

📥 Commits

Reviewing files that changed from the base of the PR and between c5c2bcf and 31916bf.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • .gitignore
  • packages/docs/package.json
  • packages/docs/src/api/docs.json
  • packages/gunshi/package.json
  • pnpm-workspace.yaml
📝 Walkthrough

Walkthrough

This PR implements optional positional arguments for the Gunshi CLI framework. The unrequired() combinator signature is updated to constrain its generic parameter and return type, usage rendering logic distinguishes optional positional symbols in help text, and tests validate the feature across parsing and type inference. Documentation is expanded to explain configuration and usage patterns.

Changes

Optional Positional Arguments Feature

Layer / File(s) Summary
Combinator Type Contract and Rendering Logic
packages/docs/src/api/combinators/functions/unrequired.md, packages/plugin-renderer/src/usage.ts
unrequired() signature updated to unrequired<T extends ArgSchema>(schema: T): Omit<T, 'required'> & CombinatorUnrequired. Usage rendering distinguishes required single positionals (<name>) from optional ones ([<name>]) via isRequiredSinglePositionalArg helper that checks explicit required field or falls back to default == null.
Positional Argument Tests
packages/gunshi/src/cli.test.ts, packages/gunshi/src/combinators.test.ts, packages/gunshi/src/combinators.test-d.ts, packages/plugin-renderer/src/usage.test.ts
CLI tests verify optional positionals can be omitted with required later positionals still parsing. Combinator tests validate type inference for unrequired(positional()) as string | undefined. Usage rendering snapshot test confirms optional positional display in help.
API Documentation
packages/docs/src/api/docs.json, packages/docs/src/api/combinators/functions/positional.md
ArgSchema properties expanded with positional-specific notes on required, multiple, and default behaviors. Combinator examples updated to show unrequired(positional()) usage. Line-number metadata updated across default, definition, and generator module sections.
Usage Guides and Examples
packages/docs/src/guide/essentials/auto-usage.md, packages/docs/src/guide/essentials/declarative.md, packages/docs/src/guide/experimentals/parser-combinators.md, packages/plugin-renderer/README.md
Guides clarify required (<resource>) vs optional ([<query>]) bracket notation, required: false declarative configuration, and unrequired(positional()) combinator pattern. README deploy example updated with optional positional region argument.
Dependency Updates
packages/docs/package.json, packages/gunshi/package.json
args-tokens bumped from ^0.25.0 to ^0.26.0 in both packages.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • kazupon/gunshi#550: Also updates args-tokens dependency in packages/gunshi/package.json.
  • kazupon/gunshi#432: Modifies packages/plugin-renderer/src/usage.ts positional argument rendering logic.
  • kazupon/gunshi#257: Changes generatePositionalSymbols in packages/plugin-renderer/src/usage.ts for positional usage generation.

Poem

🐰 A hop through positionals, some required, some free,
With brackets and angles for the CLI to see,
unrequired(positional()) dances with grace,
Making optional args a natural place! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(args): support optional positional arguments' clearly and concisely describes the main feature being added—support for optional positional arguments, which is the core objective of this PR.
Linked Issues check ✅ Passed The PR successfully implements support for optional positional arguments as requested in issue #571, demonstrated through TypeScript signature updates, documentation clarifications, test coverage for unrequired(positional()), and updated rendering logic for optional args.
Out of Scope Changes check ✅ Passed All changes are directly scoped to supporting optional positional arguments: dependency bump (args-tokens v0.26.0), function signature updates, documentation clarifications, test coverage, and rendering logic updates.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/optional-positional-args

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.

@kazupon kazupon added the feature Includes new features label Jun 10, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@gunshi/bone

npm i https://pkg.pr.new/@gunshi/bone@572

@gunshi/combinators

npm i https://pkg.pr.new/@gunshi/combinators@572

@gunshi/definition

npm i https://pkg.pr.new/@gunshi/definition@572

@gunshi/docs

npm i https://pkg.pr.new/@gunshi/docs@572

gunshi

npm i https://pkg.pr.new/gunshi@572

@gunshi/plugin

npm i https://pkg.pr.new/@gunshi/plugin@572

@gunshi/plugin-completion

npm i https://pkg.pr.new/@gunshi/plugin-completion@572

@gunshi/plugin-dryrun

npm i https://pkg.pr.new/@gunshi/plugin-dryrun@572

@gunshi/plugin-global

npm i https://pkg.pr.new/@gunshi/plugin-global@572

@gunshi/plugin-i18n

npm i https://pkg.pr.new/@gunshi/plugin-i18n@572

@gunshi/plugin-renderer

npm i https://pkg.pr.new/@gunshi/plugin-renderer@572

@gunshi/resources

npm i https://pkg.pr.new/@gunshi/resources@572

@gunshi/shared

npm i https://pkg.pr.new/@gunshi/shared@572

commit: 31916bf

@kazupon
kazupon marked this pull request as ready for review June 10, 2026 08:14

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/docs/src/api/combinators/functions/positional.md (1)

35-41: ⚡ Quick win

Enhance documentation to explain optional positional arguments.

The examples now include unrequired(positional()) to demonstrate optional positionals, which is excellent. However, the main description text (lines 12-15 and 52-55) does not mention that positional arguments can be made optional. For a newly introduced feature, users would benefit from a brief explanation in the description, such as:

"By default, positional arguments are required. Wrap with unrequired() to make them optional."

Consider also adding a cross-reference link to the unrequired() combinator documentation to help users discover the full API. As per coding guidelines, documentation should be updated when adding new features, and explaining the optional behavior (not just showing an example) better serves that goal.

Also applies to: 69-75

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/docs/src/api/combinators/functions/positional.md` around lines 35 -
41, The docs for positional arguments need a short explanatory sentence noting
that positional() arguments are required by default and can be made optional by
wrapping them with unrequired(positional()); add this sentence near the main
description (where positional() is introduced) and again where examples are
discussed, and add a cross-reference link to the unrequired() combinator docs so
readers can learn its behavior and return type changes.

Source: Coding guidelines

packages/docs/src/guide/essentials/auto-usage.md (1)

238-238: 💤 Low value

Consider breaking this long sentence into multiple sentences for readability.

The current sentence is 47 words long and packs multiple concepts (required vs optional, bracket notation, multiple values, mixed requirements). While technically correct, splitting it into 2-3 shorter sentences would improve clarity for readers.

✏️ Suggested rewrite for improved readability
-Positional arguments are displayed with clear, descriptive names that indicate their purpose. Required positional arguments use angle brackets (e.g., `<resource>`), while optional positional arguments use square brackets (e.g., `[<query>]`). Multiple positional arguments are shown as `[<file> ...]`, or `<file> [<file> ...]` when at least one value is required.
+Positional arguments are displayed with clear, descriptive names that indicate their purpose. Required positional arguments use angle brackets (e.g., `<resource>`), while optional positional arguments use square brackets (e.g., `[<query>]`). When multiple values are accepted, optional arguments are shown as `[<file> ...]`, or `<file> [<file> ...]` when at least one value is required.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/docs/src/guide/essentials/auto-usage.md` at line 238, Split the long
explanatory sentence in the "Positional arguments are displayed..." paragraph
into 2–3 shorter sentences for clarity: first state the general rule that
required positional arguments use angle brackets (e.g., `<resource>`) and
optional ones use square brackets (e.g., `[<query>]`), then add a separate
sentence explaining how multiple values are shown (e.g., `[<file> ...]`) and a
final short sentence (if needed) describing mixed requirements (`<file> [<file>
...]`) to keep each concept focused and readable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/docs/src/api/docs.json`:
- Around line 1903-1909: The documentation for ArgSchema.default currently
claims "positional/custom" can be "any appropriate default" which contradicts
the declared type "string | boolean | number"; update the prose in the "default"
property description (the block under the "default" property) to restrict
positional/custom defaults to the declared primitive union (string, boolean,
number) or, if non-primitive defaults are actually supported, change the
declared "type" to reflect that; edit the description text where it mentions
positional/custom and any other occurrences (lines around the same "default"
blocks at the other noted locations) so the wording and the type union are
consistent with ArgSchema.default.

---

Nitpick comments:
In `@packages/docs/src/api/combinators/functions/positional.md`:
- Around line 35-41: The docs for positional arguments need a short explanatory
sentence noting that positional() arguments are required by default and can be
made optional by wrapping them with unrequired(positional()); add this sentence
near the main description (where positional() is introduced) and again where
examples are discussed, and add a cross-reference link to the unrequired()
combinator docs so readers can learn its behavior and return type changes.

In `@packages/docs/src/guide/essentials/auto-usage.md`:
- Line 238: Split the long explanatory sentence in the "Positional arguments are
displayed..." paragraph into 2–3 shorter sentences for clarity: first state the
general rule that required positional arguments use angle brackets (e.g.,
`<resource>`) and optional ones use square brackets (e.g., `[<query>]`), then
add a separate sentence explaining how multiple values are shown (e.g., `[<file>
...]`) and a final short sentence (if needed) describing mixed requirements
(`<file> [<file> ...]`) to keep each concept focused and readable.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: dce5cba9-ccac-4882-9a52-dbd6682f1c54

📥 Commits

Reviewing files that changed from the base of the PR and between 06bec17 and c5c2bcf.

⛔ Files ignored due to path filters (2)
  • packages/plugin-renderer/src/__snapshots__/usage.test.ts.snap is excluded by !**/*.snap
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (14)
  • packages/docs/package.json
  • packages/docs/src/api/combinators/functions/positional.md
  • packages/docs/src/api/combinators/functions/unrequired.md
  • packages/docs/src/api/docs.json
  • packages/docs/src/guide/essentials/auto-usage.md
  • packages/docs/src/guide/essentials/declarative.md
  • packages/docs/src/guide/experimentals/parser-combinators.md
  • packages/gunshi/package.json
  • packages/gunshi/src/cli.test.ts
  • packages/gunshi/src/combinators.test-d.ts
  • packages/gunshi/src/combinators.test.ts
  • packages/plugin-renderer/README.md
  • packages/plugin-renderer/src/usage.test.ts
  • packages/plugin-renderer/src/usage.ts

Comment thread packages/docs/src/api/docs.json Outdated
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 10, 2026 •

Copy link
Copy Markdown

Deploying gunshi with  Cloudflare Pages  Cloudflare Pages

Latest commit: 31916bf
Status: ✅  Deploy successful!
Preview URL: https://666bba02.gunshi.pages.dev
Branch Preview URL: https://feat-optional-positional-arg.gunshi.pages.dev

View logs

@kazupon
kazupon merged commit d4c5f5b into main Jun 10, 2026
10 checks passed
@kazupon
kazupon deleted the feat/optional-positional-args branch June 10, 2026 08:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Includes new features

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support optional positional argument

1 participant