Skip to content
codefastlabs

Command Palette

Search for a command to run...

@codefast/cliv0.8.0· Architecture

CLI package architecture

The @codefast/cli package is a small Node CLI (top-level commands: arrange, audit, mirror, tag). It intentionally avoids hexagonal/DI ceremony: behavior is wired with plain functions, Commander for argv, and Result<T, AppError> for recoverable failures.

Layout (src/)

Area Role
bin.ts Process entry: shebang, runCli, process.exit.
cli.ts Composition root: Command program, global options, registers createArrangeCommand(), createAuditCommand(), createMirrorCommand(), createTagCommand().
core/ Shared primitives: Result / AppError / messageFrom, filesystem (nodeFilesystem), workspace discovery, Zod parseWithSchema, logger, consumeCliAppError, path-lesson text edits, TypeScript file walking.
core/config/ Zod schema (schema.ts), config load + cache (loader.ts), warning lines (warnings.ts). core/config.ts exposes loadCodefastConfig as the public Result-based API.
arrange/ Tailwind cn() / tv() tooling: Commander tree (command.ts), orchestration (analyze.ts, sync.ts, workspace.ts, …), output.ts for stdout, domain/ for pure logic + domain/ast/ for AST.
audit/ Read-only audits (command.ts, domain/): audit rtl scans source for physical-direction Tailwind classes (run.ts); audit links scans markdown for cross-references that resolve to nothing (run-links.ts); audit comments checks doc-comment conventions (run-comments.ts); audit react flags namespace/default React imports and implicit React.* UMD-global type references (run-react.ts).
mirror/ package.json exports sync: commands, prepare / sync, workspace package sync implementation, progress presenter, domain/exports.ts for export map generation.
tag/ @since JSDoc tagging: commands, prepare / sync, target discovery, since-writer, presenters.

Boundaries

  • Domain modules (*/domain/**) stay pure where possible: no Commander, no process, no ad-hoc logging—only types and algorithms (I/O lives in callers or thin core/ helpers).
  • Commands (*/command.ts) parse argv, call parseWithSchema / consumeCliAppError, delegate to prepare* / run* functions, set process.exitCode.
  • Config is loaded once per resolved repo root via core/config/loader.ts; warnings go through core/config/warnings.ts.

Imports

Internal code uses the #/… alias (see package.json imports). Prefer #/core/…, #/arrange/…, etc., over deep relative paths.

File naming

Rationale lives in DECISIONS.md.

  • Prefer one concept per filename (grouping.ts, grouping-service.ts, analyze-service.ts, exports.ts).
  • ast/ uses short names: ast-node.ts, helpers.ts, collectors-cn.ts, targets.ts, etc.
  • Zod schemas are named for what they parse, not with a reserved suffix: per-command argv schemas are cli-schema.ts, the config schema is core/config/schema.ts.
  • .test.ts is reserved for Vitest. No *.port.ts, *.adapter.ts, *.domain-service.ts, or *.value-object.ts in new code.

Testing

Tests live under tests/ only (see workspace rules). The CLI Vitest profile is Node, tests/**/*.test.*, passWithNoTests: true.

Further reading

License

Released under the MIT License.