# CLI reference

> Commands for detect, ignores, install, link, update, check, and help: flags, defaults, exit codes, JSON output, URL scanning, and detect shorthand targets.

- Repository: pbakaus/impeccable
- GitHub: https://github.com/pbakaus/impeccable
- Human docs: https://grok-wiki.com/public/docs/pbakaus-impeccable-adadc04d8de4
- Complete Markdown: https://grok-wiki.com/public/docs/pbakaus-impeccable-adadc04d8de4/llms-full.txt

## Source Files

- `cli/bin/cli.js`
- `cli/engine/cli/main.mjs`
- `cli/bin/commands/skills.mjs`
- `cli/bin/commands/ignores.mjs`
- `README.npm.md`
- `package.json`

---

---
title: "CLI reference"
description: "Commands for detect, ignores, install, link, update, check, and help: flags, defaults, exit codes, JSON output, URL scanning, and detect shorthand targets."
---

The npm package `impeccable` ships a Node CLI (`bin`: `cli/bin/cli.js`, Node `>=22.18.0`) that routes top-level commands to the detector engine, the ignores manager, and the skills installer. Invoke it as `npx impeccable …` or a global `impeccable` install. The package also exports the detector as a library (`main` / `exports["."]` → `cli/engine/detect-antipatterns.mjs`; `exports["./browser"]` → the browser bundle).

## Command router

```text
impeccable <command> [options] [args…]
```

| Command | Handler | Role |
|---|---|---|
| `detect` | `cli/engine/cli/main.mjs` (`detectCli`) | Scan files, dirs, stdin, or URLs |
| `ignores` / `ignore` | `cli/bin/commands/ignores.mjs` | Manage detector ignore config |
| `help` | `cli/bin/commands/skills.mjs` | List skill commands from the API |
| `install` | skills module | Download/copy compiled skills |
| `link` | skills module | Symlink skills from a local checkout |
| `update` | skills module | Refresh installed skills |
| `check` | skills module | Report whether project skills need update |
| `skills <sub>` | skills module | Legacy namespace for help/install/link/update/check |

Global flags on the root binary:

| Flag | Behavior |
|---|---|
| `--help` / `-h` / no args | Print command list and exit `0` |
| `--version` / `-v` | Print `package.json` version and exit `0` |

**Detect shorthand.** If the first argument is not a known command but looks like a detect target (flag, `http(s)://` URL, path-shaped string containing `/`, `\`, or `.`, or an existing path such as extension-less `Dockerfile`), the router rewrites argv and runs `detect`. Bare unknown words fail with exit `1` instead of being statted as paths.

**Prompt abort.** Interactive skill prompts can throw `IMPECCABLE_PROMPT_ABORT`; the root catcher prints `Aborted.` and exits `130`.

```bash
npx impeccable --help
npx impeccable --version
npx impeccable src/                 # shorthand → detect
npx impeccable detect --json src/
npx impeccable skills install -y    # legacy namespace
```

## `detect`

```text
impeccable detect [options] [file-or-dir-or-url…]
```

Default target when none is given and stdin is a TTY: `process.cwd()`. Non-TTY stdin with no targets reads stdin (hook-style JSON with `tool_input.file_path`, or raw text as `<stdin>`).

### Flags

<ParamField body="--json" type="boolean" default="false">
Pretty-print findings as a JSON array on stdout. Empty scan writes `[]`.
</ParamField>

<ParamField body="--quiet" type="boolean" default="false">
Text mode only: print the primary findings summary (and advisory count note) on stderr; omit per-finding detail.
</ParamField>

<ParamField body="--scope" type="string">
Comma-separated design domains. Valid values today: `type`, `layout`. Bare `--scope` or unknown names exit `1`. Empty list means no filtering.
</ParamField>

<ParamField body="--viewport" type="WxH" default="1280x800">
Browser viewport for URL scans, e.g. `--viewport 390x844`. Format: two integers 2–5 digits joined by `x`. Invalid form exits `1`.
</ParamField>

<ParamField body="--no-config" type="boolean" default="false">
Skip project detector config, ignore lists, inline ignore comments, and DESIGN.md / design-system loading.
</ParamField>

<ParamField body="--no-inline-ignores" type="boolean" default="false">
Do not honor in-file `impeccable-disable*` comments (still loads project config unless `--no-config`).
</ParamField>

<ParamField body="--no-design-system" type="boolean" default="false">
Do not load per-target DESIGN.md / `.impeccable/design.json` context.
</ParamField>

<ParamField body="--no-advisory" type="boolean" default="false">
Drop advisory findings before output and exit-code math.
</ParamField>

<ParamField body="--help" type="boolean">
Print detect usage and exit `0`.
</ParamField>

Deprecated flags (accepted, ignored, note on stderr):

| Flag | Note |
|---|---|
| `--fast` / `-fast` | Full scan always runs; regex-only path no longer used |
| `--gpt`, `--gemini` | Generated-UI tells run by default |

Aliases: `-json` → `--json`.

### Detection modes

| Target | Engine | Notes |
|---|---|---|
| `.html` / `.htm` | Static HTML/CSS (`detectHtml`) | Resolves linked CSS; design system per file project root |
| Other scannable files | Regex text (`detectText`) | CSS, SCSS/SASS/LESS, JS/TS/JSX/TSX, Vue, Svelte, Astro, Blade |
| Directory walk | Both per extension | Skips `node_modules`, `dist`, `build`, `__pycache__`, and most hidden dirs (except `.vitepress`, `.vuepress`, `.storybook`) |
| `http://` / `https://` | Puppeteer (`detectUrl`) | Optional dependency `puppeteer`; design system not loaded for remote hosts |
| `file://` | Puppeteer | Local path used for design-system resolution when mappable |

Directory scans build an import graph and may attach `importedBy` basenames on findings. When not in `--json`/`--quiet`, framework config detection can suggest scanning `http://localhost:<port>` for more accurate results. Interactive TTY scans of >50 files prompt to continue; declining exits `0`.

### Project config applied by default

Unless `--no-config`:

- `.impeccable/config.json` and `.impeccable/config.local.json` → `detector.ignoreRules`, `ignoreFiles`, `ignoreValues`, `designSystem.enabled`
- Inline comments: `impeccable-disable`, `impeccable-disable-line`, `impeccable-disable-next-line` (rule ids comma-separated, or `*` / omit for all)

### Finding shape (JSON)

Each finding includes at least:

| Field | Type | Meaning |
|---|---|---|
| `antipattern` | string | Rule id |
| `name` | string | Display name |
| `description` | string | Human description |
| `severity` | string | Default `warning` |
| `category` | string \| null | e.g. slop / quality |
| `file` | string | Path or URL label |
| `line` | number | Line when known; `0` otherwise |
| `snippet` | string | Short evidence |
| `advisory` | boolean | Present only when `true` |
| `importedBy` | string[] | Optional; basenames of importers |

### Advisory findings

Rules marked advisory (currently `em-dash-overuse`) list in a separate dimmed text section, carry `"advisory": true` in JSON, and **never** contribute to the failure count or non-zero exit. `--no-advisory` removes them entirely.

### Exit codes (`detect`)

| Code | When |
|---|---|
| `0` | No primary findings (including advisory-only scans, empty scan, help) |
| `2` | One or more non-advisory findings |
| `1` | Invalid `--scope` / `--viewport` (and other hard parse failures) |

URL scan failures for a single target write `Error: …` to stderr and continue; inaccessible path targets warn and skip.

### Examples

```bash
npx impeccable detect src/
npx impeccable detect index.html styles.css
npx impeccable detect https://example.com
npx impeccable detect file:///abs/path/to/page.html
npx impeccable detect --json --quiet --scope type,layout src/
npx impeccable detect --viewport 390x844 --no-advisory https://localhost:3000
npx impeccable detect --no-config --no-design-system dist/index.html
```

<RequestExample>
```bash
npx impeccable detect --json src/Button.tsx
```
</RequestExample>

<ResponseExample>
```json
[
  {
    "antipattern": "overused-font",
    "name": "Overused font",
    "description": "…",
    "severity": "warning",
    "category": "slop",
    "file": "/project/src/Button.tsx",
    "line": 12,
    "snippet": "font-family: Inter"
  }
]
```
</ResponseExample>

## `ignores`

```text
impeccable ignores <action> [options]
impeccable ignore <action> …   # alias
```

Writes detector ignore fields under `.impeccable/config.json` (shared, default) or `.impeccable/config.local.json` (`--local`). Default action with no args: `list`.

### Actions

| Action | Aliases | Arguments |
|---|---|---|
| `list` | `status`, `ls` | None |
| `add-rule` | `ignore-rule` | `<rule>` `[--all-values]` |
| `add-file` | `ignore-file` | `<glob>` |
| `add-value` | `ignore-value`, `update-value` | `<rule> <value>` `[--file <glob>]…` `[--reason <text>]` |
| `remove-rule` | `rm-rule` | `<rule>` |
| `remove-file` | `rm-file` | `<glob>` |
| `remove-value` | `rm-value` | `<rule> <value>` (same value flags as add) |
| `clear` | — | Scope flags only |

### Scope flags

| Flag | Meaning |
|---|---|
| `--shared` | Target shared config (default) |
| `--local` | Target `config.local.json` |
| `--all` | Remove/clear both scopes only |

Only one of `--shared`, `--local`, `--all` may be set.

### Value-ignore rules

- Wildcard value `*` requires `--file <glob>` on add (project-wide `*` is rejected).
- `overused-font` cannot be whole-rule ignored without `--all-values`; prefer `add-value overused-font <font>`.
- Empty or flag-shaped globs for `--file` are rejected.
- `list` prints merged, shared, and local `ignoreRules` / `ignoreFiles` / `ignoreValues` and design-system enabled state.

```bash
npx impeccable ignores list
npx impeccable ignores add-file "src/legacy/**"
npx impeccable ignores add-value overused-font Inter --reason "Brand font"
npx impeccable ignores add-value design-system-color "*" --file "src/demo.css"
npx impeccable ignores remove-value overused-font Inter --all
npx impeccable ignores clear --local
```

## Skills: `install`, `link`, `update`, `check`, `help`

These are first-class top-level commands and also work under `impeccable skills <sub>`. Bundle download URL: `https://impeccable.style/api/download/bundle/universal`. Override with env `IMPECCABLE_BUNDLE_PATH` (directory or zip) for offline/local bundles.

### Provider aliases

Install targets map friendly names to harness folders, including: `claude` → `.claude`, `cursor` → `.cursor`, `codex`/`agents` → `.agents`, `gemini` → `.gemini`, `github`/`copilot` → `.github`, `grok`/`xai` → `.grok`, `opencode`, `pi`, `kiro`, `qoder`, `trae`, `trae-cn`, `rovodev`/`rovo-dev`, `antigravity`/`agent` → `.agent`, `vibe`.

Default when nothing is detected: `.claude` + `.agents`. Global skill path overrides: Pi → `~/.pi/agent/skills`, OpenCode → `$OPENCODE_CONFIG_DIR` or `$XDG_CONFIG_HOME/opencode` or `~/.config/opencode`, Antigravity global → `~/.gemini/config/skills`.

### `install`

```text
impeccable install [flags]
```

| Flag | Meaning |
|---|---|
| `-y` / `--yes` | Non-interactive: use detected/default providers; scope defaults to **project** unless scoped explicitly; hooks install-by-default when undecided |
| `--providers=<list>` | Comma-separated provider names or folder names |
| `--scope=project\|global` (also `--project`, `--local`, `--user`, `--home`, `--global`, `--install-scope`) | Install root: project cwd tree vs home |
| `--force` | Reinstall/refresh even if already present |
| `--no-hooks` | Skip design-hook manifests |

Behavior summary:

1. Resolve providers (explicit → project harness dirs → global harness hints → defaults).
2. Resolve scope (explicit → interactive prompt → `-y` forces project).
3. Download universal bundle (or local override), copy per-provider skill variants (never cross-provider symlink), optional agents, optional hooks.
4. Hooks: prompt once (default yes) on TTY; consent stored in `.impeccable/config.local.json`; declined consent skips hooks; non-interactive defaults to install without recording consent.

```bash
npx impeccable install -y --providers=claude,codex --scope=project
npx impeccable install --no-hooks --providers=cursor
npx impeccable install --force --scope=global --providers=claude
```

### `link`

```text
impeccable link [--source=<path>] [--providers=<list>] [-y|--yes] [--force]
```

| Flag | Default / meaning |
|---|---|
| `--source` | `.impeccable` relative to project root (git root if found) |
| Bundle resolution | Prefer `<source>/dist/universal`, else provider `*/skills` under source |
| `--force` | Replace existing skill folders with symlinks |
| `-y` / `--yes` | Skip confirmation |

Fails if source has no compiled skills, nothing links (existing dirs without `--force`), or targets cannot be resolved.

```bash
npx impeccable link --source=.impeccable --providers=claude,cursor -y
```

### `update`

```text
impeccable update [flags]
```

| Flag | Meaning |
|---|---|
| `-y` / `--yes` | Non-interactive confirm; on dual project+user installs, defaults to **project** |
| `--project` / `--user` (and other scope aliases) | Force which install to update |
| `--force` | Passed through to hook merge/replace paths |
| `--no-hooks` | Do not install/update hook manifests |

Linked (submodule) providers are skipped with guidance to `git submodule update --remote` + re-`link`. Copied installs refresh from the downloaded bundle when file hashes differ.

### `check`

```text
impeccable check
```

Checks the **project** install only. Exit `0` if not installed (with install hint), or after reporting up-to-date / updates-available. Exit `1` if the bundle download/compare fails.

### `help`

```text
impeccable help
```

Fetches `https://impeccable.style/api/commands` and prints `/command` rows. Network failure exits `1`.

## Exit codes (skills and router)

| Code | Typical cause |
|---|---|
| `0` | Success, abort after user decline (some paths), `check` not installed / up to date, help list OK |
| `1` | Unknown command/subcommand, download/install/update failure, link nothing written, invalid scope/providers |
| `130` | Interactive prompt aborted (`IMPECCABLE_PROMPT_ABORT`) |
| `2` | **`detect` only** — primary findings present |

## Requirements and runtime notes

- **Node** `>=22.18.0`.
- **URL scanning** needs optional `puppeteer` (declared under `optionalDependencies`). Prefer `node` over Bun for HTML-heavy local scans if using the detector outside the packaged path.
- **CI**: use `detect --json` and/or `--quiet`; exit `2` means findings. See related CI guidance for ignores and Puppeteer setup.
- Skills install/update need network access to `impeccable.style` unless `IMPECCABLE_BUNDLE_PATH` is set.

## Related pages

<CardGroup>
  <Card title="Detect in CI" href="/detect-in-ci">
    Non-interactive detect, exit codes 0/2, ignores, optional URL scans.
  </Card>
  <Card title="Manage detector ignores" href="/manage-detector-ignores">
    ignoreRules, ignoreFiles, ignoreValues, scopes, and inline disable comments.
  </Card>
  <Card title="Installation" href="/installation">
    install/link/update paths, provider selection, project vs global, hooks consent.
  </Card>
  <Card title="Configuration reference" href="/configuration-reference">
    `.impeccable/config.json` and local override keys for detector and hooks.
  </Card>
  <Card title="Detector rules" href="/detector-rules">
    Rule ids, categories, advisory flag, engines, finding shape.
  </Card>
  <Card title="Environment variables" href="/environment-variables">
    IMPECCABLE_* and related env vars including bundle and OpenCode config dirs.
  </Card>
</CardGroup>
