Open
Conversation
Pull the command-registration logic out of initiateCMD into a standalone buildProgram(defaultEnv) that returns a configured Command without parsing argv. The runtime CLI keeps the same behaviour while the new function becomes the single source of truth for the man-page generator. Guard the auto-run with an import.meta.url check so importing this module from a build tool no longer triggers program.parse().
Add a build-time roff generator at src/lib/generate-man.ts that walks buildProgram() and emits a single tagoio.1 page. Wire npm run man into the build chain plus prepublishOnly, ship the file via package.json files and man fields, gitignore the artifact, and document the install path (man tagoio plus fish_update_completions for fish users) in the README. A vitest snapshot test acts as the drift gate so CI fails when a flag or command changes without a matching snapshot regeneration; a companion mandoc/groff integration test catches roff syntax errors. The interactive prompt-driven flows (start-config, backup restore, export-setup) are excluded from the coverage threshold since they are covered by manual smokes, not unit tests.
The FILES section claimed ~/.tago-lock but the runtime writes per-environment locks at ./.tago-lock.<env>.lock (verified in src/lib/token.ts), and was missing ./.tagoio/personal.env where set-env persists TAGOIO_DEFAULT. Add an EXIT STATUS section documenting 0 (success) and 1 (any failure via errorHandler) as clig.dev recommends. Snapshot regenerated to match.
CI's `npm ci` was failing because package.json declared oxfmt@^0.47.0 / [email protected] but the committed lockfile still resolved to ^0.46.0 / 1.61.0. Regenerated the lockfile so transitive @oxfmt/* and @oxlint/* bindings align with the declared versions.
Replaces the developer-oriented stdout/stderr/JSON breakdown with a purpose-first summary: official CLI to TagoIO, manages the four top-level resources, suitable for interactive and CI/CD use.
vitorfdl
requested changes
May 7, 2026
Member
vitorfdl
left a comment
There was a problem hiding this comment.
Header and Footer must be readable
Static text bodies (description, exit-status, environment, files, see-also, author) move out of the inline roff arrays in generate-man.ts and into a dedicated MAN_CONTENT module written as plain English. The generator wraps each value with escapeRoff() and emits the same structural roff. Editing prose no longer requires counting backslashes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes tago-io/project-sdk-and-tools#3
Problem
The
tagoioCLI ships noman(1)page. Users have no offline reference (man tagoioreturns "No manual entry"), and fish-shell users can't enable tab-completion sincefish_update_completionsworks by scraping installed man pages.Investigation
program.commands, each withoptions,registeredArguments,description, andaddHelpTextblocks). That's exactly the data a man page needs — there's no missing source of truth, only a missing emitter.<required>/[optional]/[args...]), and the practice of bolding flags / italicizing metavariables.marked-man,ronn,help2man,pandoc) all expect either hand-written Markdown or run-time parsing of--helptext — both of which reintroduce the drift problem we're trying to solve. Closest commander-specific alternatives are unmaintained.Solution
Three tightly-scoped commits on top of
feat/cli-refactoring-deps:refactor(index): extract buildProgram for build-time tool reuse— pulls command registration out ofinitiateCMDintobuildProgram(defaultEnv), returning a configuredCommandwithout parsing argv. Guarded the auto-run with animport.meta.urlcheck so build tools can import this module without triggeringprogram.parse(). Single source of truth for the command tree.feat(man): generate tagoio.1 from commander definitions— newsrc/lib/generate-man.tswalksbuildProgram()and emits a roff page. Wired into the build chain (npm run manruns first), intoprepublishOnly, and intopackage.json(manfield +filesarray) sonpm i -gsymlinks it into<prefix>/share/man/man1/tagoio.1. A Vitest snapshot test acts as the CI drift gate; a companionmandoc/groffintegration test catches roff syntax errors. The interactive prompt-driven flows (start-config, backup restore, export-setup) are excluded from the coverage threshold since they're covered by manual smokes.fix(man): correct FILES paths and add EXIT STATUS per clig.dev audit— verified the actual filesystem contracts in code (src/lib/token.ts,src/lib/dotenv-config.ts) and corrected the FILES section to list./tagoconfig.json,./.tago-lock.<env>.lock, and./.tagoio/personal.envaccurately. Added the EXIT STATUS section.Why a hand-rolled walker (≈250 LoC) is the right choice for this CLI
marked-man/ronn/pandocrequire Markdown source — either hand-authored (drift) or auto-generated from commander first (which is just our walker with extra steps).help2manparses--helpheuristically and depends on GNU conventions; it's a system dependency and brittle on CI.commander-to-mannpm package exists in the modern ecosystem.ghandkubectldo exactly this with cobra; npm is the only big CLI using Markdown +marked-man, and they do so because their docs team writes prose by hand — not our use case.If we ever need per-command man pages (
tagoio-deploy.1, etc.) it'd be worth re-evaluating Markdown sources, but for a single umbrella page the walker wins on simplicity.Test plan
npm run manproduces a byte-stableman/tagoio.1(verified by snapshot test)npm testfails locally and in CI when a flag/command is added without regenerating the snapshot — drift gatemandoc -Tutf8 man/tagoio.1exits 0 (integration test)npm run buildregenerates the page automatically as a pre-stepnpm pack --dry-runshowsman/tagoio.1(13.7kB) in the tarballnpm i -g ./tago-io-cli-3.2.0.tgz,man tagoiorenders the page on macOSfish_update_completionsand get tab-completion (zsh / bash do not — explicitly out of scope; documented in README)