{"id":45915396,"url":"https://github.com/derickschaefer/reserve","last_synced_at":"2026-06-10T01:01:01.442Z","repository":{"id":337943964,"uuid":"1155826125","full_name":"derickschaefer/reserve","owner":"derickschaefer","description":"A modern command-line interface (CLI) for interfacing with the Federal Reserve Bank of St. Louis FRED API.","archived":false,"fork":false,"pushed_at":"2026-05-30T19:27:46.000Z","size":61561,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T21:20:50.847Z","etag":null,"topics":["ai","cli","cross-platform","data-pipeline","data-toolbox","fred","fred-cli","golang"],"latest_commit_sha":null,"homepage":"https://reservecli.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/derickschaefer.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T00:16:17.000Z","updated_at":"2026-05-29T19:27:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/derickschaefer/reserve","commit_stats":null,"previous_names":["derickschaefer/reserve"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/derickschaefer/reserve","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derickschaefer%2Freserve","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derickschaefer%2Freserve/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derickschaefer%2Freserve/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derickschaefer%2Freserve/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/derickschaefer","download_url":"https://codeload.github.com/derickschaefer/reserve/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derickschaefer%2Freserve/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34132030,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai","cli","cross-platform","data-pipeline","data-toolbox","fred","fred-cli","golang"],"created_at":"2026-02-28T07:39:36.318Z","updated_at":"2026-06-10T01:01:01.416Z","avatar_url":"https://github.com/derickschaefer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# reserve\n\nA command-line tool for exploring, retrieving, and analyzing economic data from the\nFederal Reserve Bank of St. Louis FRED® API.\n\n\u003e FRED® is a registered trademark of the Federal Reserve Bank of St. Louis.  \n\u003e Data sourced from FRED®, Federal Reserve Bank of St. Louis; https://fred.stlouisfed.org/  \n\u003e This project is not affiliated with or endorsed by the Federal Reserve Bank of St. Louis.\n\n---\n\n## Table of Contents\n\n- [Why reserve?](#why-reserve)\n- [Install](#install)\n- [Release Integrity](#release-integrity)\n- [Quick Start](#quick-start)\n- [Design Philosophy](#design-philosophy)\n- [The Command Model](#the-command-model)\n- [Command Reference](#command-reference)\n  - [completion](#completion) — shell completion scripts\n  - [series](#series) — discover and inspect data series\n  - [obs](#obs) — retrieve observations\n  - [category](#category) — browse the data hierarchy\n  - [release](#release) — data releases\n  - [source](#source) — data source institutions\n  - [tag](#tag) — search by tag\n  - [search](#search) — global full-text search\n  - [meta](#meta) — batch metadata retrieval\n  - [fetch](#fetch) — accumulate data locally\n  - [transform](#transform) — pipeline operators\n  - [window](#window) — rolling statistics\n  - [analyze](#analyze) — statistical analysis\n  - [cache](#cache) — manage local database\n  - [alias](#alias) — local series aliases with optional notes\n  - [config](#config) — configuration management\n  - [version](#version) — binary version and build info\n  - [update](#update) — release update checks\n  - [onboard](#onboard) — machine-readable onboarding context\n- [Pipeline Usage](#pipeline-usage)\n- [Output Formats](#output-formats)\n- [Global Flags](#global-flags)\n- [Configuration](#configuration)\n- [Changelog](#changelog)\n- [License](#license)\n\n---\n\n## Why reserve?\n\nThe FRED® API is one of the richest free economic data sources in the world — 800,000+ series, updated continuously. But most tools that wrap it are platform-locked, dependency-heavy, or require a running database server just to get started.\n\n`reserve` takes a different approach:\n\n- **Cross-platform, zero-dependency binary.** Written in Go, `reserve` compiles to a single static executable with no runtime, no interpreter, and no external libraries to install. Run the same binary on Linux x86-64, Windows, ARM servers, and Apple Silicon — natively, without emulation.\n\n- **Command-object model.** Every subcommand is a first-class object with a defined input schema, validation, and a uniform `Result` envelope. Commands compose cleanly, behave predictably, and are trivial to extend. No monolithic scripts, no implicit globals.\n\n- **Embedded database — no server required.** Observation data is persisted in a single embedded database file that is created on the fly. The actual embedded database is [bbolt](https://github.com/etcd-io/bbolt), a proven embedded key-value store used in production systems. It can scale to hold tens of millions of datapoints with ease. No Postgres, no SQL Server, no running process. If your use cases require data to be centralized in a server or cloud data platform such as Snowflake, comma-separated value outputs are supported throughout reserve.\n\n- **Pipeline-ready for large data environments.** `reserve` speaks JSONL on stdin/stdout — the lingua franca of Unix data pipelines. Chain transforms and analyses with `|`, redirect to files, or feed downstream tools. Every operator is NaN-aware and handles FRED's missing-value conventions correctly at scale. CSV formatting is also supported for importing data into other data stores or spreadsheets.\n\n- **LLM and agentic workflow ready.** JSONL is the native input format for modern AI pipelines. Pipe `reserve` output directly into LLM tool-call chains, vector embedding workflows, or agentic analysis frameworks — economic time series, transformed and structured, exactly where your model expects it.\n\n- **Built-in rate limiting and retry logic.** The API client enforces a configurable token-bucket rate limiter and exponential backoff on transient failures — the right defaults for shared financial data environments where API quotas matter.\n\n- **Idiomatic Go semantics throughout.** Structured logging via `slog`, context cancellation on every HTTP call, bounded concurrency with `sync.WaitGroup` and semaphores, deterministic output ordering, and clean separation between packages. The codebase is readable, testable, and auditable.\n\n- **Small, fast, and self-contained.** The compiled binary is under 15 MB. Cold start is measured in milliseconds. Analysis on years of monthly data runs in memory without paging. The right tool for automated pipelines, cron jobs, and production data workflows — not just interactive exploration.\n\n---\n\n## Install\n\n```bash\ncurl -fsSL https://download.reservecli.dev/install.sh | sh\n```\n\nPinned version:\n\n```bash\ncurl -fsSL https://download.reservecli.dev/install.sh | sh -s v1.1.8\n```\n\nWindows PowerShell:\n\n```powershell\nirm https://download.reservecli.dev/install.ps1 | iex\n```\n\nThese installers download from your configured `download.reservecli.dev` distribution endpoint. Publishing to that endpoint is a manual release step. The release payload now includes a root-level `release.json` manifest that powers `reserve update check`.\n\nFrom source:\n\n```bash\ngit clone https://github.com/derickschaefer/reserve\ncd reserve\nmake build\n```\n\nRequires Go 1.26.3+ for source builds.\n\nFor distributed release binaries, use the stripped release target:\n\n```bash\nmake build-release\n```\n\n`make build` keeps symbols for local debugging. `make build-release` applies Go linker flags `-s -w` to remove the symbol table and DWARF debug information for smaller shipped binaries.\n\n---\n\n## Release Integrity\n\nRelease artifacts are signed with **keyless Sigstore/cosign signatures** from\nGitHub Actions OIDC.\n\n- Workflow: `.github/workflows/release-keyless.yml`\n- Verification guide: [`docs/release-security.md`](docs/release-security.md)\n\nQuick verification (after downloading release assets from your distribution endpoint):\n\n```bash\nsha256sum -c SHA256SUMS\ncosign verify-blob \\\n  --certificate SHA256SUMS.pem \\\n  --signature SHA256SUMS.sig \\\n  --certificate-identity-regexp '^https://github.com/derickschaefer/reserve/\\.github/workflows/release-keyless\\.yml@refs/tags/v[0-9].*$' \\\n  --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \\\n  SHA256SUMS\n```\n\n---\n\n## Quick Start\n\n**1. Get a free API key**\n\nRegister at https://fred.stlouisfed.org/docs/api/api_key.html\n\n**2. Configure**\n\n```bash\nreserve config init\nreserve config set api_key YOUR_KEY_HERE\n```\n\nOr set via environment variable:\n\n```bash\nexport FRED_API_KEY=YOUR_KEY_HERE\n```\n\n**3. Explore live data**\n\n```bash\nreserve series search \"unemployment rate\" --limit 5\nreserve series get UNRATE\nreserve obs get UNRATE --start 2020-01-01\nreserve obs latest GDP UNRATE CPIAUCSL\nreserve update check\n```\n\n**4. Accumulate data locally for analysis**\n\n```bash\nreserve fetch series GDP CPIAUCSL UNRATE FEDFUNDS --start 2010-01-01 --store\nreserve obs get GDP --from cache\n```\n\n**5. Run the analysis pipeline**\n\n```bash\n# Quarter-over-quarter GDP growth with summary statistics\nreserve obs get GDP --from cache --format jsonl | reserve transform pct-change | reserve analyze summary\n\n# Long-run unemployment trend\nreserve obs get UNRATE --from cache --format jsonl | reserve analyze trend\n\n# Annual CPI averages\nreserve obs get CPIAUCSL --from cache --format jsonl | reserve transform resample --freq annual --method mean\n```\n\n---\n\n## Design Philosophy\n\n`reserve` operates in two distinct modes:\n\n**Live mode** — Discovery and retrieval commands (`series`, `obs`, `category`, `search`, etc.) hit the FRED API directly by default. `obs get` uses `--from live` implicitly when no source is specified.\n\n**Analysis mode** — You explicitly accumulate data into a local [bbolt](https://github.com/etcd-io/bbolt) database using `fetch series --store`, then read it back with `obs get --from cache`. That makes analysis fast, reproducible, and offline-capable.\n\nThe pipeline is Unix-native. Commands that produce observations write JSONL to stdout; transform and analyze commands read JSONL from stdin. Chain them with `|`. When stdout is a terminal, output defaults to a formatted table. When piped, it defaults to JSONL.\n\n---\n\n## The Command Model\n\n`reserve` uses a pragmatic command model that is worth understanding before you explore the full command reference.\n\nMost commands follow a **noun-verb** pattern: the top-level command names a resource, and its subcommands are operations on that resource. This maps naturally onto the structure of the FRED API and the local data model.\n```\nreserve series get UNRATE            # noun: series  / verb: get\nreserve category tree root           # noun: category / verb: tree\nreserve release list                 # noun: release  / verb: list\nreserve obs get CPIAUCSL --from cache # noun: obs     / verb: get\nreserve config set api_key XYZ      # noun: config   / verb: set\n```\n\n`obs` is still a normal FRED wrapper noun. It is slightly unusual only because the name is abbreviated; conceptually it belongs alongside `series`, `category`, `release`, `source`, `tag`, and `meta`.\n\n`onboard` is different: it is a support/meta command that emits machine-readable documentation for agents, LLMs, and advanced users.\n```\nreserve obs get UNRATE --start 2020-01-01   # noun: obs (observations)\nreserve onboard --topic pipeline            # onboarding context for agents and advanced users\n```\n\n**Pipeline operators** — `transform`, `window`, `analyze`, and `chart` — are pure verbs. They have no resource noun because they do not target a named entity. They operate on whatever JSONL stream arrives on stdin. The data source is implicit, so there is nothing meaningful to name.\n```\n... | reserve transform pct-change --period 12\n... | reserve window roll --stat mean --window 6\n... | reserve analyze trend\n... | reserve chart plot\n```\n\nFinally, `fetch` and `search` are action-oriented commands rather than resource nouns. `fetch` performs batch acquisition across supported entity types, while `search` performs full-text query across supported global entities such as series and tags.\n```\nreserve fetch series GDP UNRATE CPIAUCSL --store\nreserve search \"yield curve\"\n```\n\nIn summary:\n\n| Class | Pattern | Examples |\n|---|---|---|\n| FRED API wrappers | noun verb | `obs`, `series`, `category`, `release`, `source`, `tag`, `meta` |\n| Local state operations | noun verb | `cache`, `config` |\n| Support / meta commands | noun verb | `onboard` |\n| Pipeline operators | verb only | `transform`, `window`, `analyze`, `chart` |\n| Batch acquisition | verb noun | `fetch` |\n| Standalone query | verb only | `search` |\n| Utility | standalone | `version`, `update`, `completion`, `help` |\n\nThe noun-verb commands follow consistent flag conventions and produce the same `Result` envelope. The pipeline operators follow consistent stdin/stdout JSONL semantics. Within each class, behavior is uniform and predictable.\n\n## Command Reference\n\n### completion\n\nGenerate shell completion scripts for bash, zsh, fish, or PowerShell.\n\n```bash\nreserve completion [bash|zsh|fish|powershell]\n```\n\nExamples:\n\n```bash\nsource \u003c(reserve completion bash)\nsource \u003c(reserve completion zsh)\nreserve completion fish | source\n```\n\n---\n\n### series\n\nDiscover and inspect FRED data series. Use `series get` for immediate metadata lookup on known IDs; use `fetch` when you want batch acquisition workflows.\n\n```bash\nreserve series get \u003cSERIES_ID...\u003e           # metadata for one or more series\nreserve series search \"\u003cquery\u003e\" [--limit N] # full-text search\nreserve series tags \u003cSERIES_ID\u003e             # tags applied to a series\nreserve series categories \u003cSERIES_ID\u003e       # categories a series belongs to\n```\n\nExamples:\n\n```bash\nreserve series get CPIAUCSL\nreserve series get GDP UNRATE CPIAUCSL --format json\nreserve series search \"consumer price index\" --limit 10\nreserve series tags UNRATE\nreserve series categories GDP\n```\n\n---\n\n### obs\n\nFetch time series observations from a selected source. The default source is live FRED API access. Use `obs get` for immediate retrieval on stdout; use `fetch series --store` when you want to build or refresh a reusable local dataset first.\n\n```bash\nreserve obs get \u003cSERIES_ID...\u003e [flags]\nreserve obs latest \u003cSERIES_ID...\u003e\n```\n\nFlags for `obs get`:\n\n```\n--start YYYY-MM-DD   start date\n--end   YYYY-MM-DD   end date\n--freq  daily|weekly|monthly|quarterly|annual\n--units lin|chg|ch1|pch|pc1|pca|cch|cca|log\n--agg   avg|sum|eop\n--from  live|cache    data origin (default: live)\n--limit N            max observations (0 = all)\n```\n\nUnits reference: `lin` = levels, `pch` = % change, `pc1` = % change from year ago, `log` = natural log.\n\nExamples:\n\n```bash\nreserve obs get UNRATE --start 2020-01-01 --end 2024-12-31\nreserve obs get GDP --from cache\nreserve obs get GDP --from cache --format jsonl\nreserve obs get CPIAUCSL --freq monthly --units pc1    # year-over-year % change\nreserve obs get GDP CPIAUCSL --format csv --out data.csv\nreserve obs latest GDP UNRATE CPIAUCSL FEDFUNDS\n```\n\n`reserve obs latest` table output prints one citation footer for the result set. If all series share the same source, it prints `Source: ...`. If multiple unique sources are present, it prints one compact `Sources:` line with semicolon-separated entries.\n\nFor multi-series table output, reserve now prints a per-series citation block:\n\n```text\nSources by series:\n- UNRATE: Bureau of Labor Statistics via FRED\n- GDP: Bureau of Economic Analysis via FRED\n- WFHCOVIDFRACMATMEN: Barrero, Jose Maria; Davis, Steven J.; Bloom, Nick via FRED\n```\n\n---\n\n### category\n\nBrowse the FRED category hierarchy.\n\n```bash\nreserve category get \u003cCATEGORY_ID\u003e\nreserve category list \u003cCATEGORY_ID|root\u003e\nreserve category tree \u003cCATEGORY_ID|root\u003e [--depth N]\nreserve category series \u003cCATEGORY_ID\u003e [--limit N]\n```\n\nExamples:\n\n```bash\nreserve category list root               # top-level categories\nreserve category tree 32991 --depth 2  # subtree with depth limit\nreserve category series 32991          # series within a category\n```\n\n---\n\n### release\n\nExplore scheduled FRED data releases.\n\n```bash\nreserve release list\nreserve release get \u003cRELEASE_ID\u003e\nreserve release dates \u003cRELEASE_ID\u003e\nreserve release series \u003cRELEASE_ID\u003e [--limit N]\n```\n\n`release get --format json` includes associated source institutions under `sources[]`.\n\n---\n\n### source\n\nExplore the institutions that provide data to FRED.\n\n```bash\nreserve source list\nreserve source get \u003cSOURCE_ID\u003e\nreserve source releases \u003cSOURCE_ID\u003e\n```\n\n---\n\n### tag\n\nSearch and explore FRED tags.\n\n```bash\nreserve tag search \"\u003cquery\u003e\" [--limit N]\nreserve tag series \u003cTAG...\u003e [--limit N]\nreserve tag related \u003cTAG\u003e [--limit N]\n```\n\n---\n\n### search\n\nGlobal full-text search across supported global entity types.\n\n```bash\nreserve search \"\u003cquery\u003e\" [--type series|tag|all] [--limit N]\n```\n\nExamples:\n\n```bash\nreserve search \"consumer price index\" --type series --limit 10\nreserve search \"employment\" --type all\n```\n\n---\n\n### meta\n\nBatch metadata retrieval for any entity type.\n\n```bash\nreserve meta series \u003cSERIES_ID...\u003e\nreserve meta category \u003cCATEGORY_ID...\u003e\nreserve meta release \u003cRELEASE_ID...\u003e\nreserve meta tag \u003cTAG...\u003e\nreserve meta source \u003cSOURCE_ID...\u003e\n```\n\n---\n\n### fetch\n\nFetch metadata or observations from the FRED API in batch. Use `series get` or `obs get` when you want data immediately on stdout; use `fetch`, especially `fetch series --store`, when you want to acquire and persist a reusable local working set.\n\nIf you need several series, prefer one multi-series `fetch series` call over many one-off fetches. reserve already performs bounded concurrent retrieval with a shared rate limiter for the batch.\n\n```bash\nreserve fetch series \u003cSERIES_ID...\u003e [--start YYYY-MM-DD] [--end YYYY-MM-DD] [--store]\nreserve fetch category \u003cCATEGORY_ID|root\u003e\nreserve fetch query \"\u003cquery\u003e\" [--limit N]\n```\n\nFor `fetch series`:\n\n```\n--store              fetch observations and persist them to the local database; also stores series metadata\n--with-meta          include series metadata in the output result\n--with-obs           include observations in the output result\n--start YYYY-MM-DD   start date for fetched observations\n--end   YYYY-MM-DD   end date for fetched observations\n```\n\nExamples:\n\n```bash\n# Build a local dataset with four core macro series from 2010 onward\nreserve fetch series GDP CPIAUCSL UNRATE FEDFUNDS --start 2010-01-01 --store\n\n# Refresh one cached series from a known start date\nreserve fetch series GDP --start 2010-01-01 --store\n\n# Return observations to stdout without storing them locally\nreserve fetch series GDP CPIAUCSL --with-obs --start 2020-01-01 --format json\n```\n\nStored data is written to `~/.reserve/reserve.db` by default (override with `db_path` in `config.json` or the `RESERVE_DB_PATH` environment variable). There is no automatic expiry on stored observations.\n\n---\n\n### transform\n\nPipeline operators. Each reads JSONL from stdin, applies a transformation, and writes JSONL to stdout.\n\n```bash\nreserve transform pct-change [--period N]\nreserve transform diff [--order 1|2]\nreserve transform log\nreserve transform index --base 100 --at YYYY-MM-DD\nreserve transform normalize [--method zscore|minmax]\nreserve transform resample --freq monthly|quarterly|annual --method mean|last|sum\nreserve transform filter [--after YYYY-MM-DD] [--before YYYY-MM-DD] \\\n                         [--min N] [--max N] [--drop-missing]\n```\n\n| Operator | Description |\n|---|---|\n| `pct-change` | `(v[t] − v[t-N]) / |v[t-N]| × 100`. Default period=1 (period-over-period). Use `--period 12` for year-over-year on monthly data. |\n| `diff` | First difference `v[t] − v[t-1]`, or second difference with `--order 2`. |\n| `log` | Natural log of each value. Non-positive inputs produce NaN with a warning. |\n| `index` | Re-scales the series so the value at `--at` equals `--base` (default 100). |\n| `normalize` | Z-score standardization (`zscore`) or min-max scaling to 0–1 (`minmax`). |\n| `resample` | Downsample to a lower frequency. `mean` averages the period, `last` takes the final value, `sum` accumulates. |\n| `filter` | Retain observations within a date range or value bounds. `--drop-missing` removes NaN rows. |\n\nExamples:\n\n```bash\n# Quarter-over-quarter GDP growth rate\nreserve obs get GDP --from cache --format jsonl | reserve transform pct-change\n\n# Year-over-year CPI inflation (monthly data)\nreserve obs get CPIAUCSL --from cache --format jsonl | reserve transform pct-change --period 12\n\n# Index GDP to 100 at the start of 2010\nreserve obs get GDP --from cache --format jsonl | reserve transform index --base 100 --at 2010-01-01\n\n# Annual average CPI\nreserve obs get CPIAUCSL --from cache --format jsonl | reserve transform resample --freq annual --method mean\n\n# Post-2020 observations only\nreserve obs get UNRATE --from cache --format jsonl | reserve transform filter --after 2020-01-01\n```\n\n---\n\n### window\n\nRolling window statistics over a JSONL stream.\n\n```bash\nreserve window roll --stat mean|std|min|max|sum --window N [--min-periods M]\n```\n\nNaN values are excluded from window computations. If fewer than `--min-periods` valid values exist in a window, the output for that period is NaN.\n\nExamples:\n\n```bash\n# 12-month rolling average unemployment rate\nreserve obs get UNRATE --from cache --format jsonl | reserve window roll --stat mean --window 12\n\n# 4-quarter rolling standard deviation of GDP growth\nreserve obs get GDP --from cache --format jsonl | reserve transform pct-change \\\n  | reserve window roll --stat std --window 4\n```\n\n---\n\n### analyze\n\nStatistical analysis on a JSONL stream. Results print to the terminal (table or JSON).\n\n```bash\nreserve analyze summary               # descriptive statistics\nreserve analyze trend [--method linear|theil-sen]\n```\n\n**`analyze summary`** produces:\n\n| Field | Description |\n|---|---|\n| count | total observations |\n| missing_count, missing_pct | NaN count and percentage |\n| mean, std | mean and standard deviation |\n| min, p25, median, p75, max | five-number summary |\n| skew | Fisher-Pearson skewness coefficient |\n| first, last | boundary non-NaN values |\n| change, change_pct | absolute and percentage change over the full series |\n| analysis_version, start_date, end_date, n_obs | stable machine-readable metadata/context |\n\n**`analyze trend`** produces:\n\n| Field | Description |\n|---|---|\n| direction | `up`, `down`, or `flat` |\n| slope_per_year | trend slope in original units per year |\n| slope_per_day | slope in original units per day |\n| intercept | regression intercept |\n| r2 | coefficient of determination (0–1) |\n| method | `linear` (OLS) or `theil-sen` (robust) |\n\nExamples:\n\n```bash\nreserve obs get UNRATE --from cache --format jsonl | reserve analyze summary\nreserve obs get GDP --from cache --format jsonl | reserve transform pct-change | reserve analyze summary\nreserve obs get UNRATE --from cache --format jsonl | reserve analyze trend\nreserve obs get UNRATE --from cache --format jsonl | reserve analyze trend --method theil-sen\n\n# same summary, human-first table output\nreserve obs get GDP --start 2020-01-01 --format jsonl | reserve analyze summary --format table\n\n# same summary, machine-first JSON contract\nreserve obs get GDP --start 2020-01-01 --format jsonl | reserve analyze summary --format json\n```\n\n---\n\n### cache\n\nManage the local embedded key-value cache database (bbolt).\n\n```bash\nreserve cache stats                         # bucket row counts and DB size\nreserve cache inventory                     # per-series local coverage, date ranges, and gaps\nreserve cache clear --all                   # wipe all data\nreserve cache clear --bucket obs            # wipe observations only\nreserve cache clear --bucket series_meta    # wipe metadata only\nreserve cache clear --series GDP            # wipe cached observation sets for one series\nreserve cache compact                       # reclaim disk space after clearing\nreserve cache reset-backfill                # force a rebuild of the local rights index marker\n```\n\n`cache inventory` gives a higher-level view of what you have locally: one row per cached series with merged date coverage, point counts, gap counts, frequency, and whether metadata is present. It ends with a small rule-based action summary so you can quickly see whether the next step is metadata enrichment, range refill, or no action at all. Daily series display `GAPS` as `n/a` because weekends and market holidays make gap counting misleading for that cadence.\n\nWhen `obs get --from cache` encounters multiple cached observation sets for the same series and no exact date/parameter filter is provided, reserve now chooses a canonical local set by widest coverage and warns which range was selected. Likewise, storing a second observation set for the same series emits a warning so the cache does not silently drift into multiple competing local variants.\n\n`cache clear --series \u003cID\u003e` removes all cached observation sets for one series while leaving its stored metadata intact. This is the preferred cleanup level when you want to rebuild one local series without wiping the entire observations bucket.\n\nFor disciplined local-cache workflows, prefer live reads for ad hoc questions, use `cache inventory` before storing additional variants of a series, and treat `cache clear --series` as a deliberate rebuild step rather than an automatic cleanup action.\n\n`cache clear` removes entries from one bucket or all buckets. bbolt does not shrink the database file automatically — freed pages are returned to an internal freelist and reused on future writes. The file footprint does not decrease until you run `compact`.\n\n`cache compact` rewrites the database to a new file, recovering all space freed by prior clears. The operation is safe: live data is copied to a temporary file first, then the original is atomically replaced.\n\n`cache reset-backfill` clears the internal marker that records whether the one-time local rights-index backfill has completed. The next command that needs the rights index will rebuild it.\n\n```bash\n# Typical maintenance workflow after a large clear:\nreserve cache clear --all\nreserve cache compact\n```\n\n---\n\n### alias\n\nManage local aliases for awkward FRED series IDs. Aliases resolve before API calls and are stored in `config.json`.\n\n```bash\nreserve alias set \u003cALIAS\u003e \u003cSERIES_ID\u003e [--note \"...\"]  # create/update alias\nreserve alias list                                     # list aliases (with note column)\nreserve alias get \u003cALIAS\u003e                              # show one alias mapping\nreserve alias delete \u003cALIAS\u003e                           # delete alias\nreserve alias rm \u003cALIAS\u003e                               # shorthand delete alias\n```\n\nExamples:\n\n```bash\nreserve alias set rfsdp PB0000031Q225SBEA --note \"Real Final Sales Dom. Producers\"\nreserve alias list\nreserve alias get rfsdp\nreserve alias delete rfsdp\n```\n\nRules:\n\n- Alias names are normalized to lowercase.\n- Valid characters: letters, numbers, dot (`.`), underscore (`_`), hyphen (`-`).\n- Aliases cannot use reserved command names.\n- `alias set` verifies the target series ID and blocks collisions with real FRED series IDs.\n\n---\n\n### config\n\nManage `config.json` in the user config directory, with optional local `./config.json` overrides.\n\n```bash\nreserve config init                    # create a template config.json in your user config directory\nreserve config get [--show-secrets]    # print resolved configuration (key redacted by default)\nreserve config set \u003ckey\u003e \u003cvalue\u003e       # update a single value\nreserve config grant \u003cSERIES_ID\u003e       # record a local permission override for one series\nreserve config revoke \u003cSERIES_ID\u003e      # remove a local permission override\nreserve config list-grants             # list locally granted series permissions\n```\n\nCommon `config set` keys: `api_key`, `default_format`, `timeout`, `concurrency`, `rate`, `base_url`, `db_path`, `person_org_type`, `block_unknown_rights`, `block_ambiguous_rights`, `block_preapproval_required_in_commercial`, `require_citation_on_display`, `require_citation_on_export`, `allow_override_with_permission_record`, `log_compliance_decisions`, `rights_refresh_days.default`, `rights_refresh_days.export`, `rights_refresh_days.publish`.\n\nThe permission-grant commands are for series where you independently obtained permission to use restricted data. They do not replace the need for actual authorization; they only record your local override decision for reserve's compliance checks.\n\n---\n\n### version\n\nPrint the reserve version string and build metadata.\n\n```bash\nreserve version                  # plain text — grep/awk friendly\nreserve version --format json    # structured output\nreserve version --format jsonl   # single line for audit streams\n```\n\nPlain text output:\n\n```bash\nreserve v1.1.8\ngo      go1.26.3\nos      darwin/arm64\n```\n\n---\n\n### update\n\nCheck a lightweight remote release manifest for newer versions and short release notes.\n\n```bash\nreserve update check                # human-readable update status\nreserve update check --format json  # structured output for scripts\nreserve update check --format jsonl # single-line audit/event output\nreserve update apply                # macOS/Linux: download, verify, and replace the current binary\nreserve update apply --dry-run      # test the live update path without installing\nreserve update apply --dry-run --force # exercise the full path even when already current\n```\n\nWhen a new release is available, `reserve update check` prints the current version, latest version, a short summary, release highlights, and static update instructions from the remote manifest.\n\n`reserve update apply` is Phase 1 self-update support. On macOS and Linux it downloads the platform archive for the latest release, verifies the archive against the published `SHA256SUMS`, and replaces the current executable in place. On Windows it reports the exact release asset URL and release page so updates stay manual.\n\n---\n\n### onboard\n\nEmit a machine-readable onboarding document for agents, LLMs, and advanced users.\nIt is designed to be pasted directly into Claude, ChatGPT, or another agent session\nso the model gets authoritative reserve semantics without guessing at commands or flags.\n\n```bash\nreserve onboard                          # full-program onboarding\nreserve onboard obs                      # command-specific onboarding\nreserve onboard --topic pipeline         # single topic\nreserve onboard --topic pipeline,gotchas # comma-separated topics\nreserve onboard --topic all              # full document (large context windows)\nreserve onboard --topic all | pbcopy     # copy to clipboard\nreserve onboard export ./onboard         # write program.json + per-command docs\n```\n\n**Topics:**\n\n| Topic | Contents |\n|---|---|\n| `toc` | Topic index and interaction guide (default) |\n| `commands` | Full command reference: nouns, verbs, flags, formats |\n| `pipeline` | stdin/stdout semantics, JSONL format, operator chaining |\n| `data-model` | Core types, NaN handling, Result envelope |\n| `examples` | Verified end-to-end examples with confirmed output values |\n| `gotchas` | Sharp edges, missing data, known limitations |\n| `version` | Build metadata for provenance |\n| `all` | Everything — for large context windows |\n\n**Workflow:**\n```bash\n# Step 1 — handshake: let the AI tell you what it needs\nreserve onboard --topic toc\n# paste into your LLM session\n\n# Step 2 — surgical context: paste only what the AI requested\nreserve onboard --topic pipeline,data-model,gotchas\n# paste → LLM confirms ready\n\n# Step 3 — ask your question\n```\n\n**Project export:**\n```bash\nreserve onboard export ./onboard\n# writes program.json plus command docs like obs.json, series.json, and config.json\n```\n\nOnboarding JSON includes explicit agent metadata fields so LLM clients can treat the payload as agent context rather than end-user help:\n\n- `primary_audience`\n- `intended_for_humans`\n- `content_type`\n\n**Suggested prompt:**\n```\nI am about to explore macro-economic data from the FRED API.\nUse this as your reference for a CLI called reserve.\nIt contains the authoritative command reference, pipeline\nsemantics, verified examples, and known gotchas.\nTell me when you are ready.\n```\n\nOutput is always JSON with HTML escaping disabled — `\u003c` and `\u003e` render\nliterally, not as `\\u003c` / `\\u003e`.\n\n---\n\n\n## Pipeline Usage\n\nAny command that produces observations can be piped into a transform or analyze command:\n\n```bash\n# Full macro pipeline: fetch → cache read → transform → analyze\nreserve obs get GDP --from cache --format jsonl \\\n  | reserve transform pct-change \\\n  | reserve analyze summary\n\n# Post-COVID unemployment: filter → rolling average\nreserve obs get UNRATE --from cache --format jsonl \\\n  | reserve transform filter --after 2020-01-01 \\\n  | reserve window roll --stat mean --window 12\n\n# Inflation signal: resample monthly CPI to annual → trend\nreserve obs get CPIAUCSL --from cache --format jsonl \\\n  | reserve transform resample --freq annual --method mean \\\n  | reserve analyze trend\n\n# Year-over-year unemployment change → CSV file\nreserve obs get UNRATE --from cache --format jsonl \\\n  | reserve transform pct-change --period 12 \\\n  | reserve transform filter --drop-missing \\\n  \u003e unrate_yoy.csv\n```\n\n**NaN handling:** FRED missing values (reported as `\".\"`) become `NaN` internally. Transforms skip NaN inputs in calculations and propagate NaN to outputs where appropriate. `analyze summary` counts and reports missing values explicitly.\n\n**Format auto-detection:** Pipeline commands default to `jsonl` when piped, `table` when output is a terminal. Override with `--format` on any command.\n\n---\n\n## Output Formats\n\nAll commands accept `--format`:\n\n| Format | Description |\n|---|---|\n| `table` | Human-readable aligned table (default for terminal output) |\n| `json` | Full result envelope as pretty-printed JSON |\n| `jsonl` | One JSON object per line (default for piped output) |\n| `csv` | Comma-separated with header row |\n| `tsv` | Tab-separated with header row |\n| `md` | Markdown table |\n\nWrite to a file with `--out`:\n\n```bash\nreserve obs get GDP --format csv --out gdp.csv\nreserve obs get CPIAUCSL --from cache --format jsonl --out cpi.jsonl\n```\n\n---\n\n## Global Flags\n\nThese flags are available on every command:\n\n```\n--format table|json|jsonl|csv|tsv|md    output format\n--out \u003cpath\u003e                            write command output to file (renderer-backed commands)\n--api-key \u003ckey\u003e                         override API key for this invocation only\n--timeout \u003cduration\u003e                    HTTP request timeout (default: 30s)\n--concurrency \u003cn\u003e                       parallel requests for batch operations (default: 8)\n+-rate \u003cn\u003e                              API requests/sec client-side limit (default: 2.0)\n--verbose                               show timing and cache stats after output\n--debug                                 log HTTP requests (API key redacted)\n--quiet                                 suppress all non-error output\n--no-cache                              bypass local database reads\n--refresh                               force re-fetch and overwrite cached entries\n```\n\n---\n\n## Configuration\n\n`reserve config init` creates `config.json` in your user config directory:\n\n- Linux: `~/.config/reserve/config.json`\n- macOS: `~/Library/Application Support/reserve/config.json`\n- Windows: `%AppData%\\reserve\\config.json`\n\nIf a local `./config.json` exists in the current working directory, it overrides the user config file for that shell location.\n\nThis makes ad hoc project overrides easy in a very Unix-style way: keep your personal API key and defaults in the user config file, then drop a local `./config.json` into a test or project directory when you want to override only selected settings such as `default_format` or `db_path`.\n\nExample local override:\n\n```json\n{\n  \"default_format\": \"json\",\n  \"db_path\": \"/tmp/reserve-local.db\"\n}\n```\n\nIn that directory, `reserve` will still inherit any missing values such as `api_key` from your user config, while honoring the local overrides for the fields you set.\n\nExample file contents:\n\n```json\n{\n  \"api_key\":        \"YOUR_KEY_HERE\",\n  \"default_format\": \"table\",\n  \"timeout\":        \"30s\",\n  \"concurrency\":    8,\n  \"rate\":           2.0,\n  \"db_path\":        \"\",\n  \"person_org_type\": \"student\",\n  \"block_unknown_rights\": true,\n  \"block_ambiguous_rights\": true,\n  \"block_preapproval_required_in_commercial\": true,\n  \"require_citation_on_display\": true,\n  \"require_citation_on_export\": true,\n  \"allow_override_with_permission_record\": true,\n  \"series_aliases\": {\n    \"rfsdp\": {\n      \"series_id\": \"PB0000031Q225SBEA\",\n      \"note\": \"Real Final Sales Dom. Producers\"\n    }\n  },\n  \"rights_refresh_days\": {\n    \"default\": 30,\n    \"export\": 7,\n    \"publish\": 7\n  },\n  \"log_compliance_decisions\": true\n}\n```\n\n**API key resolution order** (first non-empty wins):\n\n1. `--api-key` CLI flag\n2. `FRED_API_KEY` environment variable\n3. `api_key` in local `./config.json`\n4. `api_key` in user `config.json`\n\n**Database path resolution order:**\n\n1. `RESERVE_DB_PATH` environment variable\n2. `db_path` in local `./config.json`\n3. `db_path` in user `config.json`\n4. Default: `~/.reserve/reserve.db`\n\n---\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for the full version history.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\nFRED® is a registered trademark of the Federal Reserve Bank of St. Louis.  \nThis project is not affiliated with or endorsed by the Federal Reserve Bank of St. Louis.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderickschaefer%2Freserve","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fderickschaefer%2Freserve","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderickschaefer%2Freserve/lists"}