Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions .claude/skills/quartr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,19 @@ explicitly passed, `--all` raises it to 500 to minimize round-trips.
```bash
# Companies
quartr companies list --tickers AAPL,MSFT --fields id,name,country
quartr companies resolve CE # every company using that ticker
quartr companies get 4742 --format json

# Events (earnings calls, AGMs, etc.)
quartr events list --tickers AAPL --sort-by date --direction desc --limit 10
quartr events list --tickers NYSE:BLD --expand company --limit 5
quartr events get 406161 --format json

# Transcripts
quartr transcripts list --tickers AAPL --expand event --limit 10
quartr transcripts list --tickers AAPL --expand event,company --limit 10
quartr transcripts get <id> --format json
quartr transcripts download <id> --output transcript.json
quartr transcripts download <id> --output - | jq . # stream, no file
quartr transcripts chapters <id> --levels 1,2

# Reports (10-K, 10-Q, 8-K, etc.)
Expand All @@ -111,9 +114,9 @@ quartr live list --states live,willBeLive
quartr live transcripts list --states live
quartr live transcripts stream <id> --transcript-version 1.7

# Lookup tables (use these to map names → IDs before filtering)
# Lookup tables (whole catalog, not a first page; map names → IDs before filtering)
quartr event-types list --format csv # Q1=26, Q2=27, Q3=28, Q4=29 …
quartr document-types list --format csv # 10-K=11, 10-Q=7, 8-K=10, 20-F=13
quartr document-types list --format csv # 10-K=11, 10-Q=7, 8-K=10, 25=shareholder letter
```

## Escape hatch
Expand All @@ -132,9 +135,29 @@ quartr request get /events --query tickers=AAPL --query limit=3 --format json
- **Companies use `ids`, not `companyIds`.** The CLI auto-maps `--company-ids`
to `ids` for the `companies` resource. Other resources use `companyIds`.
This only matters when reading raw API responses or using `request get`.
- **Only `events list` can sort.** `--sort-by` (fields `id`, `date`) exists
nowhere else and is rejected with exit 2, because those endpoints return rows
in insertion order — the newest filing or call is often *not* on the first
page. To get the latest documents: sort events, then filter by `--event-ids`,
or pull with `--all` and sort locally on `createdAt`. `--direction` works
everywhere but reverses insertion order, not date order.
- **Tickers collide across exchanges.** `--tickers CE` returns Celanese,
Credito Emiliano and Cortus Energy. Run `quartr companies resolve <ticker>`
when a symbol might be shared, then either use `--company-ids` or qualify the
ticker as `NYSE:BLD` (the CLI resolves it to a companyId before querying).
There is no name search in the API — tickers and CIKs only.
- **`--expand company` is a client-side join.** The API rejects
`expand=company`; the CLI strips it and batch-fetches `/companies` instead.
Use it whenever rows need to be attributable — otherwise they carry only a
bare `companyId` and a collision is invisible.
- **Tier-restricted endpoints** return `403 Forbidden` on the user's API tier.
Observed restrictions: `events summary`, `audio list`, `live transcripts list`.
Surface the error verbatim — do not retry, hide, or silently fall back.
The CLI prints a `hint:` line clarifying that 403 is entitlement, not
authentication. Surface the error verbatim — do not retry, hide, silently
fall back, or start debugging the API key. A rejected key returns 401.
- **Downloads always write a file** named `<resource>-<id>.<ext>` unless
`--output` says otherwise; the `Saved <path>` line goes to stderr. To pipe or
redirect the document itself, use `--output -`.
- **Downloads don't send the API key by default.** The metadata response
contains a public file URL. Add `--with-api-key` only if a 401/403 occurs
fetching the file URL itself.
Expand Down
34 changes: 27 additions & 7 deletions .claude/skills/quartr/references/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ specific flag or endpoint at hand.
| Command | Operations | Base path | Notes |
|--------------------|---------------------------------------------|----------------------------|--------------------------------|
| `auth` | `login`, `show`, `logout` | (local) | Manages `~/.config/quartr/config.json` |
| `companies` | `list`, `get` | `/companies` | Uses `ids` API param, not `companyIds` |
| `companies` | `list`, `get`, `resolve` | `/companies` | Uses `ids` API param, not `companyIds`; `resolve <ticker\|cik>` lists collision candidates |
| `events` | `list`, `get`, `summary` | `/events` | `summary` is tier-restricted |
| `documents` | `list`, `get`, `download` | `/documents` | Generic parent; prefer typed resources |
| `reports` | `list`, `get`, `summary`, `pages`, `download` | `/documents/reports` | `fileUrl` is the download field |
Expand All @@ -18,8 +18,8 @@ specific flag or endpoint at hand.
| `live` | `list`, `get` | `/live` | Honors `transcriptVersion` |
| `live audio` | `list`, `get`, `download` | `/live/audio` | Download field is `audio` |
| `live transcripts` | `list`, `get`, `stream` | `/live/transcripts` | `list` may be tier-restricted; stream field is `transcript` |
| `event-types` | `list`, `get` | `/event-types` | Lookup table |
| `document-types` | `list`, `get` | `/document-types` | Lookup table |
| `event-types` | `list`, `get` | `/event-types` | Lookup table; `list` returns the whole catalog |
| `document-types` | `list`, `get` | `/document-types` | Lookup table; `list` returns the whole catalog |
| `request` | `get` | (any path) | Escape hatch; `--query k=v --paginate` |

`live audio` and `live transcripts` accept either `quartr live audio …` or
Expand Down Expand Up @@ -50,7 +50,8 @@ Auth precedence: flags > env > config file > defaults.
--all follow pagination.nextCursor (auto-bumps limit to 500 if not set)
--fields a,b,c output columns; supports dotted paths

--tickers AAPL,MSFT comma-separated tickers
--tickers AAPL,MSFT comma-separated tickers; EXCHANGE:TICKER (NYSE:BLD) is
resolved to a companyId first, deduped case-insensitively
--company-ids 4742 maps to "ids" for companies, "companyIds" elsewhere
--countries US,GB ISO country codes
--exchanges NYSE,NASDAQ exchange symbols
Expand All @@ -61,19 +62,23 @@ Auth precedence: flags > env > config file > defaults.
--end-date 2024-12-31 ISO 8601
--updated-after 2024-01-01 incremental sync lower bound
--updated-before 2024-12-31
--expand event merge related objects into response
--expand event,company event is expanded by the API; company is joined client-side
--type-ids 1,2,3 events / documents* / transcripts* / reports* / slides* / audio*
--event-ids 128301 documents* / transcripts* / reports* / slides* / audio* / live*
--document-group-ids foo documents* / transcripts* / reports* / slides*
--states live,willBeLive live, live-transcripts, live-audio
--transcript-version 1.7 live, live-transcripts, transcripts (get only), audio (get only)
--sort-by date events list only
--sort-by id|date events list ONLY; rejected with exit 2 everywhere else
--levels 1,2 chapters subcommand on reports/slides/transcripts/audio
```

Filter flags that aren't allowed for a resource are silently dropped; the
allowed set is enforced by `paramSet` in `internal/cli/resources.go`.

Two exceptions are errors rather than silent drops, because silence produced
wrong answers: `--sort-by` on anything but `events list`, and `--expand
company` on rows that carry no companyId. Both exit 2.

## Per-operation flags beyond list

| Operation | Flag | Notes |
Expand All @@ -86,7 +91,8 @@ allowed set is enforced by `paramSet` in `internal/cli/resources.go`.
| `<r> summary` | `--fields` | Output columns |
| `<r> pages` | list flags | reports, slides only |
| `<r> chapters` | list flags + `--levels` | transcripts, audio only |
| `<r> download` | `--output PATH` | Defaults to `<resource>-<id>.<ext>` in cwd |
| `<r> download` | `--output PATH` | Defaults to `<resource>-<id>.<ext>` in cwd; `-` streams to stdout |
| `<r> download` | (status line) | `Saved <path>` goes to **stderr**, never stdout |
| `<r> download` | `--url-field NAME` | Defaults to `fileUrl` (or resource-specific) |
| `<r> download` | `--with-api-key` | Send `x-api-key` when fetching the file URL |
| `<r> download` | `--expand` | On the metadata request |
Expand Down Expand Up @@ -141,6 +147,16 @@ with `-`.
- Up to 3 attempts with exponential backoff (250ms, 500ms)
- Errors surface as `quartr api error: <status>: <body>` on final failure

## Exit codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | The request failed (API error, network, missing key) |
| 2 | The command line was wrong: unsupported `--sort-by`, `--expand company` on rows without a company, an exchange-qualified ticker matching nothing, a bad global flag |

A `2` is never transient. The message names the supported alternative.

## Lookup tables (run these once, then reference in flags)

```bash
Expand Down Expand Up @@ -174,6 +190,10 @@ quartr document-types list --format csv
# …
```

Both commands return the entire catalog (46 document types, 34 event types),
not a first page, so grepping their output is safe. Pass an explicit `--limit`
to page instead.

When the user names a filing form (10-K, 8-K, etc.), look up the `id` first
and pass it via `--type-ids`.

Expand Down
85 changes: 70 additions & 15 deletions .claude/skills/quartr/references/recipes.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,33 @@ For multiple tickers in one call:
quartr companies list --tickers AAPL,MSFT,NVDA --fields id,name,country
```

**Always check for a ticker collision first.** Quartr matches a ticker across
every exchange, so common US symbols also return foreign namesakes:

```bash
quartr companies resolve CE
# id name country matchedTickers
# 5977 Celanese Corporation US NYSE:CE
# 16679 Credito Emiliano S.p.A. IT BIT:CE
# 16930 Cortus Energy SE OM:CE
```

`resolve` takes a ticker, an `EXCHANGE:TICKER` pair, or a CIK, and lists every
candidate with the exchange pairs that matched. There is no name search — the
API has no `search`/`query`/`name` parameter — so never try to look a company
up by name.

Once the exchange is known, qualify the ticker anywhere `--tickers` is
accepted and the CLI resolves it to a companyId before querying:

```bash
quartr events list --tickers NYSE:BLD --limit 5
```

Known collisions seen in practice: `ACA` (Arcosa / Crédit Agricole), `BLD`
(TopBuild / Boral), `CE` (Celanese / Credito Emiliano), `WM`, `COST`, `TEL`,
`AVNT`.

When parsing programmatically, prefer:

```bash
Expand Down Expand Up @@ -78,27 +105,22 @@ typeId, companyId, language, …}`.

Three steps:

```bash
# 1. Get company ID (or use --tickers directly in step 2 if the API accepts it)
COMPANY_ID=$(quartr companies list --tickers AAPL --format json \
| jq -r '.data[0].id')

# 2. Find the latest 10-K (document type id 11)
quartr reports list --tickers AAPL --type-ids 11 \
--sort-by date --direction desc --limit 1 \
--fields id,fileUrl,eventId,createdAt
```
**`reports list` cannot sort.** `--sort-by` exists only on `events list`;
everywhere else the CLI rejects it with exit 2, because the endpoint returns
rows in insertion order and the newest filing is often not on the first page.
Do not reach for `--sort-by` here, and do not trust the first page.

The `reports list` endpoint may not accept `--sort-by` (it's events-only); if
so, list and pick the highest-`createdAt`:
Pull a wide page and sort locally:

```bash
quartr reports list --tickers AAPL --type-ids 11 --limit 5 --format json \
quartr reports list --tickers AAPL --type-ids 11 --all --format json \
| jq '.data | sort_by(.createdAt) | reverse | .[0]'
```

`--all` matters: with a small `--limit` the newest report may simply be
absent. Then download it:

```bash
# 3. Download
quartr reports download <id> --output apple-10k.pdf
```

Expand Down Expand Up @@ -137,6 +159,18 @@ quartr transcripts list --tickers AAPL --expand event --all --format json \
`--all` follows `pagination.nextCursor` and auto-bumps `--limit` to 500.
`--expand event` merges the parent event object into each transcript row.

Add `company` to the expansion when the rows need to be attributable — rows
otherwise carry a bare `companyId`, which is how a ticker collision goes
unnoticed:

```bash
quartr transcripts list --tickers AAPL --expand event,company --all --format json
```

`event` is expanded by the API; `company` is joined client-side by the CLI
(the API rejects `expand=company`), batching the distinct companyIds into
`/companies` lookups. It works on `list` and `get`.

Resulting shape:

```json
Expand Down Expand Up @@ -173,6 +207,17 @@ quartr transcripts list --tickers AAPL --all --format json \
done
```

To pipe one document straight through without touching disk, use
`--output -`; it streams the document to stdout and nothing else:

```bash
quartr transcripts download 432907 --output - | jq -r '.transcript.text'
```

Without `--output -` a download always writes a file (the `Saved <path>`
confirmation goes to stderr), so `download <id> > f.json` produces an empty
`f.json` and a file you did not name.

---

## 5. Stream a live earnings transcript
Expand Down Expand Up @@ -272,17 +317,27 @@ For event types (Q1/Q2/Q3/Q4 earnings calls, AGM, Investor Day):
quartr event-types list --format csv
```

Both lookup commands return the **whole** catalog (46 document types, 34 event
types) rather than one page, so a `grep` over them is trustworthy. Pass an
explicit `--limit` only if paging is wanted.

---

## 10. Empty results vs errors — how to tell the user

| Output | Meaning | What to say |
|-------------------------------------------|------------------------------------------------------|-------------|
| `No rows` | Valid API response with empty `data` array | "No matches for those filters." |
| `quartr api error: 403 Forbidden: …` | API tier doesn't include this endpoint | Quote the error; suggest narrowing scope or contacting Quartr to upgrade. |
| `quartr api error: 403 Forbidden: …` | API tier doesn't include this endpoint (the CLI prints a `hint:` line saying so) | Quote the error; it is entitlement, not auth — do not re-check the key. Suggest contacting Quartr to upgrade. |
| `quartr api error: 401 Unauthorized: …` | The key itself was rejected | Check `quartr auth show` and `QUARTR_API_KEY`. |
| `quartr api error: 400 Bad Request: …` | Bad parameter (e.g. unsupported `expand` value) | Check the message body — it usually names the offending field. |
| `quartr api error: 404 Not Found: …` | ID doesn't exist | Verify the ID via a list query first. |
| `missing API key; set QUARTR_API_KEY …` | No reachable credential | Ask user to set `QUARTR_API_KEY` or run `quartr auth login`. |

Don't retry 403/400/404 — they're not transient. The CLI already handles
429/5xx with backoff.

**Exit codes:** `0` success, `1` request failed, `2` the command line itself
was wrong (unsupported `--sort-by`, `--expand company` where rows have no
company, an exchange-qualified ticker that matches nothing). A `2` will never
be fixed by retrying — read the message, it names the alternative.
Loading