# stonks Daily financial news + market data analysis. Fetches crypto/equity/futures prices (yfinance-equivalent + Finnhub) and market news (RSS), asks Claude for an investment-advice briefing, and posts it to Discord — on a systemd user timer. See [PLAN.md](PLAN.md) for the full design, cost analysis, and rationale. ## Build ```sh go build -o stonks ./cmd/stonks ``` ## Configure ```sh mkdir -p ~/.config/stonks cp config/config.yaml ~/.config/stonks/config.yaml cp config/secrets.env.example ~/.config/stonks/secrets.env chmod 600 ~/.config/stonks/secrets.env $EDITOR ~/.config/stonks/secrets.env # fill in FINNHUB_API_KEY, DISCORD_WEBHOOK_URL, (ANTHROPIC_API_KEY if using api mode) ``` If `analyzer.mode: subscription` (the default), install Claude Code and authenticate once: ```sh claude login ``` ### Multi-agent mode (optional) `analyzer.advisors` in `config.yaml` lists additional CLI-based AI analysts (Gemini, Codex) that get the same fetched data and produce an independent take; their output is appended to Claude's prompt as extra context (Claude still writes the one final report — see PLAN.md § "Claude integration"). Each needs to be installed and logged in separately: ```sh gemini # first run walks through auth codex login ``` A failing or unauthenticated advisor is logged as a warning and simply excluded — it never fails the run. Remove an entry (or the whole `advisors:` list) to disable multi-agent mode. ### Archiving runs (optional) Set `archive.enabled: true` in `config.yaml` to save each run's fetched data, full prompt (including any advisor section), raw and parsed analysis to `archive.dir` (default `~/.local/state/stonks/runs`), one timestamped subdirectory per run: `fetched.json`, `prompt.txt`, `analysis_raw.md`, `report.md`, `recommendations.json`. Useful for debugging prompt or parsing issues without reproducing a live run. Off by default — these accumulate over time with no automatic cleanup. ## Install as a user-scope systemd service ```sh mkdir -p ~/.local/bin ~/.config/systemd/user go build -o ~/.local/bin/stonks ./cmd/stonks cp systemd/stonks.service systemd/stonks.timer ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now stonks.timer loginctl enable-linger "$USER" # keep the timer firing while logged out ``` Run it once manually to verify before waiting for the timer: ```sh systemctl --user start stonks.service journalctl --user -u stonks.service -f ``` ## Adding a new fetcher / output Implement the `fetch.Fetcher` / `output.Output` interface in a new file under `internal/fetch` / `internal/output`, self-register it in an `init()` (see `internal/fetch/rss.go` for an example), add the name to `config.yaml`, and rebuild. See PLAN.md § "Modularity in Go" for why this is compile-time rather than a runtime plugin system.