Repository navigation
Module mode: /** @internal */ stops an export being a command - #226
Conversation
Tagging an exported function, `fn()`/`z.function()` export, class or class method `@internal` keeps it out of the CLI. On an overloaded function, a tag on any declaration hides the whole command. README: `@internal` replaces the `NoInfer` trick as the documented way to hide helpers, and drops the stale claim that non-command exports fail at startup (they've been skipped since #211). Includes Misha's README adjustments listing the other ways to hide an export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes
src/module-commands.ts—parseCliJsdocnow reads@internalintoCliJsdoc.internal;groupOverloadDeclarationsdrops any group with an@internaldeclaration (shared by function and class-method extraction, including overloads),extractModuleClassesskips tagged classes, andbuildLocalProceduresskips taggedfn()/z.function()exports.test/fn-module-commands.test.ts,test/typebox-module-commands.test.ts— cover fn/zod exports, plain functions and arrow consts, a whole class, a class method, the "any overload declaration hides the command" rule, plus invocation and unknown-command behavior.README.md— documents@internaland the two alternatives, and corrects the stale "other exports fail at startup" bullet to match the skip behavior already tested intest/typebox-module-commands.test.ts:167.
I verified the two touched test files pass (71 passed, no type errors) and eslint --max-warnings=0 is clean on the changed files. The @internal filter is applied at the same choke points that otherwise turn an export into a command, and the tests would fail if any of those checks were absent.
ℹ️ @internal is not consulted on re-export statements
Tagging a re-export (export * as group from './group', export {Users} from './users.ts') has no effect — the re-export machinery in buildRouterFromFileModule only reads the child router, which respects the tag only if it lives on the declaration in the child module. This is consistent with the PR's stated scope (functions, classes, class methods), but since the README now presents @internal as the standard way to hide an export, a reader may reasonably expect it to work on any export statement. Non-blocking; worth a one-line note in the docs if you want to set expectations.
Technical details
# Parent-level `@internal` on re-exports is ignored
## Affected sites
- `src/module-commands.ts:276-299` — `extractModuleReexports`/`buildRouterFromFileModule` add namespace, named, and star re-exports without ever calling `parseCliJsdoc` on the re-export statement's jsdoc.
- `README.md:694-708` — presents `@internal` as the general way to hide an export.
## Required outcome
- Either document that `@internal` applies to declarations in the commands module (not to `export ... from` statements), or extend the check to the re-export path.DeepSeek Flash (free via Pullfrog for OSS) | 𝕏
|
This is included in v0.17.1. |

In module mode, tag an export
/** @internal */to keep it out of the CLI - the standard TSDoc tag for "exported, but not public API".Works on functions, arrow functions,
fn()/z.function()exports, classes (hides the whole group) and class methods. On an overloaded function,@internalon any declaration hides the whole command - simpler than TS's per-signaturestripInternalsemantics, and it fails closed.Before this, the documented way to hide a helper was to make its signature unparseable (
params: NoInfer<{...}>). That still works, as does nesting the function under an exported object; the README lists both as alternatives.Change / Purpose
src/module-commands.ts:parseCliJsdocreads@internalintoCliJsdoc.internal@alias,@param, now@internal).src/module-commands.ts:groupOverloadDeclarationsdrops groups with an@internaldeclarationsrc/module-commands.ts:extractModuleClassesandbuildLocalProceduresskip@internalclasses andfn()/zod exportstest/typebox-module-commands.test.ts,test/fn-module-commands.test.tsREADME.md@internal(plus the other ways to hide an export), and drops a stale bullet claiming non-command exports fail at startup - they've been skipped since #211.🤖 Generated with Claude Code
Session:
local_bea2c0e0-1e8b-42e4-a063-77aa028a4139(@internal annotation for module mode)