feat: done vibing
This commit is contained in:
27 files changed
+1922
-13
No files matched your search
@@ -5,7 +5,7 @@ Daily financial news + market data analysis service. Fetches free-tier market da
|
||||
## Architecture
|
||||
|
||||
```
|
||||
systemd timer (daily) --> stonks.service (oneshot) --> cmd/stonks/main.go
|
||||
systemd timer (every 5h) --> stonks.service (oneshot) --> cmd/stonks/main.go
|
||||
|
|
||||
---------------------------------------------
|
||||
| | |
|
||||
@@ -110,6 +110,12 @@ outputs:
|
||||
|
||||
Both modes implement the same `Analyzer` interface, selected by `analyzer.mode` in config.
|
||||
|
||||
### Multi-agent mode (optional advisors)
|
||||
|
||||
`analyzer.advisors` (a list of `{name, command, args}`) names additional one-shot CLIs — e.g. `gemini`, `codex exec -` — that receive the *same* fetched-data prompt (piped via stdin, `internal/analyze/advisor.go`) and produce an independent take. Advisors run concurrently; the ones that succeed are appended to Claude's final prompt as an "Other AI Analysts' Independent Takes" section, and `SystemPrompt` instructs Claude to weigh them (agree/disagree explicitly) rather than defer to them — Claude still writes the one final report and recommendations block.
|
||||
|
||||
This is deliberately **not** a fourth `Analyzer` implementation — advisors don't produce the final report shape (no recommendations-JSON contract), they're inputs to it. A failing or unauthenticated advisor CLI is logged as a warning and excluded from the prompt, same graceful-degradation pattern as the fetchers; it never fails the run. Each advisor CLI needs its own separate login (`gemini`, `codex login`) — independent of the `claude`/Anthropic auth used for the final analysis.
|
||||
|
||||
## systemd integration — user scope (`systemctl --user`)
|
||||
|
||||
Units live under `~/.config/systemd/user/` and are managed with `systemctl --user`, not root-owned `/etc/systemd/system/`. This fits naturally with `subscription` mode, since `claude login`'s session lives under the same user's `$HOME` anyway — no `User=`/permissions mismatch to manage.
|
||||
@@ -129,10 +135,11 @@ ExecStart=%h/.local/bin/stonks --config %h/.config/stonks/config.yaml
|
||||
```ini
|
||||
# ~/.config/systemd/user/stonks.timer
|
||||
[Unit]
|
||||
Description=Run stonks daily
|
||||
Description=Run stonks every 5 hours
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 07:00:00
|
||||
# Fires at 00:00, 05:00, 10:00, 15:00, 20:00 (wall-clock aligned).
|
||||
OnCalendar=*-*-* 0/5:00:00
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
@@ -145,7 +152,7 @@ WantedBy=timers.target
|
||||
systemctl --user enable --now stonks.timer
|
||||
```
|
||||
|
||||
**User-scope services normally stop when the user logs out.** Since this needs to fire daily unattended (including when nobody's logged in), enable lingering once:
|
||||
**User-scope services normally stop when the user logs out.** Since this needs to fire every 5 hours unattended (including when nobody's logged in), enable lingering once:
|
||||
|
||||
```sh
|
||||
loginctl enable-linger "$USER"
|
||||
@@ -169,18 +176,20 @@ Estimated build time: a working v1 (one fetcher, one output, hardcoded targets)
|
||||
|
||||
## Cost
|
||||
|
||||
**`subscription` mode: $0 marginal cost**, covered by your existing Claude Pro/Max subscription, assuming usage stays well within its rate limits — trivially true for one call/day.
|
||||
The timer now fires every 5 hours (`OnCalendar=*-*-* 0/5:00:00`) — 5 runs/day instead of 1.
|
||||
|
||||
**`api` mode**, for ~5-15k input / ~1-2k output tokens per day (no caching benefit at one call/day):
|
||||
**`subscription` mode: still $0 marginal cost**, covered by your existing Claude Pro/Max subscription. The one thing worth watching at 5x the frequency: subscription plans have rolling usage windows (typically ~5 hours), so if this job's prompt is large or other subscription usage is heavy at the same time, it's worth an occasional `journalctl --user -u stonks.service` check for rate-limit errors — not a cost concern, just a headroom one.
|
||||
|
||||
| Model | Input $/MTok | Output $/MTok | Daily (worst case: 15k in / 2k out) | Daily (typical: 8k in / 1.5k out) | Monthly (typical) |
|
||||
**`api` mode**, for ~5-15k input / ~1-2k output tokens per run (no caching benefit between runs — each is a cold prompt), now at 5 runs/day:
|
||||
|
||||
| Model | Input $/MTok | Output $/MTok | Daily (worst case: 5 × 15k in / 2k out) | Daily (typical: 5 × 8k in / 1.5k out) | Monthly (typical) |
|
||||
|---|---|---|---|---|---|
|
||||
| Claude Opus 5 | $5.00 | $25.00 | $0.125 | $0.078 | ~$2.30 |
|
||||
| Claude Sonnet 5 (intro, through 2026-08-31) | $2.00 | $10.00 | $0.050 | $0.031 | ~$0.94 |
|
||||
| Claude Sonnet 5 (standard) | $3.00 | $15.00 | $0.075 | $0.047 | ~$1.40 |
|
||||
| Claude Haiku 4.5 | $1.00 | $5.00 | $0.025 | $0.016 | ~$0.47 |
|
||||
| Claude Opus 5 | $5.00 | $25.00 | $0.625 | $0.39 | ~$11.70 |
|
||||
| Claude Sonnet 5 (intro, through 2026-08-31) | $2.00 | $10.00 | $0.25 | $0.155 | ~$4.65 |
|
||||
| Claude Sonnet 5 (standard) | $3.00 | $15.00 | $0.375 | $0.235 | ~$7.05 |
|
||||
| Claude Haiku 4.5 | $1.00 | $5.00 | $0.125 | $0.08 | ~$2.40 |
|
||||
|
||||
Even at Opus 5 pricing in `api` mode this is under $3/month — the choice between modes should be driven by which auth story you'd rather run unattended (personal subscription login vs. a static API key), not by cost.
|
||||
Still cheap in absolute terms, but ~5x the daily-cadence estimate — worth knowing if you're on `api` mode and cost-sensitive. `subscription` mode sidesteps this entirely since it isn't metered per token.
|
||||
|
||||
## Open questions / next steps
|
||||
|
||||
|
||||
Reference in new issue
Block a user