# CLI reading

> pull, view, head, schema, manifest, search — every command for hub-published datasets.

All accept a ref (bare name resolves through [bindings](https://esker.so/docs/sdk/bindings.md); full ref accepted directly). All read-side commands accept `--json` for pipeable output. None require auth in phase 1 (manifests, schemas, parquet are public reads).

## esker pull

```
Usage: esker pull [OPTIONS] REF
  --output -o  PATH   default: output
```

Fetch a published dataset and content-hash verify the parquet.

`REF` may be:

- bare name → resolved through bindings
- `<owner>/<name>` → fetch latest manifest
- `<owner>/<name>@<version>` → fetch that specific version
- `<owner>/<name>@latest` → equivalent to no version

```
$ esker pull archie/us.treasury.yields
  archie/us.treasury.yields@2.0.0
  pipeline   2.0.0
  records    4,205
  published  2026-05-03 23:00 UTC
  by         archiewyles@gmail.com
  run        a7076934-be56-477b-a030-250e4492ec93
  content    sha256:79eeb5cb20...
  source     sha256:5a7d2c1f8b...
  saved output/us.treasury.yields.parquet
```

Sequence:

1. Resolve the ref through bindings (lifts bare names, applies lockfile pin).
2. Fetch the manifest (versionless = latest).
3. Download `data.parquet` to `<output>/<DOMAIN_ID>.parquet`.
4. Re-compute `content_hash` and compare against the manifest. Mismatch → red error, exit 1.
5. Print summary.

`pull` does **not** fetch the schema or lineage — just the parquet + manifest. To download lineage, hit the artifact URL directly.

## esker view

```
Usage: esker view [OPTIONS] REF
  -n / --rows  INTEGER >= 0  default: 5
  --json
```

One-line header + sample table. The "what is this" command.

```
$ esker view us.treasury.yields
  archie/us.treasury.yields@2.0.0 · 4,205 records · 2026-05-03 23:00 UTC

  quote_date  rate_1m  rate_3m  rate_6m  rate_1y  rate_2y
  2026-05-02  4.83     4.81     4.78     4.62     4.55
  ...

  9 fields · esker schema for shape · esker manifest for hashes
```

Default 5 rows. `-n 0` suppresses records, leaving header + footer only.

Synthesized `esker_*` fields are hidden. Use `esker head --all` to see them.

## esker head

```
Usage: esker head [OPTIONS] REF
  -n / --rows  INTEGER >= 1  default: 10
  --where TEXT     key=value (repeatable, AND-composed)
  --all
  --json
```

Records-only view, filterable.

```
$ esker head us.sec.companies --where ticker=AAPL
  cik         ticker  title
  0000320193  AAPL    Apple Inc.
```

`--where`:

- Splits on the first `=`.
- Repeatable (multiple flags AND-compose).
- Coerces to column dtype (bool/int/float; everything else stays string).
- Bool string: `true|1|yes` (case-insensitive) → `True`, otherwise `False`.
- Unknown column → red error + dim `available columns: …`.

`--all` reveals the synthesized `esker_*` columns (default hidden).

`--json` skips `--all` and emits the full record dicts as a list.

## esker schema

```
Usage: esker schema [OPTIONS] REF
  --remote
  --json
```

The schema as a typed table.

```
$ esker schema us.treasury.yields
  archie/us.treasury.yields@2.0.0
  via local

  quote_date         date                 not null
  rate_1m            float                nullable
  rate_3m            float                nullable
  ...
  esker_id           EskerID              not null
  esker_source_url   HttpUrl              not null
  esker_lineage_id   uuid                 not null
```

Origin tag is `local` or `remote` (dim). Resolution rules:

1. Bare name + registered locally → use local pipeline's schema. Header drops the `<owner>/` prefix (no published owner yet).
2. Bare name with binding (or full ref) + registered locally + unversioned → use local. Header is `<owner>/<domain>@<version>`.
3. Otherwise (or with `--remote`) → fetch `schema.json` from the hub.

`--remote` is the override when a local pipeline would otherwise win — useful for verifying the _published_ schema.

The schema table renders synthesized `esker_*` fields in dim, after author fields, in fixed order.

## esker manifest

```
Usage: esker manifest [OPTIONS] REF
  --json
```

The manifest as `key  value` lines.

```
$ esker manifest archie/us.treasury.yields
  archie/us.treasury.yields@2.0.0
  pipeline   2.0.0
  source     us.treasury.yields
  records    4,205

  ingested   2026-05-03 23:00 UTC
  published  2026-05-03 23:00 UTC

  by         archiewyles@gmail.com

  content    sha256:79eeb5cb20…3e
  digest     sha256:5a7d2c1f8b…ab
  lineage    sha256:5ef35cc434…da

  run        a7076934-be56-477b-a030-250e4492ec93
```

Group structure: identity → time → actor → integrity → run. Hashes are short-form in terminal mode, full in JSON.

## esker search

```
Usage: esker search [OPTIONS] QUERY
```

Disambiguate publishers of a name, or full-text search.

```
$ esker search ca.corporations.registry
  archie/ca.corporations.registry   1,235 pulls/30d
  bigcorp/ca.corporations.registry  421 pulls/30d · verified
  jdoe/ca.corporations.registry     12 pulls/30d
```

Behavior:

- Query matches `^[a-z0-9]+(\.[a-z0-9]+)+$` → disambiguation (who publishes this domain).
- Otherwise → full-text search.

Empty results → dim `no results`, exit 0.

Verified publishers get a `· verified` suffix (dim). Results pre-ranked: verified first, then by 30d pull volume.

No `--json`, no `--limit`. Surface is intentionally minimal.

## See also

- [CLI overview](https://esker.so/docs/cli/overview.md) — the visual contract
- [CLI bindings](https://esker.so/docs/cli/bindings.md) — what `add` does that makes bare-name reads work
- [Reading](https://esker.so/docs/sdk/reading.md) — the library equivalents (`esker.get`, `get_one`, `search`)
