@alexanderolsen/fetcher
v0.1.2
Published
Durable CLI for pulling trace data from LangSmith (v2 API)
Maintainers
Readme
langsmith-fetcher
Durable CLI for bulk-pulling trace data from LangSmith via the v2 API
(POST /api/v2/runs/query), with a pleasant terminal experience.
Zero runtime dependencies. Node ≥ 20.
Install
Run instantly with npx (no install)
npx @alexanderolsen/fetcher # interactive wizard
npx @alexanderolsen/fetcher fetch --project <url> --last 24hFrom npm (global install)
npm install -g @alexanderolsen/fetcher
fetcher --helpFrom source
One command — builds the CLI and puts a fetcher launcher on your PATH
(at ~/.local/bin/fetcher; override with FETCHER_BIN_DIR):
git clone <repo-url> && cd fetcher
npm run install-cli
fetcher --helpThe launcher points at the repo's dist/, so after pulling updates just run
npm run build — no reinstall needed. To remove it: npm run uninstall-cli.
Alternatives
- No install:
npm install && npm start -- fetch --project my-project --last 24h - npm-style global link:
npm link→fetcher --help - Straight from git (auto-builds via
prepare):npm install -g git+<repo-url>
Quick start
Interactive mode (easiest)
Just run fetcher with no arguments. It walks you through everything:
- API key — auto-detected from
LANGSMITH_API_KEY, or prompted (masked) - Project URL — open the project in your browser, copy the URL, paste it
- Time window — last 1h / 24h / 7d, or a custom start/end range
- Output file — sensible timestamped default
- Data volume — full payloads vs. slim (fast) mode
- Filters — optional LangSmith trace/tree filter expressions
- Resume — if a checkpoint exists at the output path, resume or start fresh
You'll get a summary to confirm before anything is pulled. Ctrl-C exits cleanly.
Flags mode (scripts & CI)
export LANGSMITH_API_KEY=lsv2_pt_... # auto-detected (LANGCHAIN_API_KEY also works)
# Easiest: paste the project URL straight from the LangSmith UI
fetcher fetch --project "https://smith.langchain.com/o/<org-id>/projects/p/<project-id>" --last 24h
# ...or use a project name / UUID
fetcher fetch --project my-project --from 2024-06-01T00:00:00Z --to 2024-06-03T00:00:00Z --out june.jsonl--project accepts a UI URL, a project name, or a UUID. URLs from regional
UIs (e.g. eu.smith.langchain.com) automatically target the matching API
endpoint unless --api-url / LANGSMITH_ENDPOINT is set. LANGSMITH_PROJECT
provides a default project.
Env vars honored: LANGSMITH_API_KEY, LANGSMITH_ENDPOINT (EU/self-hosted),
LANGSMITH_WORKSPACE_ID, LANGSMITH_PROJECT. CLI flags override.
What you get
<out>— flat runs, one JSON object per line (written + fsync'd incrementally)<base>.traces.jsonl— one trace per line:{trace_id, start_time, end_time, run_count, runs[]}with runs sorted bydotted_order. Includes full tool/LLM input & output payloads (unless--slimor--selectis used).
Durability
Every page checkpoints a cursor to
<out>.state.json(atomic write).Ctrl-C pauses cleanly; resume any interrupted pull with just its path:
fetcher resume traces.jsonl # or traces.jsonl.state.jsonThe original project, time window, filters, selects, and endpoint are all restored from the checkpoint — no flags needed. (
--api-urloverrides if the instance moved.)A crash leaves a valid truncated JSONL + resumable cursor.
--freshrestarts.Output paths are bound to job params — a mismatched window/project won't silently append to the wrong file.
Rate limiting
v2 rate limits are undocumented, so the client paces itself (--rate, default
5 req/s), honors Retry-After, backs off exponentially on 429/5xx with
jitter, halves its pacing rate on 429 and recovers additively on success.
Retries and rate-limit events surface in the terminal as they happen.
Notes / caveats
- The v2 API is alpha — the request/response contract may change. All v2
traffic is isolated in
src/client.ts. - The assembly pass (
runs.jsonl→traces.jsonl) holds runs in memory. For very large windows use--flatand group downstream. min_start_timeis inclusive,max_start_timeexclusive.--filtermatches individual runs and can yield partial trees; prefer--trace-filter/--tree-filterwhen you need whole traces.
