Files
stonks/README.md
T
2026-09-05 09:55:24 +08:00

65 lines
2.8 KiB
Markdown

# 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.