market-analyzer
CLAUDE.md2 starsChanged 2 months agoMITView on GitHub
Desktop trading-analysis app for the user's own use. Python sidecar (FastAPI on 127.0.0.1) + Electron + React + TypeScript renderer + SQLite cache, with a Streamable-HTTP MCP server mounted on the sidecar at /mcp. Primary control surface: Claude Code (CLI) via MCP (ADR-0015). The user drives the app by talking to an agent, which calls MCP tools on the sidecar. The Electron viewer is a live visualisation surface — it subscribes to a sidecar event stream (ADR-0017) and renders agent-issued…
- Reads credentials
In this repository9 other files it gives its agents.
- advisorSkill
- architectSkill
- backtesterSkill
- defi-analystSkill
- devSkill
- market-analystSkill
- safe-commitSkill
- strategy-authorSkill
- ui-builderSkill
The file
We split this CLAUDE.md into the rules it gives an agent
5 rules. About 0 are common, 0 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 59
Don't guess. Read the skill descriptions in .claude/skills/*/SKILL.md frontmatter, or ask.
- Very specific: line 118
Exact pinning: Every direct dependency in pyproject.toml and desktop/package.json is ==X.Y.Z (Python) or X.Y.Z (Node).
- Very specific: line 122
Weekly cutoff bump: Every ~7 days, advance exclude-newer by ~7 days and update minimumReleaseAge's effective floor as a regular chore …
- Very specific: line 123
CVE-driven bump: When a security patch lands inside the cooldown window, bump the relevant cutoff past the patch's publish date, run uv …
- Very specific: line 129
No range operators in manifests: Not in runtime deps, not in dev tooling, no ~=/^/>= exceptions.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
market-analyser
Desktop trading-analysis app for the user's own use. Python sidecar (FastAPI on 127.0.0.1) + Electron + React + TypeScript renderer + SQLite cache, with a Streamable-HTTP MCP server mounted on the sidecar at /mcp.
Primary control surface: Claude Code (CLI) via MCP (ADR-0015). The user drives the app by talking to an agent, which calls MCP tools on the sidecar. The Electron viewer is a live visualisation surface — it subscribes to a sidecar event stream (ADR-0017) and renders agent-issued chart commands. The sidecar runs as a standalone process (ADR-0016): Electron auto-attaches via a lockfile if one is already running, and closing the viewer does not stop the sidecar. Data layer written in-house per ADR-0009 (supersedes ADR-0003's vendoring policy).
This file is the orientation map for the project's skill ecosystem. Skills do the actual work; this file says which skill does which kind of work and how they hand off.
Skill ecosystem
Ten skills under .claude/skills/. Each has its own SKILL.md + references. Trust their descriptions — Claude Code triggers them automatically. This table is the orientation, not the trigger.
| Skill | Owns | Triggers on |
architect | docs/architecture/ (ADRs, plans, diagrams) | Design questions, "should we...", new ADRs, plan authoring, reviews |
dev | Python sidecar + tooling + CI | "Implement plan N", "do phase X", architect-authored work |
strategy-author | src/market_analyser/strategies/ | Writing/editing/porting trading strategies |
backtester | src/market_analyser/backtest/, runs/ | Running backtests, computing metrics, building the engine |
ui-builder | desktop/ | React views, charts, Electron shell, IPC, renderer plumbing |
market-analyst | Read-only TradFi analysis → runs/analysis/ | Candlestick scans, trend/momentum snapshots, screeners |
defi-analyst | Read-only DeFi analysis → runs/defi/ | Pool screens, LP positions, lending health, on-chain audits |
advisor | Advisory recommendations → runs/advice/ | "Should I buy/sell/short/exit", "what's your call", rebalance asks |
skill-creator | .claude/skills/ | Creating, editing, or measuring skills (meta) |
safe-commit | The commit ceremony (explicit-path staging, gates, inline PowerShell here-string message) | Any imminent commit — "commit this", "commit the phase" |
Hard splits to remember:
- TradFi vs DeFi. Stocks/indices/futures →
market-analyst. Pools/LPs/lending →defi-analyst. Never both. - Analyst vs backtester. "What's the current condition" → analyst. "How would this have done historically" → backtester.
- Analyst vs advisor. "What IS" (conditions, health, trend) → analyst. "What should I DO" (buy/sell/exit/rebalance) →
advisor, the one labeled advisory layer (ADR-0029). Analysts never recommend; the advisor never re-reports bare conditions. - Author vs implementer. Architect designs; dev/sibling skills implement. Never invert.
Canonical workflows
New feature (most common)
architect (design + plan) → user "go" → dev or sibling (implement all phases) → fresh architect session (close ceremony: review + status flip + move plan to plans/done/ + merge the implementation branch if one exists)- One plan, one session per implementer — or, for plans the index marks disjoint, one git worktree per implementer running in parallel (see plans/README § Parallel execution). Sibling-owned phases get routed to that sibling (per the plan's
Owner skill:tag). - The implementer never reviews their own work or moves plans to
done/. That's architect's close ceremony. - Implementer commits per phase (conventional-commit) but never pushes.
Bug fix / small refactor (no architect needed)
Direct implementation, conventional-commit, no plan, no review. If the fix reveals an ADR is wrong → escalate to architect.
Trading work (strategy / analysis / backtest)
- Idea-stage ("what should I watch", "what's the regime"):
market-analystMode 4 (brainstorm) — no code, no fetches. - Want a real read on a symbol:
market-analystMode 1 (pattern scan) or Mode 2 (snapshot). Reads cached bars. - Want to encode it:
strategy-authorwrites the strategy module. - Want to test it:
backtesterruns against historical bars. - Want a call ("should I buy", "long or short", "rebalance my book"):
advisor— fuses conditions + live signal + walk-forward edge + forecast via therecommendtool into a labeled advisory recommendation, or an honest "no actionable edge". - Want to see it in the app:
ui-builderrenders the result.
When you don't know which skill
Don't guess. Read the skill descriptions in .claude/skills/*/SKILL.md frontmatter, or ask. Most of the time the user's phrasing routes correctly via descriptions; the wrong skill speaking up is usually a description-tuning bug, not an orchestration bug.
Cross-cutting non-negotiables
These apply to every skill that writes code or analysis in this repo.
- No lookahead bias. A decision at bar
ionly sees data frombars[0..=i]. Backtests, strategies, analyses — same rule. Indicators must be trailing, not centered. - Determinism. Same inputs → same outputs in the financially-meaningful path: no
setiteration, no wall-clock reads, no unseeded randomness in strategy / metric / equity-curve computation. A backtest re-run fromspec.jsonproduces aresult.jsonthat is byte-identical modulo run provenance —run_id,started_at, andfinished_atare the documented exceptions (ADR-0018; the engine's golden test pinsmodel_dump(exclude={"run_id", "started_at", "finished_at"})equality cross-process). - No secrets in code or logs. Bearer tokens, API keys, the IPC per-launch secret — never persisted, never logged.
secrets.json(when it exists) lives outside the repo. - Where secrets live — one picture (stop re-deriving it). Third-party credentials (data-source keys + RPC URLs) resolve through the sidecar's
SecretsStore.get(key)(persistence/secrets.py): (1) env overrideMARKET_ANALYSER_<KEY>(uppercased, e.g.MARKET_ANALYSER_BASE_RPC_URL) if non-empty, else (2) the canonical0600secrets.jsonin the user-data dir (ADR-0038), else unset (typed error, never a silent fallback). A repo-root.env(dev-only, gitignored) is not a separate store — the sidecar loads it into those sameMARKET_ANALYSER_*env vars at startup (override=False; packaged builds load nothing), feeding layer 1..env/env useMARKET_ANALYSER_<UPPER>,secrets.jsonuses the bare key; same key set — the twelve inSecretKey(persistence/secrets.py, the source of truth; grow that Literal, not this list):zerion_api_key,graph_api_key,eth_rpc_url,base_rpc_url,binance_read_api_key,binance_read_api_secret,alchemy_prices_key,lunarcrush_api_key,reddit_client_id,reddit_client_secret,fred_api_key,finnhub_api_key. Every one is optional and gates exactly one source; absent, that source errors typed or degrades honest-empty and nothing else breaks. Separate homes (not this store): the per-launch IPC bearer (MARKET_ANALYSER_SECRET→sidecar.lock), the MCP bearer (mcp-secret.json), and future trade-execution keys (OS keychain viakeyring, ADR-0044 — never insecrets.json/.env). One-off scripts read via the realSecretsStore, never a bespoke bare env var. Full walkthrough: README → Configuration. - Security defaults are not optional. Electron renderer:
contextIsolation: true,nodeIntegration: false,sandbox: true, double-CSP. Renderer never imports Node, never reaches the network except via the typed sidecar fetch client (which injects the bearer). - Validate at boundaries. Pydantic for sidecar inputs, Zod for IPC payloads, typed responses for sidecar HTTP. Don't validate again inside trusted code paths.
- Conditions are facts, decisions are the user's. Analyst skills (
market-analyst,defi-analyst) report conditions; they never recommend buy/sell/exit/rebalance. The one sanctioned carve-out is theadvisorskill (ADR-0029): it may recommend — labeled advisory, always carrying rationale + backtested/forecast basis — but never acts (no orders, no trade keys; execution is ADR-0025's untaken decision). The crossing lives in that one layer only; it never leaks back into the analysts. - Commit hygiene under concurrency. Parallel sessions share one working tree, so stage only the files you changed, by explicit path — never
git add -A/./--all/:/(aPreToolUsehook denies broad staging).git statusfirst; never stage, stash, orcheckoutanother session's in-progress files. Never rewrite history (no amend/rebase/reset), never push. The/safe-commitskill is the ceremony that encodes all of this.
Where things live
docs/architecture/
├── adrs/ # NNNN-<slug>.md — accepted/superseded decisions
├── plans/ # NNNN-<slug>.md — drafts and in-progress
│ └── done/ # architect moves them here after close ceremony
├── diagrams/ # mermaid in standalone .md files
└── roadmap.md # aspirational direction — not committed scope
docs/reference/ # GENERATED, CI-gated API reference — every MCP tool / REST route / SSE event
# (params, return/payload shapes, source links). Do not hand-edit; regenerate
# with `pnpm gen:api-docs` (or `uv run python -m market_analyser.apiref`). ADR-0064.
src/market_analyser/
├── api/ # FastAPI app + routes — dev owns
├── data/ # MarketDataProvider Protocol, adapters — dev owns
├── persistence/ # SQLite + Alembic + repositories — dev owns
├── strategies/ # strategy-author owns
├── backtest/ # backtester owns
├── analysis/ # market-analyst's deps (patterns, indicators surface — to be authored)
├── advisor/ # Recommendation model + fusion (dev owns the code; the `advisor` skill consumes it via the `recommend` tool)
└── apiref/ # dev owns — introspects the live sidecar → generates docs/reference/ (ADR-0064)
desktop/ # ui-builder owns end-to-end (Electron main + preload + React renderer)
runs/ # gitignored — backtest, analysis, defi, advice artifacts
positions/ # gitignored — defi-analyst's positions.yaml (sensitive)ADRs that gate frequent decisions:
- ADR-0002 — IPC over localhost HTTP with bearer auth
- ADR-0004 — strategy interface (pure function + pydantic Params)
- ADR-0005 — why Electron (supersedes ADR-0001's Tauri pick)
- ADR-0006 — persistence layout (SQLite + config.json)
- ADR-0007 — MarketDataProvider Protocol
- ADR-0008 — Electron shell conventions (build pipeline, IPC discipline, CSP, packaging)
- ADR-0009 — data layer written in-house (supersedes ADR-0003)
Dependency discipline
Two policies, both tracked in git, both applied to PyPI (via uv) and the npm registry (via pnpm):
- Cooldown. Package versions younger than 14 days are refused at resolution time. Tracked as
[tool.uv] exclude-newer = "YYYY-MM-DD"inpyproject.tomlandminimumReleaseAge: 20160(minutes) inpnpm-workspace.yaml. See ADR-0012. - Exact pinning. Every direct dependency in
pyproject.tomlanddesktop/package.jsonis==X.Y.Z(Python) orX.Y.Z(Node). No>=, no^, no~. Dev tooling is pinned with the same rule as runtime deps. See ADR-0013.
Operational handles
- Weekly cutoff bump. Every ~7 days, advance
exclude-newerby ~7 days and updateminimumReleaseAge's effective floor as a regular chore commit. The cooldown is meant to lag, not stall — let it drift and ordinary dependency-update work starts failing for unrelated reasons. - CVE-driven bump. When a security patch lands inside the cooldown window, bump the relevant cutoff past the patch's publish date, run
uv lockand/orpnpm install, and land manifest + lockfile in a single commit whose message names the CVE. - Every direct-dep upgrade is a manifest edit. Bumping
fastapifrom0.136.1to0.137.0is a one-linepyproject.tomlchange plusuv lockplus a commit.uv lock --upgradeagainst a>=range is not how upgrades happen here. Same forpnpm: editdesktop/package.json, thenpnpm install, both in the same commit.
Non-negotiables
- No per-package cooldown allowlist.
pnpm'sminimumReleaseAgeExcludeand any hypothetical per-package exemption mechanism are off the table. ADR-0012 explains why: an allowlist becomes a quietly-growing exception register that undermines the audit property the policy exists to provide. - No range operators in manifests. Not in runtime deps, not in dev tooling, no
~=/^/>=exceptions. ADR-0013 explains why we pin both groups under the same rule.
Pitfalls to avoid
- Don't skip the architect for cross-cutting decisions. New IPC channel, new dependency, CSP change, new ADR-shaped question → architect, even if it feels like a small edit.
- Don't fabricate when blocked. The analyst, backtester, and ui-builder skills are explicit about this: if the data/engine/shell isn't there, surface it; don't paper over.
- Don't ad-hoc shared infrastructure in a single skill. Pattern detectors, indicator math, the BacktestResult schema — these get consumed by multiple skills, so they live in
src/, not in a one-off script. Architect designs, dev implements. - Don't push. Implementers commit; the user pushes. CI runs on push and tag. Auto-update is deferred to a future packaging plan.
- Don't bypass the typed fetch client in the renderer. Every sidecar call goes through
desktop/renderer/api/client.tsso the bearer token is injected once.
When the project state has moved
Skill references/project-context.md files describe state at the time they were written. Reality moves faster. If a skill's docs claim a module exists and you can't find it (or vice versa), trust Glob over the docs and surface the drift. The skill-creator workflow has eval tooling to catch this; routine drift gets fixed lazily as it's noticed.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

