# CLI Reference

> Documentation index: [llms.min.txt](https://caseyrfsmith.github.io/scull/llms.min.txt) · Document manifest: [documents.json](https://caseyrfsmith.github.io/scull/documents.json)

Breadcrumbs: Reference > CLI Reference

## Installation

```bash
# Core CLI only (list, validate, concept subcommands — JSON output)
pip install -e .  # or: uv sync

# With semantic search capability
pip install -e ".[search]"

# Or with fully local semantic search
pip install -e ".[local]"

# Full setup: search + build tools + query server
pip install -e ".[search,build,server]"
```

| Extra      | Packages                   | Commands                                    |
| ---------- | -------------------------- | ------------------------------------------- |
| *(none)*   | click, pyyaml, numpy       | `list`, `validate`, `concept` subcommands   |
| `[search]` | voyageai, openai           | `search`, `dedup`                           |
| `[local]`  | fastembed                  | Offline `search`, `dedup`, and index builds |
| `[build]`  | litellm, jsonschema        | Schemafier pipeline, `--format=human`       |
| `[server]` | fastapi, uvicorn, pydantic | HTTP query server                           |

```bash
scull <command> [arguments] [options]
```

Every command that produces output takes `--format` to switch between human-readable and JSON (`get`/`caveats`/`shape` accept `--format json|human`; `context`/`list`/`search`/`related`/`dedup` accept `--format text|json`). Core install requires only `click`, `pyyaml`, and `numpy`. Optional features require additional packages:

| Extra      | Packages                   | Commands                                                                             |
| ---------- | -------------------------- | ------------------------------------------------------------------------------------ |
| *(none)*   | click, pyyaml, numpy       | `list`, `validate`, `concept` subcommands (JSON output)                              |
| `[search]` | voyageai, openai           | `search` command, embedding-based dedup                                              |
| `[local]`  | fastembed                  | Offline `search`, embedding-based dedup, local index builds                          |
| `[build]`  | litellm, jsonschema        | `--format=human` for `get`/`caveats` (LLM reconstitution), scull-schemafier pipeline |
| `[server]` | fastapi, uvicorn, pydantic | Query server (`uvicorn scull.schemafier.server.main:app`)                            |

## Environment Variables

| Variable                  | Purpose                                                       | Default                               |
| ------------------------- | ------------------------------------------------------------- | ------------------------------------- |
| `SCULL_SCHEMA_PATH`       | Override schemas directory location                           | Auto-discovered (`schemas/` from cwd) |
| `SCULL_EMBED_PROVIDER`    | Embedding provider (`voyage`, `openai`, or `local`)           | `"voyage"`                            |
| `VOYAGE_API_KEY`          | API key for Voyage AI                                         | *unset*                               |
| `OPENAI_API_KEY`          | API key for OpenAI                                            | *unset*                               |
| `SCULL_EMBED_MODEL`       | Model name override (e.g., `"text-embedding-3-small"`)        | Provider default                      |
| `SCULL_EMBED_CACHE_DIR`   | Local model download/cache directory                          | FastEmbed default                     |
| `SCULL_EMBED_TIMEOUT`     | Per-request timeout (seconds) for the embed provider's client | `10`                                  |
| `SCULL_EMBED_MAX_RETRIES` | Client-level retry count on transient embed failures          | `1`                                   |
| `SCULL_MODEL`             | Default LLM model for `--format=human`                        | *unset*                               |

The nearest `scull.yaml` in the current directory or its parents may provide the corresponding
project defaults without repeated environment variables:

```yaml
defaults:
  schemas_dir: schemas
  kg_dir: kg
  embed_provider: local
  embed_cache_dir: .cache/embeddings
```

## Commands

### `scull list [--format text|json]`

List all available concepts with field and caveat counts. Human-readable output shows a table with aligned columns; `--format json` outputs structured data. (`--json` still works as a deprecated alias for `--format json`.)

```bash
$ scull list

  Concept                              Fields  Caveats Status
  ───────────────────────────────────    ────    ───── ────

  deployment_config                        4       12  ⚠ needs_review
  job_runtime                              8       15
  ...

$ scull list --format json
[{"name": "deployment_config", "fields": 4, "caveats": 12, "needs_review": true}, ...]
```

### `scull validate [--release]`

Validate all schema files against required structure. Returns exit code 0 on success, 1 on errors. Output uses color-coded checkmarks/error counts when running in a terminal.

Unreadable files, invalid YAML or schema shapes, unsupported format versions, duplicate concept
names, dangling or malformed caveat attachments, stale content hashes, and an invalid
configured schema directory are validation errors. They fail the command even when other
schemas are valid; a parse warning cannot turn an invalid file into a successful validation.
An existing directory containing no schema files reports `No schemas found.` and exits 0.

`--release` additionally rejects an empty schemaset, `needs_review: true`, missing approval
metadata, and approval fingerprints made stale by any later edit. Passing it confirms structure and
a current human-review record, not factual accuracy or completeness.

```bash
$ scull validate
✓ 18 schema(s) valid.

$ echo $?
0
```

Errors are numbered and grouped by concept:

```bash
✗ 3 validation error(s):

    1. ERROR: deployment_config.fields.values: missing 'value_type'
    2. ERROR: query_operators.caveats.div-by-zero: missing 'evidence_hash'
    3. ERROR: job_runtime.caveats.retry-loop: invalid severity 'critical'
```

### `scull get <concept> <field> [<field> ...] [--format json|human] [--model MODEL]`

Get one or more field definitions from a concept. Default is raw JSON (zero inference). With
`--format=human`, exactly one field is accepted and an LLM renders prose (requires `[build]` extra +
`--model`).

```bash
$ scull get deployment_config values

{
  "values": {
    "value_type": "map[string]string",
    "description": "...",
    "confidence": "high"
  }
}

$ scull get deployment_config values --format=human --model provider/model

Values is a map of string keys to string values.
...
```

### `scull caveats <concept> [--severity high|medium|low] [--format json|human]`

List caveats for a concept. Human-readable output groups by severity level (high → medium → low), showing numbered entries with summary, evidence preview, and `applies_to` hints. `--severity` filters to a single level.

```bash
$ scull caveats deployment_config

  Caveats for deployment_config

  [HIGH]  Configuration must exist before a workload references it...
  [MEDIUM]  A workload and its configuration must share a scope...

$ scull caveats deployment_config --severity high

  Caveats for deployment_config

  [HIGH]  Configuration payloads have a fixed size limit...
  [HIGH]  Configuration values are not an encrypted secret store...
```

### `scull context <concept> <field> [...] [--situation TAG] [--detail] [--format json|text]`

Return named field definitions together with every caveat attached to any requested field and every
general caveat for the concept. Multiple fields may be separate arguments or comma-separated. An
attached caveat that covers multiple requested fields appears once and retains its full
`applies_to` list.

This command reads only schema YAML. It does not require a KG, embedding provider, API key, account,
or network connection.

Repeat `--situation` to supply curated usage tags. Tagged caveats are returned only when their tag
hierarchy overlaps; caveats with no `applies_when` metadata remain unconditional. Omitting the option
returns the complete set, preserving the conservative default for existing callers and schemas.

```bash
$ scull context schema schema_hash sources
$ scull context schema schema_hash,sources --format text
$ scull context deployment_config values --situation payload.size
```

The default JSON is compact for agents. It separates `caveats.attached` from `caveats.general` and
keeps field definitions, qualified paths, required scopes, concise constraints, examples/default
annotations, completeness, and inspection links without full interpretation records. It also
includes schema provenance and review state. Add `--detail` for complete scoped records, or use
`scull inspect-schema` with a returned rule link for bounded original evidence.
Compact mode groups artifact warnings by kind and count instead of repeating every mechanical
warning record.

### `scull search <query> [--top-k N] [--kg KG_DIR] [--concepts C1,C2] [--format text|json]`

Semantic search across all embedded concepts using hybrid scoring (cosine similarity + lexical
overlap boost). Results are bounded semantic field units. A retrieved field bundle expands its
members without consuming more result slots, and reviewed attached caveats are nested with explicit
`Applies when` conditions. These are conditional context, not claims that the query satisfies the
condition. The default text format is the recommended agent interface. Requires `[search]` for
Voyage/OpenAI or a supported local embedding extra.

```bash
$ scull search "how do I make config immutable"

  Results for: how do I make config immutable

  Score      Type
  1.0000    FIELD UNIT  [payments]
           immutable: When true, prevents changes to data and binaryData...
           HIGH  Existing consumers are not restarted automatically...
             Applies when: consume.runtime (conditional context)
```

Options:

- `--top-k N`: Number of results (default: 5)
- `--concepts runtime_*`: Restrict search to specific concepts (comma-separated)
- `--max-caveats-per-unit N`: Bound nested caveats for each unit (default: 8)
- `--max-caveats-total N`: Bound nested caveats for the response (default: 40)
- `--format json`: Output the same structured semantic units and truncation metadata as JSON

If caveats are truncated, text and JSON expose the omitted count and a deterministic `context`
follow-up instead of silently dropping the remaining context.

### `scull related <concept> [field]`

Show caveats related to a concept, optionally filtered to a specific field. Groups by field, showing
caveat summaries with severity tags. This reads graph edges from the index but does not embed the
query or call an embedding provider.

```bash
$ scull related deployment_config

  Caveats for deployment_config

  (general) (6)
    [HIGH]  Configuration must exist before a workload references it...

  data (17)
    [HIGH]  Configuration payloads have a fixed size limit...
    [HIGH]  Configuration values are not an encrypted secret store...
```

### `scull dedup [--threshold FLOAT] [--format text|json]`

Show near-duplicate caveats detected by embedding similarity during KG build. Reports pairs exceeding the cosine similarity threshold, with scores, IDs, and summaries truncated for review. Useful for manual deduplication decisions.

```bash
$ scull dedup

  Found 67 near-duplicate pair(s):

  Pair  1  Score: 0.9821  [deployment_config]

    A: mounted-values-not-refreshed
       A workload using a mounted configuration snapshot will not receive updates…

    B: mounted-snapshot-no-auto-update
       A mounted configuration snapshot does not receive later changes…

  Tip: Review these pairs with 'scull caveats <concept>' to decide which to remove.
```

Options:

- `--threshold 0.95`: Higher threshold means fewer, more similar pairs (default: 0.90)

### `scull concept <name> list-fields`

List all field names for a concept with type and confidence columns.

```bash
$ scull concept query_operators list-fields

Field                          Type         Confidence
───────────────────────────────  ────          ────────

bitwise_operators      string       medium
pipe_operator          operator     medium
try_operator           operator     medium
cast_operator          operator     medium
```

### `scull concept <name> get <field> [--format json|human]`

Alias for `scull get <concept> <field>` via the concept subgroup. Same options apply.

```bash
$ scull concept query_operators get pipe_operator
```

### `scull concept <name> caveats [--severity LEVEL]`

Alias for `scull caveats <concept>` via the concept subgroup. Same options apply.

```bash
$ scull concept query_operators caveats --severity high
```

## Color Support

All commands auto-detect whether stdout is a TTY and adjust output accordingly:

- Terminal sessions: ANSI colors for severity levels (red/yellow/blue), green scores, cyan matched terms
- Pipes/redirects: Colors disabled automatically

Explicit control: colors follow standard terminal detection heuristics. To force colors in non-TTY contexts, set `CLICOLOR=1`.
