Getting started
This guide takes you from nothing to a working Marrow install: the runtime, the encryption identity, the credential vault, a registered brokerage account, and a first set of commands that confirm everything is wired. It is written for a developer setting Marrow up by hand and for an AI agent setting it up on a developer’s behalf.
Marrow is non-custodial and bring-your-own-key. It runs on your machine against your own brokerage account. Your broker credentials are encrypted at rest and never leave your machine. Everything below configures files and keys that you control.
1. Prerequisites and clone
Marrow runs on Bun. It also shells out to two standard command-line tools to manage its credential vault:
- age provides
age-keygen, which creates the encryption identity that protects your keys. - SOPS encrypts and decrypts the keystore file using that identity.
Install all three before continuing. On macOS with Homebrew:
brew install oven-sh/bun/bun age sops
On Linux, install Bun from bun.sh and install age and sops from your package manager or their release pages. Confirm each is on your PATH:
bun --version
age-keygen --version
sops --version
Clone the repository and install dependencies:
git clone https://github.com/vincitamore/marrow.git
cd marrow
bun install
Marrow exposes a single executable named marrow. Link it so the command is available globally:
bun link
If you prefer not to link, invoke the entry point directly and read bun src/bin.ts wherever this guide writes marrow:
bun src/bin.ts account --json
The rest of this guide uses the linked marrow form.
2. The shipped skill
Marrow ships an agent skill at skill/SKILL.md. It is a self-contained instruction file that teaches an agent harness how to drive the CLI: the command surface, the JSON result contract, the fixed exit codes, the research fan-out, and the safety model on the write path.
If you are driving Marrow from an agent, load that skill into your harness. The agent reads it once and then operates Marrow through typed verbs, branching on the JSON envelope rather than parsing prose. If you are working at the terminal yourself, you do not need the skill; this guide and marrow --help are enough.
The skill is part of the product. It describes only Marrow’s own surface and is safe to share with any harness you use.
3. The encryption identity and keystore
Marrow keeps your broker credentials in an encrypted vault. Two pieces make that work, and it helps to understand them before you run init.
The age identity. A single age key encrypts and decrypts your vault. Marrow creates it on first use at:
~/.config/marrow/age-key.txt
The identity lives outside the repository on purpose, so an accidental commit of the repo can never expose your private key. The file is created with 0600 permissions (owner read/write only). To keep it somewhere else, set MARROW_AGE_KEY_FILE to an absolute path before running any command:
export MARROW_AGE_KEY_FILE="$HOME/keys/marrow-age.txt"
Back this file up. If you lose it, the encrypted keystore cannot be decrypted and you will have to re-register your accounts.
The keystore. Your broker API keys are stored, encrypted, in a SOPS file. By default it lives inside the repository at:
secrets/keystore.yaml
The secrets/ directory is gitignored, and the file is encrypted to your age identity, so it is never readable without the key above. To store it elsewhere, set MARROW_KEYSTORE_PATH to an absolute path:
export MARROW_KEYSTORE_PATH="$HOME/.config/marrow/keystore.yaml"
The account inventory. A separate, non-secret file names your accounts and maps each to a broker, a mode (paper or live), and the keystore entry that holds its credentials. By default:
inventory/accounts.yaml
This file holds no secrets and is safe to read in the open. It also carries the per-account trading guardrails (symbol allowlist, notional limits, confirmation thresholds) once you set them. Override its location with MARROW_INVENTORY_PATH.
You do not create any of these files by hand. The init command in the next step creates all three.
4. Initialize the vault and register an account
Run init to create the encryption identity (if it does not exist), create or update the encrypted keystore, and register a brokerage account in the inventory:
marrow init
With no flags, init registers an account named paper for the alpaca broker in paper mode. To name the account or change the broker or mode, pass flags:
marrow init --account my-paper --broker alpaca --mode paper
Flags:
--account <ref>names the account. The reference must be lowercase kebab-case (letters, digits, and hyphens, starting with a letter or digit). Defaults topaper.--broker <name>selects the broker. Alpaca is the supported broker; this defaults toalpaca.--mode <paper|live>selects paper or live. Defaults topaper. Start with paper.
init then prompts for your broker API key id and API secret. Input is hidden and never appears on the command line or in logs:
alpaca API key id:
alpaca API secret:
For scripted or agent-driven setup with no terminal, supply the two values through the environment instead of the prompt:
MARROW_INIT_API_KEY="PK..." MARROW_INIT_API_SECRET="..." marrow init --account paper
The first account you register becomes the default, so later commands can omit --account. init will not overwrite an existing keystore it cannot decrypt; if it reports that, check that your age identity is in place and that MARROW_AGE_KEY_FILE points at the right file.
On success, init reports the three paths it wrote and how to verify. Pass --json to any command, including init, for a machine-readable result.
5. API keys and data sources
Marrow reads from a brokerage and from several market-data sources. One key is required to trade; the data sources are independent and most are keyless. Configure only what you need.
Alpaca (required for broker commands)
Alpaca is the brokerage adapter. Account, position, quote, and order commands need an Alpaca key. Start with paper trading.
- Create an Alpaca account and open the paper trading dashboard.
- Generate an API key. You receive a key id and a secret.
- Provide them to
marrow init(step 4), either at the hidden prompt or throughMARROW_INIT_API_KEYandMARROW_INIT_API_SECRET.
Paper-mode commands talk to paper-api.alpaca.markets; live mode talks to api.alpaca.markets. Market data comes from data.alpaca.markets. Keep --mode paper until you have validated a strategy. Live execution is wired but refused until a reviewed checkpoint.
SEC EDGAR (recommended, no key)
The filings commands (filings, insiders, holdings) read from SEC EDGAR, which is public and needs no key. EDGAR’s fair-access policy does require every request to carry a User-Agent that declares a contact. Marrow ships a non-routable placeholder, which can be refused under load. Set your own contact so the filings commands stay reliable:
export MARROW_SEC_USER_AGENT="your-app/1.0 (you@example.com)"
FRED (optional macro data, free key)
The macro commands read economic series from the St. Louis Fed’s FRED. This is optional. To enable it, get a free API key from fredaccount.stlouisfed.org and set:
export MARROW_FRED_API_KEY="your-fred-key"
If the key is unset, the macro commands report that the source is optional and not configured, and the rest of Marrow is unaffected.
OpenBB (optional broad data, self-hosted)
For broad multi-provider market data and quant, Marrow connects to an OpenBB MCP server that you run yourself. It bundles no OpenBB code; it forwards tool calls across a process boundary. This is optional.
Run an OpenBB MCP server, then point Marrow at it with one of two transports. The HTTP transport is recommended:
export MARROW_OPENBB_URL="http://127.0.0.1:8000/mcp/"
Or launch a stdio server:
export MARROW_OPENBB_CMD="openbb-mcp --stdio"
A heavy server can be slow to start; raise the per-request timeout (default 60000 ms) with MARROW_MCP_TIMEOUT_MS if needed. Any provider keys OpenBB itself requires live in OpenBB’s own settings, not in Marrow.
FINRA and DefiLlama (no key, no setup)
The shorts command reads FINRA’s public Reg SHO daily short-volume files, and onchain tvl reads DefiLlama’s public API. Both are keyless and read-only. Nothing to configure.
Summary
| Source | Commands | Setup |
|---|---|---|
| Alpaca | account, positions, quote, trade | Required. Key id + secret via init. |
| SEC EDGAR | filings, insiders, holdings | Keyless. Set MARROW_SEC_USER_AGENT. |
| FRED | macro | Optional. MARROW_FRED_API_KEY. |
| OpenBB | openbb | Optional. MARROW_OPENBB_URL or MARROW_OPENBB_CMD. |
| FINRA | shorts | Keyless. None. |
| DefiLlama | onchain | Keyless. None. |
6. First commands
With the vault initialized and an Alpaca paper key registered, confirm the setup end to end.
Check the account. This reaches Alpaca and returns value, buying power, cash, and settlement state:
marrow account --account paper
If you registered a single account, or it is the default, you can drop the flag:
marrow account
List positions (empty on a fresh paper account):
marrow positions
Get a quote. Pass one or more tickers. The result carries a single price to act on and a stale flag that marks an unreliable book; prefer price over computing your own midpoint:
marrow quote SPY
marrow quote SPY QQQ AAPL
Read filings, which needs no broker key and confirms your EDGAR User-Agent is working:
marrow filings list AAPL --types 8-K,10-Q --since 90d
Every read command accepts --json and returns an envelope whose first key is ok:
marrow account --json
{ "ok": true, "command": "account", "data": { } }
Exit codes are fixed and stable, which makes the CLI safe to drive from a script or an agent:
0 success, nothing actionable
1 ran successfully, actionable state found
2 a broker or data source was unreachable
64 usage error (bad flag, unknown command, a refused write)
69 an external service was unavailable
70 an internal error
If marrow account returns your paper balance, the runtime, the encryption identity, the keystore, and the broker adapter are all working. From here, read Driving Marrow for the full research-to-trade loop, and Competing to put a persona on the board.