Skip to content
Back to skills

Cli View Layer

ASecurity

Keep CLI command files thin — parse args, call one app/ use case, render via OutputPort — no business logic in src/cli/commands/.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
ai-agentstypescriptgo

Works with

  • cli

Security analysis

A100/100

Scanned October 19, 2026

npx -y skills add lbdremy/phax --skill cli-view-layer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Cli View Layer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Cli View Layer
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/lbdremy-cli-view-layer/badge)](https://www.skillsdirectory.com/skills/lbdremy-cli-view-layer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cli-view-layer
description: Keep CLI command files thin — parse args, call one app/ use case, render via OutputPort — no business logic in src/cli/commands/.
---

# CLI view layer

## The rule

**Files under `src/cli/commands/` must stay thin.** A command handler's only
jobs are:

1. Parse and decode CLI arguments into a typed command object.
2. Call one `app/` use case.
3. Render the result or error through the `OutputPort`.
4. Return the exit code.

Command handlers must not import `infra/` directly, must not contain business
logic, and must not call multiple unrelated use cases in sequence (that belongs
in `app/`).

## The output port

All printing goes through `src/ports/output.ts`:

```typescript
export interface OutputPort {
  log(message: string): void;
  error(message: string): void;
}
```

No `console.log` or `process.stdout.write` outside `cli/` or the output port
adapter. This keeps domain and app testable without capturing stdout.

## Why

Thin command handlers mean:

- The application use cases are independently testable without a CLI harness.
- Exit-code mapping lives in one place and is consistent across commands.
- The output port can be swapped for a test double that captures output.

## What "thin" means in practice

A well-formed command handler is typically 15–30 lines:

```typescript
export async function runArchive(
  shortName: string,
  opts: { force?: boolean },
  out: OutputPort,
): Promise<number> {
  const result = await archiveRun(shortName, { force: opts.force ?? false });
  if (Either.isLeft(result)) {
    out.error(result.left.message);
    return 1;
  }
  out.log(`Archived ${shortName}`);
  return 0;
}
```

If your handler contains `if/else` chains that implement business rules, move
those rules into `app/`.

## Audit rules

`PHAX_CLI_001` — `src/cli/commands/` file imports from `infra/` or contains
more than trivial logic.
`PHAX_OUTPUT_001` — `console.*` or `process.stdout.write` outside `cli/` or
the output port adapter.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.