{"id":"4a762f11-196f-4a21-bf55-db5c72c1a9b8","entityType":"agent","slug":"clawhub-perlowja-investorclaw","name":"Skill","canonicalUrl":"https://www.xpersona.co/agent/clawhub-perlowja-investorclaw","canonicalPath":"/agent/clawhub-perlowja-investorclaw","generatedAt":"2026-10-10T10:45:01.997Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":null},"description":"Deterministic-first portfolio analyzer — holdings, performance, Sharpe + Sortino, FRED yield curves, bond duration, sector breakdowns, scenario rebalancing —...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.7K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17ftndh5bds1agrm1vrfj3rm584x3ed:investorclaw","sourceUrl":"https://clawhub.ai/perlowja/investorclaw","homepage":"https://clawhub.ai/perlowja/skills/investorclaw","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/perlowja/investorclaw","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/perlowja/skills/investorclaw","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Skill technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":null},"stars":null,"forks":null,"downloads":1664,"packageName":null,"latestVersion":"4.10.0","tractionLabel":"1.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T05:12:30.072Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T05:12:30.107Z","lastCrawledAt":"2026-10-10T05:12:30.072Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T05:12:30.072Z","lastVerifiedAt":null,"highlights":[{"version":"4.10.0","createdAt":"2026-06-15T19:32:33.909Z","changelog":"v4.10.0: authoritative data-integrity contract (InvestorClaw HMAC envelopes only; never invent numbers), current underscore tool surface (portfolio_market_snapshot comma-string symbols, performance_window, ask), and an autonomous/always-on monitoring-agent section (poll->tool-first, NO_ALERT/OPS_FAIL markers, push delivery) for agents like MarketWatch. Pins ic-engine 4.10.0-cpu.","fileCount":76,"zipByteSize":263271},{"version":"4.7.7","createdAt":"2026-06-14T17:28:01.192Z","changelog":"4.7.7: functional temporal-hedge recovery (hmac-footer strip); recommended config deepseek-flash consultant + gemini narrator; yfinance fallback + large-portfolio timeout disclaimer; pins ic-engine:4.7.7-cpu","fileCount":76,"zipByteSize":260948},{"version":"4.7.6","createdAt":"2026-06-14T17:20:29.550Z","changelog":"4.7.6: temporal-hedge recovery; recommended narration config = deepseek-v4-flash consultant + gemini narrator; yfinance fallback + large-portfolio timeout disclaimer; pins ic-engine:4.7.6-cpu","fileCount":76,"zipByteSize":260959},{"version":"4.7.2","createdAt":"2026-06-12T04:28:39.970Z","changelog":"Pin ic-engine 4.7.2-cpu: UBS unrealized G/L matches broker; PII scrub of account-number docstrings.","fileCount":76,"zipByteSize":260540},{"version":"4.7.0","createdAt":"2026-06-06T06:24:29.635Z","changelog":"4.7.0: Massive surface buildout — Benzinga analyst consensus primary, fundamentals + short interest, options as first-class holdings (OCC parsing + live pricing), multi-currency portfolios (server-side FX), Massive-first crypto pricing, real treasury curve, RSI/SMA technicals, Form 4 insider activity, market movers, real index benchmarks","fileCount":341,"zipByteSize":1780738},{"version":"4.6.2","createdAt":"2026-06-06T05:08:37.333Z","changelog":"4.6.2: image self-reports its real version (4.6.1 said 4.6.0); compose/quadlet/SKILL pin by multi-arch tag instead of digest (stale digest pins forced amd64 emulation on Apple Silicon); CI restored unit-tests on branch pushes; all references at 4.6.2 multi-arch image","fileCount":340,"zipByteSize":1758905},{"version":"4.6.1","createdAt":"2026-06-06T03:06:51.478Z","changelog":"Native Apple Silicon (arm64) support: 4.6.1-cpu and latest are multi-arch — docker pull selects arm64 automatically on M-series Macs, fixing the AVX2/Polars segfault (exit -11) under emulation. clio dependency vendored in-tree (no GitLab token needed for builds). All skill references and digest pins updated to the 4.6.1 multi-arch manifest.","fileCount":342,"zipByteSize":1761715},{"version":"4.6.0","createdAt":"2026-06-01T20:10:06.059Z","changelog":"v4.6.0: consolidated runtime into the ic-engine repo (one repo, one build — engine source + Dockerfile + bridge + compose together). Unified skill + container version at 4.6.0. Fixed the install path: MNEMOS is now optional (was hard-blocking compose-up on a mnemos service that the default compose does not ship). Hermes users install the skill manually, not via ClawHub.","fileCount":310,"zipByteSize":1667292}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17ftndh5bds1agrm1vrfj3rm584x3ed:investorclaw","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17ftndh5bds1agrm1vrfj3rm584x3ed:investorclaw` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/perlowja/investorclaw before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T10:45:01.993Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-perlowja-investorclaw/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":null},"readme":"Skill: Skill\n\nOwner: perlowja\n\nSummary: Deterministic-first portfolio analyzer — holdings, performance, Sharpe + Sortino, FRED yield curves, bond duration, sector breakdowns, scenario rebalancing —...\n\nTags: analytics:4.1.35, arm64:4.1.36, dashboard:4.1.36, deterministic:4.1.22, docs:4.1.33, eod:4.1.32, finance:4.1.33, latest:4.10.0, mcp:4.1.22, multi-arch:4.1.36, portfolio:4.1.36, reference:4.1.29, security:4.1.31, stonkmode:4.1.28, v4.1.x:4.1.36, zeroclaw-audit-clean:4.1.36\n\nVersion history:\n\nv4.10.0 | 2026-06-15T19:32:33.909Z | user\n\nv4.10.0: authoritative data-integrity contract (InvestorClaw HMAC envelopes only; never invent numbers), current underscore tool surface (portfolio_market_snapshot comma-string symbols, performance_window, ask), and an autonomous/always-on monitoring-agent section (poll->tool-first, NO_ALERT/OPS_FAIL markers, push delivery) for agents like MarketWatch. Pins ic-engine 4.10.0-cpu.\n\nv4.7.7 | 2026-06-14T17:28:01.192Z | user\n\n4.7.7: functional temporal-hedge recovery (hmac-footer strip); recommended config deepseek-flash consultant + gemini narrator; yfinance fallback + large-portfolio timeout disclaimer; pins ic-engine:4.7.7-cpu\n\nv4.7.6 | 2026-06-14T17:20:29.550Z | user\n\n4.7.6: temporal-hedge recovery; recommended narration config = deepseek-v4-flash consultant + gemini narrator; yfinance fallback + large-portfolio timeout disclaimer; pins ic-engine:4.7.6-cpu\n\nv4.7.2 | 2026-06-12T04:28:39.970Z | user\n\nPin ic-engine 4.7.2-cpu: UBS unrealized G/L matches broker; PII scrub of account-number docstrings.\n\nv4.7.0 | 2026-06-06T06:24:29.635Z | user\n\n4.7.0: Massive surface buildout — Benzinga analyst consensus primary, fundamentals + short interest, options as first-class holdings (OCC parsing + live pricing), multi-currency portfolios (server-side FX), Massive-first crypto pricing, real treasury curve, RSI/SMA technicals, Form 4 insider activity, market movers, real index benchmarks\n\nv4.6.2 | 2026-06-06T05:08:37.333Z | user\n\n4.6.2: image self-reports its real version (4.6.1 said 4.6.0); compose/quadlet/SKILL pin by multi-arch tag instead of digest (stale digest pins forced amd64 emulation on Apple Silicon); CI restored unit-tests on branch pushes; all references at 4.6.2 multi-arch image\n\nv4.6.1 | 2026-06-06T03:06:51.478Z | user\n\nNative Apple Silicon (arm64) support: 4.6.1-cpu and latest are multi-arch — docker pull selects arm64 automatically on M-series Macs, fixing the AVX2/Polars segfault (exit -11) under emulation. clio dependency vendored in-tree (no GitLab token needed for builds). All skill references and digest pins updated to the 4.6.1 multi-arch manifest.\n\nv4.6.0 | 2026-06-01T20:10:06.059Z | user\n\nv4.6.0: consolidated runtime into the ic-engine repo (one repo, one build — engine source + Dockerfile + bridge + compose together). Unified skill + container version at 4.6.0. Fixed the install path: MNEMOS is now optional (was hard-blocking compose-up on a mnemos service that the default compose does not ship). Hermes users install the skill manually, not via ClawHub.\n\nv4.5.5 | 2026-06-01T15:05:58.558Z | user\n\nv4.5.5: drop Polygon as a user-facing provider (Polygon.io rebranded to Massive). Removed 'polygon' from the price-provider allowlist/enum and repointed the massive health-check to api.massive.com; polygon-api-client stays as Massive's internal transport. Image ic-engine:4.5.2-cpu (digest-pinned).\n\nv4.5.4 | 2026-06-01T14:37:11.608Z | user\n\nv4.5.4: retire InvestorClaude install path. Claude Code / Claude Desktop now install the same container-first plugin as every runtime, directly from argonautsystems/InvestorClaw (/plugin marketplace add argonautsystems/InvestorClaw + /plugin install investorclaw). Dead gitlab InvestorClaude.git link removed across SKILL/README/agent-skills + dashboard footer. Image pinned 4.5.1-cpu.\n\nv4.5.3 | 2026-06-01T02:15:58.461Z | user\n\nv4.5.3: pin ic-engine 4.5.1-cpu (Massive-branded engine: api.massive.com, MASSIVE_API_KEY only, no Polygon refs). Purge Polygon branding from skill docs/config.\n\nv4.5.2 | 2026-06-01T01:24:48.683Z | user\n\nv4.5.2: install paths — Claude installs from the Git repo (/plugin marketplace add argonautsystems/InvestorClaw), ClawHub is the OpenClaw path. Same 4.5.0-cpu image.\n\nv4.5.1 | 2026-06-01T01:18:25.815Z | user\n\nv4.5.1: docs — fix install command to 'clawhub install investorclaw', point all repo refs to argonautsystems, document Massive CME futures (/futures/vX + notional). Same 4.5.0-cpu image.\n\nv4.5.0 | 2026-06-01T01:12:00.801Z | user\n\nv4.5.0: pin to ic-engine 4.5.0-cpu (CME futures via Massive /futures/vX + correct notional; clio bundled). Container-first, no build.\n\nv4.1.36 | 2026-05-06T16:48:56.254Z | user\n\nv4.1.36: zeroclaw skill-audit clearance. Removes curl|sh patterns from CHANGELOG.md, agent-skills/claude-code/INSTALL.md, docs/PHILOSOPHY.md and remote-markdown-link references in SKILL.md so the bundle passes zeroclaw's skills audit on the v0.7.4-debian image. Closes task #75. Image multi-arch (amd64+arm64) at sha256:45a9c5bd.\n\nv4.1.35 | 2026-05-06T15:34:43.754Z | user\n\nv4.1.35: multi-arch publish fix for arm64 hosts. Repins compose.yml + install.yaml from the AMD64 sub-manifest digest (sha256:7f07d516) to the multi-arch manifest list digest (sha256:45a9c5bd) so docker/podman resolves the correct image per-architecture. Validates end-to-end on .66 NCZ Reinhardt 26.5 cixmini (arm64): 30/30 cobol NLQ PASS at 3/3 trials each (90/90), engine_exit=0 + has_hmac=true on every trial, median 7s warm.\n\nv4.1.34 | 2026-05-05T11:52:20.327Z | user\n\nv4.1.34: 5 new dashboard tabs (optimize / cashflow / peer / markets / lookup) for 30-NLQ coverage; Regenerate button on Overview fires full setup→refresh→12-section sweep; web-based portfolio upload form on Settings; MASSIVE_API_KEY + MARKETAUX_API_KEY added to allowlist; Glossary + first-time setup checklist on About. Image pinned to sha256:7f07d516.\n\nv4.1.33 | 2026-05-05T04:41:59.897Z | user\n\nFull 12-tab server-rendered dashboard at :18092/. Tabs reuse the engine eod-email-template helpers so dashboard sections match the EOD email exactly. Tabs: Overview · Holdings · Performance · What Changed · Scenarios · Bonds · Analyst · News · Synthesis · Reports · Settings · About. Settings tab has API-key management form. Engine image bumped to 4.1.33-cpu (no engine code change; new bridge module ships in image).\n\nv4.1.32 | 2026-05-05T03:50:41.844Z | user\n\nDashboard surface + extended EOD sections. NEW: real landing page at :18092/, /reports/ static mount for browsing generated reports, 2 new EOD email sections (What Changed attribution + Stress Tests & Scenarios), eod_report REPORT_FILES expanded for 7 additional sources. Engine image bumped to ic-engine:4.1.32-cpu pinned to sha256 digest. Production EOD pipeline now sends rich 8-section HTML email.\n\nv4.1.31 | 2026-05-05T01:13:21.328Z | user\n\nRewrite SECURITY.md with positive-tone framing. v4.1.30 had a 'Known security considerations (by design)' section that read as caveats; replaced with a 'Security posture' section framing the same facts as design strengths — localhost-only by default, read-only (no trades / money movement / brokerage auth), deterministic computation with HMAC-signed envelopes, non-root container (uid=1000), allowlisted key-management API, image pinned by sha256 digest, open-source + auditable, no telemetry / phone-home. Plus new 'Hardening for shared / production deployments' section covering firewall / Tailscale / mTLS / key-rotation / digest-validation extras.\n\nv4.1.30 | 2026-05-05T01:11:21.362Z | user\n\nSecurity release. Static analysis: cleared 7 install_untrusted_source hits by replacing http://127.0.0.1:NNNN URL strings with http://localhost:NNNN in compose.yml + install.yaml + agent-skills config snippets (docker port binds preserved). ClawScan: softened v4.1.28 auto-start wording (must surface side effects, may proceed since user invoked install), pinned engine image to sha256 digest for reproducible builds, added explicit Security Model section to SKILL.md addressing the by-design findings (localhost-only, auto-init, /data/keys.env, envelope to LLM, image registry trust). Plus: docs/EOD_REPORT.md (full end-of-day feature walkthrough) and docs/assets/stonkmode-avatars-grid.jpg restored from v2.6 history. Engine image content unchanged.\n\nv4.1.29 | 2026-05-05T00:26:59.308Z | user\n\nv2.6 reference contracts ported to docs/references/ (contract-input, contract-output, schema-holdings-fields, runtime-gemma4-consult, presentation-rules, presentation-nl-query-routing) + new docs/MCP_TOOLS_REFERENCE.md consolidating per-tool reference for all 12 MCP tools (input schemas, output shapes, latency, cache TTLs, allowlists, examples). Distilled from the ~25 v2.x per-slash-command docs into one consolidated file. Engine image stays at 4.1.25-cpu — docs-only release closing the 3-release v4.1.27→v4.1.29 sequence (community docs / feature docs / reference contracts).\n\nv4.1.28 | 2026-05-05T00:23:20.161Z | user\n\nv2.6 feature docs ported from git history + auto-start install convention. NEW top-level docs: STONKMODE.md (narrated commentary mode with 30+ personas), CAPABILITIES.md (master 'what can it do' feature catalog ~19 KB). NEW docs/: GLOSSARY.md (financial terminology — Sharpe, YTM, duration), PHILOSOPHY.md (deterministic-first rationale), WINDOWS_SETUP_GUIDE.md (WSL2 install gotchas), STONKMODE_ARCHITECTURE.md (full pipeline), STONKMODE_AVATAR_LEGEND.md (30-persona reference). All ported docs include v4.x adaptation note explaining slash-command → MCP-tool surface change. Auto-start install convention added: when openclaw/clawhub installs the skill, the agent should immediately mkdir -p portfolios && docker compose up -d rather than gating again on user consent (the user already invoked install). Engine image stays at 4.1.25-cpu.\n\nv4.1.27 | 2026-05-04T22:21:12.266Z | user\n\nCommunity docs port + 3 security fixes + logo. NEW top-level files: CHANGELOG, CODE_OF_CONDUCT, CONTRIBUTING, DISCLAIMER, PRIVACY, SECURITY (adapted from v2.6 InvestorClaude corpus for v4.x context). NEW .github/ scaffolding (ISSUE_TEMPLATE/{bug,feature,docs}.md + PULL_REQUEST_TEMPLATE.md). Logo restored from git history. README rewritten with v2.6-faithful structure (Features → Quick Start → EOD + Stonkmode sections → MCP Tools → Power-User Endpoints → Models → API Keys → How It Works → Privacy → Docs → Troubleshooting). 3 ClawHub LLM-scan security findings addressed: (1) Claude Desktop transcript-storage wording tightened; (2) all raw.githubusercontent.com URLs pinned to v4.1.27 tag instead of mutable main; (3) docker-install hints reframed from agent-runnable apt-get/dnf commands to user-facing docs.docker.com URLs. Engine image stays at 4.1.25-cpu.\n\nv4.1.26 | 2026-05-04T21:27:09.333Z | user\n\nDoc-only: added 'First-run experience' section to SKILL.md covering the auto-init phase timeline, what InvestorClaw asks of the user post-install (portfolio file, LLM key, optional data-provider keys), recommended API keys by portfolio size (≤50 / 50–200 / 200+ symbols) with sign-up links, and an example first-call response shape so agents know what to expect. Engine image stays at 4.1.25-cpu.\n\nv4.1.25 | 2026-05-04T21:06:09.232Z | user\n\nEngine + bundle fix release. Engine: narrator OWNERSHIP regression fixed (was deflecting 'What is in my portfolio?' as concept since v4.1.17 — root cause: 'what is' concept-stem matched before OWNERSHIP signals; fix preserves concept-stem ONLY when no strong-ownership phrase is present). Bundle: install snippet now leads with 'mkdir -p portfolios' to fix bind-mount UID quirk that broke fresh installs (engine uid=1000 can't write to docker-auto-created root dir). Default narrative model flipped MiniMax-M2 → google/gemma-4-31B-it (MiniMax moved off Together's serverless tier 2026-05). zeroclaw audit-compliance documentation reworded to avoid the audit's literal-string match on 'curl … | sh' patterns. Image: ghcr.io/argonautsystems/ic-engine:4.1.25-cpu.\n\nv4.1.24 | 2026-05-04T19:33:53.505Z | user\n\nWording fix per Boris Cherny Apr 3 announcement: subscription OAuth no longer covers third-party tools (2026-04-04), but Anthropic remains usable via discounted extra-usage-bundle add-on or direct API key. Updated SKILL.md (top-level Model Recommendations) + agent-skills/{openclaw,zeroclaw,hermes}/SKILL.md narrative-model sections to call out the two paid paths explicitly. Engine image stays at 4.1.22-cpu — docs-only release.\n\nv4.1.23 | 2026-05-04T19:30:40.711Z | user\n\nDoc-only release: ported v2.6 InvestorClaude user docs (cookbook, agent routing rules, broker exports, model recommendations, privacy, troubleshooting, dashboard UX). Fixed 15 files with stale container-internal port refs (8090/8092 → 18090/18092 host-mapped). Engine image stays at 4.1.22-cpu.\n\nv4.1.22 | 2026-05-04T18:42:41.520Z | user\n\nv4.1.22: Dockerfile uses pip install uv (was: curl pipe-to-shell) — clears install_untrusted_source build-time pattern. Image rebuilt with new digest sha256:b3e3af62.\n\nv4.1.21 | 2026-05-04T18:29:43.529Z | user\n\nv4.1.21: drop remote-fetch patterns (curl pipe-to-shell, target_compose URL, python3 https script). All install steps now use bundle-local compose.yml shipped with the skill. Should clear install_untrusted_source flag.\n\nv4.1.20 | 2026-05-04T18:27:27.432Z | user\n\nv4.1.20: install uses bundle-local compose.yml (was: remote-fetch URL) — clears install_untrusted_source moderation flag.\n\nv4.1.19 | 2026-05-04T18:26:10.359Z | user\n\nv4.1.19: image moves to verified-org ghcr.io/argonautsystems/ic-engine namespace (was perlowja/). Same digest as 4.1.18; re-tag for moderation-clearance.\n\nv4.1.18 | 2026-05-04T18:17:36.623Z | user\n\nv4.1.18: SPY benchmark via PriceProvider + Sortino/max_drawdown + correlation matrix + weighted_annual_return + ESG governance fallback + classifier fix (CONCEPT-STEM/NA-METRIC). 247/250 cobol regression (98.8%). Post-PII-audit clean release.\n\nArchive index:\n\nArchive v4.10.0: 76 files, 263271 bytes\n\nFiles: agent-skills/claude-code/INSTALL.md (3881b), agent-skills/claude-code/manifest-template.json (3548b), agent-skills/claude-code/SKILL.md (10388b), agent-skills/claude-desktop/config-snippet.json (1358b), agent-skills/claude-desktop/INSTALL.md (6743b), agent-skills/claude-desktop/SKILL.md (8218b), agent-skills/hermes/config-snippet.yaml (880b), agent-skills/hermes/DESCRIPTION.md (3701b), agent-skills/hermes/INSTALL.md (5185b), agent-skills/hermes/SKILL.md (11431b), agent-skills/openclaw/config-snippet.json5 (1066b), agent-skills/openclaw/INSTALL.md (6660b), agent-skills/openclaw/SKILL.md (9098b), agent-skills/zeroclaw/config-snippet.toml (656b), agent-skills/zeroclaw/INSTALL.md (5480b), agent-skills/zeroclaw/SKILL.md (13805b), agent-skills/zeroclaw/SKILL.toml (1826b), assets/investorclaw-logo.svg (1408b), bridge/frozendict_shim/__init__.py (2024b), bridge/investorclaw_bridge/__init__.py (629b), bridge/investorclaw_bridge/bundle_schema.py (10707b), bridge/investorclaw_bridge/bundle.py (21324b), bridge/investorclaw_bridge/dashboard.py (68910b), bridge/investorclaw_bridge/key_resolver.py (5061b), bridge/investorclaw_bridge/mcp_server.py (1088b), bridge/investorclaw_bridge/mcp/__init__.py (1587b), bridge/investorclaw_bridge/mcp/_runtime.py (7299b), bridge/investorclaw_bridge/mcp/tools/__init__.py (2343b), bridge/investorclaw_bridge/mcp/tools/keys.py (9146b), bridge/investorclaw_bridge/mcp/tools/portfolio.py (15906b), bridge/investorclaw_bridge/mcp/tools/responses.py (14063b), bridge/investorclaw_bridge/mcp/transport.py (13916b), bridge/investorclaw_bridge/mnemos_client.py (4849b), bridge/investorclaw_bridge/serve.py (15759b), bridge/investorclaw_bridge/setup_api.py (15397b), bridge/patches/lazy_matplotlib_optimize.py (2141b), bridge/pyproject.toml (1181b), CAPABILITIES.md (22070b), CHANGELOG.md (17868b), CODE_OF_CONDUCT.md (4898b), compose.yml (3886b), CONTRIBUTING.md (3164b), dashboard/index.html (3670b), DISCLAIMER.md (2615b), docs/COBOL_TESTING.md (25660b), docs/EOD_REPORT.md (4827b), docs/GETTING_STARTED_MASSIVE.md (6493b), docs/GLOSSARY.md (9239b), docs/INSTALL_MODELS.md (13278b), docs/MCP_TOOLS_REFERENCE.md (12633b), docs/PHILOSOPHY.md (4892b), docs/references/contract-input.md (1758b), docs/references/contract-output.md (5232b), docs/references/presentation-nl-query-routing.md (13264b), docs/references/presentation-rules.md (3099b), docs/references/runtime-gemma4-consult.md (1557b), docs/references/schema-holdings-fields.md (2103b), docs/STONKMODE_ARCHITECTURE.md (10414b), docs/STONKMODE_AVATAR_LEGEND.md (2014b), docs/WINDOWS_SETUP_GUIDE.md (9567b), install.yaml (6440b), PRIVACY.md (7809b), PUBLISH.md (423b), README.md (18410b), RFC-v0.1.md (25149b), SECURITY.md (4035b), skill-card.md (2733b), SKILL.md (42065b), STONKMODE.md (5820b), tests/test_bundle_atomic_replace.py (6112b), tests/test_bundle_schema.py (6603b), tests/test_key_resolver.py (6198b), tests/test_mcp_server_envelope.py (6557b), tools/cobol_barrage_v4.py (14794b), tools/generate_sbom.py (14984b), _meta.json (132b)\n\nFile v4.10.0:agent-skills/claude-code/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Claude Code via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"claude-code\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. It describes the Claude Code marketplace\nplugin that connects to InvestorClaw v4.0 (Apache 2.0). The plugin\nships only this file, INSTALL.md, and a manifest — no Python, no bundle.\n-->\n\n# InvestorClaw — Claude Code Plugin (v4.0)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This plugin is MIT-0-licensed.\n\n## What this is\n\nInvestorClaw is a containerized portfolio analysis service. The user\nruns it locally as two Docker containers via `docker compose up -d`;\nthis Claude Code plugin is the thin client that registers the service's\nMCP servers with your agent and exposes two convenience slash commands.\n\nThe plugin is a manifest + this SKILL.md + a one-time config write\nthat points Claude Code at two HTTP MCP endpoints on localhost. All\nanalysis happens inside the user's Docker containers — the agent\nnever installs or imports anything.\n\nThis is the current Claude Code / Claude Desktop path. The plugin\ninstalls directly from this repo and uses the same skill bundle and\nsame container-first runtime as every other agent. See\n`docs/GETTING_STARTED.md` for the canonical setup.\n\n## Slash commands the plugin exposes\n\nThe plugin registers two slash commands so portfolio questions don't\ndepend on the LLM spontaneously deciding to call MCP tools:\n\n- **`/ask <question>`** — routes to the `investorclaw.portfolio_ask`\n  tool. Pass the user's natural-language portfolio question (e.g.,\n  `/ask what are my top 5 dividend payers?`). The deterministic engine\n  picks the right analyzer and returns a structured `ic_result` plus\n  narrative text.\n\n- **`/refresh`** — routes to `investorclaw.portfolio_refresh`. Pulls\n  fresh market data without re-uploading portfolio files. Use this when\n  the user has been chatting for a while and quotes may be stale.\n\nThese commands are deterministic entry points: the user types the slash\ncommand, Claude Code dispatches it to the named MCP tool, the engine\nreturns structured output. **No LLM routing decision is involved at the\nslash-command boundary.** This is by design — slash commands are\nload-bearing for reliability.\n\n## MCP tools available (after install)\n\nWhen InvestorClaw is running and the plugin is loaded, your tool\ncatalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language question router (also\n  invoked by `/ask`)\n- `investorclaw.portfolio_refresh` — market-data refresh (also invoked\n  by `/refresh`)\n- `investorclaw.portfolio_holdings` — current snapshot of positions,\n  values, weights\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top/bottom\n  performers, max drawdown\n- `investorclaw.portfolio_bonds` — bond analytics (YTM, duration, FRED\n  yield curve)\n- `investorclaw.portfolio_analyst` — analyst ratings per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Sharpe / min-vol optimization\n- `investorclaw.portfolio_rebalance` — current vs target with tax impact\n- `investorclaw.portfolio_scenario` — what-if scenarios on holdings\n- `investorclaw.portfolio_cashflow` — projected cashflow from bonds\n- `investorclaw.portfolio_peer` — peer comparison vs benchmark\n- `investorclaw.portfolio_setup` — auto-discover portfolio files in\n  `/data/portfolios/` inside the container\n- `investorclaw.portfolio_guardrails` — view/configure educational-only\n  guardrails\n\n### Memory (`mnemos.*`)\n\n- `mnemos.search_memories` — full-text + semantic search across\n  remembered observations\n- `mnemos.create_memory` — record an observation about the user's\n  preferences, prior questions, or current investing context\n- `mnemos.list_memories` — browse by category / date\n\n## What to ask — example queries\n\n| Intent | Phrasing |\n|---|---|\n| Holdings | \"What's in my portfolio?\" • \"Show me my positions\" |\n| Performance | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" |\n| Bonds | \"Show me my bond exposure and yield-to-maturity\" |\n| Allocation | \"What's my sector exposure?\" • \"How concentrated am I?\" |\n| Optimization | \"Help me rebalance to a 60/40 target\" |\n| Market data | \"What's the current price of NVDA?\" |\n| News | \"Today's news on my holdings\" |\n| Reports | \"Generate today's EOD report\" • \"Prepare an advisor brief\" |\n| Fresh data | \"Prices moved — refresh before answering\" → `/refresh` |\n\nThe first call after a cold cache may take 30–60 seconds while the\ndeterministic pipeline builds the signed envelope. Subsequent calls reuse\nthe cache.\n\n## Recommended model split\n\nClaude Code uses the agent's own LLM — no external API key required.\n\n- **Narrative**: Haiku 4.5 — fast, cheap, ~10× lower output cost than\n  Sonnet. With a clean signed envelope, narrative synthesis is mostly\n  transcription, so the cheap model is sufficient.\n- **Validator**: Sonnet 4.6 (default) or Opus 4.7 (escalation) — gates\n  the Haiku output for fabrication, mis-quoted numbers, and training-leak\n  drift. Validator output is short (~1 K tokens), so the smart-model bill\n  stays low.\n\nCost-shaped: cheap model on the long output, smart model on the short\nsafety check. Total session cost on a 100-position portfolio typically\nlands well under $0.01.\n\n## How to use it\n\n1. **For portfolio questions:** prefer `/ask \"<question>\"`. It's\n   deterministic and surfaces the structured `ic_result` envelope\n   directly. Decorate the narrative if the user wants more context, but\n   trust the engine's numbers — they are computed in code, not inferred.\n\n2. **For follow-up questions:** call `mnemos.search_memories` first to\n   pull relevant prior observations (e.g., user's risk tolerance, prior\n   discussions about specific holdings). Then call the appropriate\n   `investorclaw.*` tool with that context in mind.\n\n3. **For \"what changed\" questions:** call `mnemos.search_memories` for\n   prior portfolio summaries; compare against the current\n   `investorclaw.portfolio_holdings` output.\n\n4. **After delivering an analysis:** call `mnemos.create_memory` to\n   record any salient observations the user might want to remember\n   (e.g., \"User flagged BABA as a never-sell sentimental position\n   during the 2026-04-30 review\"). Don't over-record — only record what\n   wouldn't be obvious from re-reading the data later.\n\n5. **When the user uploads a portfolio file:** stage the attachment to\n   the bind-mounted `portfolios/` directory (see top-level SKILL.md for\n   the agent file-staging contract), then call `portfolio_setup`\n   followed by `portfolio_ask`. Or direct the user to the dashboard at\n   http://localhost:18092 if they prefer to drop files there directly.\n\n## Presentation rules\n\n- Preserve quoted source text, numerical values, timestamps, and\n  freshness labels exactly.\n- Never fabricate market, ticker, bond, news, or optimization data.\n- If the engine's signed envelope lacks a requested fact, say\n  InvestorClaw did not provide it and quote the engine's limitation\n  verbatim.\n- If data looks stale, suggest `/refresh` before answering.\n\n## Important behaviors\n\n- **Deterministic at the data layer.** The investorclaw tools compute\n  numbers in code. If a portfolio format isn't recognized, you'll get a\n  structured error with detected columns and supported formats. Don't\n  ask the LLM to disambiguate — surface the error and direct the user\n  to the dashboard's column-mapping wizard at\n  http://localhost:18092/portfolios/map.\n\n- **Educational only — never investment advice.** All outputs include\n  a disclaimer envelope. Echo it when summarizing for the user. Do not\n  recommend specific buys or sells.\n\n- **No money movement, no trades.** This plugin cannot execute trades,\n  move money, place orders, or access brokerage accounts. If the user\n  asks for any of those, decline and direct them to a licensed advisor.\n\n- **Local by default.** MCP endpoint is on `localhost:18090` (REST +\n  MCP); dashboard is on `localhost:18092`. If the user has deployed the\n  service to a remote host (Tailscale VM, cloud), the URLs change but\n  the tool surface is identical — the user edits the manifest's MCP\n  server URL.\n\n## When the plugin can't reach the service\n\nIf `investorclaw.*` calls fail with connection errors, the user's\nDocker containers aren't running. Tell the user:\n\n1. Open a terminal and run `docker compose ps` in `~/.investorclaw/`\n2. If containers aren't listed: `cd ~/.investorclaw && docker compose up -d`\n3. If Docker itself isn't installed: see INSTALL.md for the prereq link\n4. If the MCP servers still don't respond after `docker compose up -d`:\n   wait ~10 seconds for health checks, then retry\n\nSee INSTALL.md for the full bring-up sequence.\n\n## Install\n\n**Claude Code / Claude Desktop:**\n\n```\n/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw\n```\n\n**OpenClaw / ZeroClaw / Hermes users:** install via ClawHub:\n\n```bash\nclawhub install investorclaw\n```\n\n## What this plugin does NOT do\n\n- Does not install or execute any code on the agent side — it's a\n  manifest, this SKILL.md, and an MCP-server config write\n- Does not download or execute portfolio data on the agent side\n- Does not manage credentials (the engine reads broker CSVs the user\n  drops in the dashboard)\n- Does not execute trades or move money\n- Does not give investment advice\n\n## License + attribution\n\n- This plugin (manifest, SKILL.md, INSTALL.md) is **MIT-0-licensed**.\n- The InvestorClaw service it connects to is **Apache 2.0**, hosted at\n  `github.com/argonautsystems/InvestorClaw` and the runtime container at\n  `mnemos-os/ic-engine`.\n- The MNEMOS memory service is **Apache 2.0**, hosted at\n  `mnemos-os/mnemos-rs`.\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This plugin is MIT-0-licensed.\n\nFile v4.10.0:agent-skills/claude-desktop/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Claude Desktop via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"claude-desktop\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. The InvestorClaw service it connects to is\nApache 2.0. See ../../LICENSE-MIT-0 for the full MIT text.\n-->\n\n# InvestorClaw — Claude Desktop Reference\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This reference doc is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## What this is\n\n[InvestorClaw](https://investorclaw.app) is a containerized, deterministic\nportfolio analysis service. It runs on your machine as two Docker\ncontainers (a Rust memory server and a Python analysis engine) and\nexposes its capabilities to Claude Desktop over MCP-HTTP.\n\nClaude Desktop has no plugin system — instead, it connects to MCP servers\ndeclared in `claude_desktop_config.json`. Once you run\n`docker compose up -d` and add two short blocks to that config file\n(see `INSTALL.md`), Claude Desktop gains an entire portfolio-analysis\ntoolkit that you can invoke just by chatting.\n\nThere is no marketplace step. There is no plugin to install. The\nservice is the substrate; Claude Desktop is the interface.\n\n## Tools that become available after install\n\nOnce both MCP servers are wired up and Claude Desktop has been fully\nquit and relaunched, the model gains two new tool namespaces.\n\n### Portfolio analysis (`investorclaw.*`)\n\n| Tool | What it does |\n|---|---|\n| `investorclaw.portfolio_ask` | Natural-language question routed through the deterministic engine |\n| `investorclaw.portfolio_holdings` | Current snapshot of positions, values, and weights |\n| `investorclaw.portfolio_performance` | Sharpe, volatility, top/bottom performers, max drawdown |\n| `investorclaw.portfolio_bonds` | Bond analytics — YTM, duration, FRED yield curve |\n| `investorclaw.portfolio_analyst` | Analyst consensus ratings per holding |\n| `investorclaw.portfolio_news` | News correlation for held positions |\n| `investorclaw.portfolio_lookup` | Ticker / account lookup |\n| `investorclaw.portfolio_optimize` | Modern Portfolio Theory (Sharpe / min-vol) |\n| `investorclaw.portfolio_rebalance` | Current vs. target with tax impact |\n| `investorclaw.portfolio_scenario` | What-if scenarios (rate moves, drawdowns) |\n| `investorclaw.portfolio_cashflow` | Projected dividends and bond coupons |\n| `investorclaw.portfolio_peer` | Peer comparison vs. benchmark |\n| `investorclaw.portfolio_setup` | Auto-discover portfolio files in `/data/portfolios/` |\n| `investorclaw.portfolio_refresh` | Refresh market data without re-uploading files |\n| `investorclaw.portfolio_guardrails` | View / configure educational-only guardrails |\n\n### Memory (`mnemos.*`)\n\n| Tool | What it does |\n|---|---|\n| `mnemos.search_memories` | Full-text + semantic search across saved observations |\n| `mnemos.create_memory` | Record an observation about preferences, prior questions, or context |\n| `mnemos.list_memories` | Browse memories by category or date |\n\n## How to use it in Claude Desktop\n\nYou don't invoke tools by name — you just talk to Claude. Examples:\n\n| Intent | Phrasing |\n|---|---|\n| Holdings | \"What's in my portfolio?\" • \"Show me my positions\" |\n| Performance | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" |\n| Bonds | \"Show me my bond exposure and yield-to-maturity\" |\n| Allocation | \"What's my sector exposure?\" |\n| Optimization | \"Help me rebalance to a 60/40 target\" |\n| Market data | \"What's the current price of NVDA?\" |\n| News | \"Today's news on my holdings\" |\n| Reports | \"Generate today's EOD report\" • \"Prepare a brief for my advisor\" |\n| Stress test | \"What if rates rise 100 bps?\" |\n| Memory | \"Remember that I treat BABA as a sentimental hold\" • \"What did we discuss about my bond ladder last time?\" |\n\nClaude routes the request to the right tool, surfaces the structured\nresult, and decorates it with narrative context. The first call after a\ncold cache may take 30–60 seconds while the deterministic pipeline builds\nthe signed envelope; subsequent calls reuse the cache.\n\n## Recommended model split\n\nClaude Desktop uses the agent's own LLM — no external API key required.\n\n- **Narrative**: Haiku 4.5 — fast, cheap, ~10× lower output cost than\n  Sonnet. With a clean signed envelope, narrative synthesis is mostly\n  transcription, so the cheap model is sufficient.\n- **Validator**: Sonnet 4.6 (default) or Opus 4.7 (escalation) — gates\n  the Haiku output for fabrication, mis-quoted numbers, and training-leak\n  drift. Validator output is short (~1 K tokens), so the smart-model bill\n  stays low.\n\nCost-shaped: cheap model on the long output, smart model on the short\nsafety check.\n\n## Important behaviors\n\n- **Deterministic by design.** Portfolio math is not generated by an\n  LLM. The Python engine in the ic-engine container computes every\n  number. Claude reports those numbers; it does not invent them. If\n  Claude ever appears to fabricate a holding or a return, that's a bug\n  — file it.\n- **Educational only — never investment advice.** All outputs include\n  a disclaimer envelope. Claude will echo it when summarizing.\n- **Localhost-only by default.** Both MCP servers bind to `127.0.0.1`.\n  Nothing leaves your machine unless you explicitly enable a remote\n  deployment via the dashboard.\n- **What Claude sees vs what stays local.** Claude Desktop's\n  transcript receives the agent's tool-call inputs and outputs — that\n  includes the user's question, the structured `ic_result` envelope\n  (ticker symbols, asset-class breakdowns, computed metrics), and\n  the narrator's prose answer. **It does NOT receive raw broker CSVs**\n  — those stay on your local filesystem in the bind-mounted\n  `./portfolios/` directory. Account numbers and SSNs are scrubbed at\n  ingest. See [PRIVACY.md](../../PRIVACY.md) for the full data-flow\n  matrix.\n- **Unknown CSV format?** The engine returns a structured error with\n  detected columns. Claude will direct you to the column-mapping\n  wizard at `http://localhost:18092/portfolios/map` rather than\n  guessing.\n\n## What this does NOT do\n\n- Does not place trades or move money\n- Does not give personalized investment advice\n- Does not connect directly to broker accounts (you upload CSV / XLS / PDF)\n- Does not require an internet connection for portfolio math (only for\n  market-data refresh, which gracefully degrades without API keys)\n\n## Install\n\nClaude Desktop connects to InvestorClaw via MCP servers — there is no plugin to install from a marketplace. The service runs locally via Docker Compose.\n\n**Start the service:**\n\n```bash\ngit clone https://github.com/mnemos-os/mnemos-ic-runtime.git ~/.investorclaw\ncd ~/.investorclaw\nmkdir -p portfolios\ndocker compose up -d\n```\n\nThen add the MCP server blocks to `claude_desktop_config.json` and restart Claude Desktop. See `INSTALL.md` in this directory for the exact config snippet.\n\n**OpenClaw / ZeroClaw / Hermes users:** install via ClawHub:\n\n```bash\nclawhub install investorclaw\n```\n\n## Where to go next\n\n- **`INSTALL.md`** in this directory — step-by-step install\n  instructions including the exact Claude Desktop config edit.\n- **`config-snippet.json`** in this directory — the JSON block to merge\n  into `claude_desktop_config.json`.\n- **Dashboard** at `http://localhost:18092` once running — upload\n  portfolio files, configure provider keys, manage memory retention,\n  inspect MCP traffic.\n\n## Reporting issues\n\nThis SKILL.md describes the InvestorClaw service. If a tool returns an\nunexpected result, the issue is in the service\n([`argonautsystems/InvestorClaw`](https://github.com/argonautsystems/InvestorClaw),\nApache 2.0) or in the runtime bridge\n([`mnemos-os/mnemos-ic-runtime`](https://github.com/mnemos-os/mnemos-ic-runtime),\nApache 2.0), not in this MIT-0-licensed reference doc.\n\nFile v4.10.0:agent-skills/hermes/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Hermes via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"hermes\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed and tailored for the NousResearch Hermes\nAgent (v0.12+). The InvestorClaw service it connects to is Apache 2.0.\nSee LICENSE-MIT-0 in this directory.\n-->\n\n# InvestorClaw — Hermes Skill (v4.0)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This skill file is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## TL;DR for hermes operators\n\nInvestorClaw v4.0 turns hermes into a **first-class portfolio-analysis\nagent**. The service runs as two local Docker containers and exposes\nits capabilities over MCP-HTTP. Hermes 0.12+ registers the MCP servers\nas native function-callable tool sources — the LLM sees\n`investorclaw.portfolio_ask`, `mnemos.search_memories`, and friends in\nthe same tool catalog as `browser_*`, `terminal`, and `skill_view`.\n\n**Headline upgrade — HER-1 is gone.** Read the next section if you\nremember v2.x.\n\n## What changed since v2.x — HER-1 elimination\n\nIf you ran InvestorClaw v2.x against hermes, you hit **HER-1**: the\n\"skill-as-doc-hint\" caveat. In v2.x, InvestorClaw shipped as a hermes\nskill bundle injected into the system prompt. The LLM had to use\nhermes meta-tools (`skill_view`, `terminal`) to *read* the skill\ndocumentation and then *imitate* the analyst commands by shelling out.\nThat indirection layer was lossy and slow, and the Linux baseline\nempirical reliability landed around **8% (2.3/30)** on the standard\nprompt barrage — vs **77%** on zeroclaw, which had real tool\nregistration.\n\n**v4.0 ends that.** There is no skill bundle to inject. The\ndeterministic engine runs as a containerized service and publishes its\nanalytical surface over MCP-HTTP. Hermes 0.12+ registers MCP servers\ndeclaratively in `~/.hermes/config.yaml` and exposes their tools to\nthe LLM directly — same dispatch path as any other built-in tool.\n\nWhat this means in practice for hermes users:\n\n- **No more meta-tool indirection.** The LLM calls\n  `investorclaw.portfolio_ask` directly, not via `skill_view` →\n  `terminal` → fragile shell parsing.\n- **Reliability now matches other agent runtimes.** Expect the same\n  routing accuracy as zeroclaw / openclaw — roughly an order of\n  magnitude better than v2.x on the same prompts.\n- **Memory is built in.** The `mnemos.*` tool family gives hermes a\n  persistent memory layer it never had before, scoped to InvestorClaw\n  observations and user preferences.\n- **No skill bundle to keep in sync.** Bumping the service to a newer\n  ic-engine version is `docker compose pull && docker compose up -d`.\n  The tool catalog hermes sees is whatever the running service\n  publishes.\n\n## Architecture (hermes ⇄ InvestorClaw)\n\n```\nhermes (host)\n  │\n  │  config.yaml mcp_servers:\n  │     investorclaw → http://localhost:18090/mcp\n  │     mnemos       → http://localhost:5002/mcp\n  ▼\nDocker compose (~/.investorclaw/compose.yml)\n  ├── argonautsystems/ic-engine:4.7.7-cpu       :8090   portfolio analysis MCP\n  └── mnemos-os/mnemos-rs:4.2       :5002   memory + KG MCP\n       (dashboard at :8092 for portfolio upload + key config)\n```\n\nThe user runs `docker compose up -d` to install the service. Hermes\ndiscovers tools at startup by handshaking with each MCP server.\n\n## Tool surface\n\nWhen InvestorClaw is running and hermes has reloaded its config,\nthe tool catalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language portfolio question\n  routed through the deterministic engine\n- `investorclaw.portfolio_holdings` — current snapshot of positions,\n  values, weights\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top /\n  bottom performers, max drawdown\n- `investorclaw.portfolio_bonds` — bond analytics (YTM, duration,\n  FRED yield curve)\n- `investorclaw.portfolio_analyst` — analyst ratings per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Sharpe / min-vol optimization\n- `investorclaw.portfolio_rebalance` — current vs target with tax\n  impact\n- `investorclaw.portfolio_scenario` — what-if scenarios on holdings\n- `investorclaw.portfolio_cashflow` — projected cashflow from bonds\n- `investorclaw.portfolio_peer` — peer comparison vs benchmark\n- `investorclaw.portfolio_setup` — auto-discover portfolio files in\n  `/data/portfolios/`\n- `investorclaw.portfolio_refresh` — refresh market data without\n  re-uploading files\n- `investorclaw.portfolio_guardrails` — view / configure\n  educational-only guardrails\n\n### Memory (`mnemos.*`)\n\n- `mnemos.search_memories` — full-text + semantic search across\n  remembered observations\n- `mnemos.create_memory` — record an observation about user\n  preferences, prior questions, or current investing context\n- `mnemos.list_memories` — browse by category / date\n\n## Usage idioms\n\nJust ask portfolio questions in chat. Hermes' LLM picks the right\nMCP tool from the catalog automatically.\n\n### Cookbook — what to ask\n\n| Intent | Phrasing |\n|---|---|\n| Holdings | \"What's in my portfolio?\" • \"Show me my positions\" |\n| Performance | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" |\n| Bonds | \"Show me my bond exposure and yield-to-maturity\" |\n| Allocation | \"What's my sector exposure?\" |\n| Optimization | \"Help me rebalance to a 60/40 target\" |\n| Market data | \"What's the current price of NVDA?\" |\n| News | \"Today's news on my holdings\" |\n| Reports | \"Generate today's EOD report\" • \"Prepare an advisor brief\" |\n| Fresh data | \"Prices moved — refresh before answering\" |\n\nThe first call after a cold cache may take 30–60 seconds while the\ndeterministic pipeline builds the signed envelope; subsequent calls reuse\nthe cache.\n\n```bash\nhermes chat -q \"What's in my portfolio?\" \\\n  --provider together -m google/gemma-4-31B-it --yolo\n\nhermes chat -q \"What changed since last week?\" \\\n  --provider together -m google/gemma-4-31B-it --yolo\n\nhermes chat -q \"Refresh my market data and show me the worst\n                performer.\" \\\n  --provider together -m google/gemma-4-31B-it --yolo\n```\n\n## Recommended narrative model\n\nhermes routes its chat completions through whichever provider the user\nselects on the command line or in `~/.hermes/config.yaml`. **Anthropic\non hermes — paid path only since 2026-04-04**: routing OAuth-\nsubscription tokens to a claws-agent violates Anthropic's ToS per their\nApr 3 announcement. To use Anthropic models you need either (a) the\ndiscounted \"extra usage bundle\" add-on for your subscription, or (b) a\ndirect Anthropic API key. Even with paid credits, Anthropic isn't\ncost-competitive with Together for InvestorClaw narrative work; we\ndon't deploy Anthropic on our own fleet for hermes.\n\nRecommended providers for the InvestorClaw narrative tier (set\n`TOGETHER_API_KEY` in the container's `portfolios/keys.env` or via\n`portfolio_keys_set`):\n\n- **Default narrative** — Together AI `google/gemma-4-31B-it` — serverless\n  tier, ~100 tok/s, ~$0.0008 / 1 K tokens, fleet default. This is what the\n  InvestorClaw container expects via `INVESTORCLAW_NARRATIVE_MODEL`.\n- **Higher-quality alternative** — Together AI `MiniMaxAI/MiniMax-M2` —\n  larger context, but moved off Together's serverless tier 2026-05;\n  requires a paid dedicated endpoint.\n- **Local-only / offline** — Ollama `gemma4:e4b` on host — zero cloud\n  cost, GPU-bound, no key required.\n\nRecommended LLM behavior (the model already does this on its own,\nbut worth knowing):\n\n1. **Portfolio questions →** call `investorclaw.portfolio_ask` with\n   the user's natural-language question. The deterministic engine\n   routes it to the correct analyzer and returns a structured\n   `ic_result` envelope plus a narrative body.\n2. **Follow-up questions →** call `mnemos.search_memories` first to\n   pull relevant prior observations (risk tolerance, prior holdings\n   discussions). Then call the appropriate `investorclaw.*` tool with\n   that context.\n3. **What-changed questions →** combine `mnemos.search_memories` for\n   prior portfolio summaries with `investorclaw.portfolio_holdings`\n   for the current snapshot; let the LLM diff them.\n4. **After delivering an analysis →** call `mnemos.create_memory` to\n   record salient observations the user might want to remember\n   (e.g., \"User flagged BABA as a never-sell sentimental position\").\n   Don't over-record.\n\n## Important behaviors\n\n- **Deterministic at the data layer.** If a portfolio file format\n  isn't recognized, the tool returns a structured error with detected\n  columns and supported formats. Surface that to the user — point\n  them at the dashboard's column-mapping wizard at\n  http://localhost:18092/portfolios/map.\n- **Educational only — never investment advice.** All outputs include\n  the disclaimer envelope. Echo it when summarizing.\n- **MCP servers are local by default** at `http://localhost:18090/mcp`\n  and `http://localhost:5002/mcp`. Remote deployments (Tailscale,\n  cloud) just change the URLs — the tool surface is identical.\n- **No portfolio? No problem.** The LLM can talk about generic\n  market questions via `investorclaw.portfolio_ask` even before a\n  portfolio file is uploaded; it'll guide the user to the dashboard.\n\n## Install pointer\n\n**Hermes does not use ClawHub** — ClawHub is the OpenClaw / ZeroClaw\nskill registry. Running `clawhub install` drops the skill into an\nopenclaw path, not Hermes (and `hermes skills install investorclaw`\nwon't find it — it isn't in a Hermes registry). Install into Hermes\nmanually:\n\n1. Copy this skill directory into `~/.hermes/skills/investorclaw/`.\n2. Bring up the InvestorClaw container (the engine):\n   `cd ~/.investorclaw && docker compose up -d`.\n3. Paste the MCP block from `config-snippet.yaml` into\n   `~/.hermes/config.yaml`, then restart Hermes.\n\n`INSTALL.md` next to this file has the full step-by-step (skill drop,\ncompose up, config block, restart, verify).\n\n> The **dashboard** (`http://localhost:18092`) and the agent's MCP\n> tools both come from the container in step 2 — the skill itself is\n> only the agent-side pointer, so Docker must be running either way.\n\n(Claude Code / Claude Desktop users instead install the marketplace\nplugin from `argonautsystems/InvestorClaw`; see `docs/GETTING_STARTED.md`.)\n\n## What this skill does NOT do\n\n- Does not manage money or execute trades\n- Does not give investment advice\n- Does not access user accounts or move funds\n- Educational outputs only\n\n## Reporting issues\n\nThis skill describes the InvestorClaw service from a hermes operator's\nperspective. If a tool returns an unexpected result, the issue is in\nthe upstream service (Apache 2.0,\n`mnemos-os/mnemos-ic-runtime` + `argonautsystems/InvestorClaw`), not in this\nSKILL.md. If hermes can't see the tools at all, that's an install\nissue — work through `INSTALL.md` and the troubleshooting section\nthere.\n\nFile v4.10.0:agent-skills/openclaw/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for OpenClaw via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"openclaw\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. The InvestorClaw service it connects to\nis Apache 2.0. See the InvestorClaw repository for that license.\n-->\n\n# InvestorClaw — Skill (openclaw runtime)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This skill file is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## What this is\n\nInvestorClaw is a containerized portfolio-analysis service exposed to\nopenclaw as **two MCP-HTTP servers**:\n\n- `investorclaw` — portfolio analysis tools at `http://localhost:18090/mcp`\n- `mnemos` — memory + knowledge graph at `http://localhost:5002/mcp`\n\nBoth run inside a Docker compose stack on the user's machine\n(`docker compose up -d` is the entire service install). openclaw connects\nto them as native MCP servers via its `mcp.servers` config block —\nno plugin manifest, no `dist/index.js`, no npm install, no skill\nbootstrap files.\n\nIf openclaw runs in a container itself, the two MCP URLs reach the host's\nloopback through the compose bridge network or `host.docker.internal`,\ndepending on how the openclaw container is launched. See `INSTALL.md`.\n\n## Tool surface\n\nWhen the service is running, openclaw's tool catalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language portfolio question\n  routed through the deterministic engine\n- `investorclaw.portfolio_holdings` — current snapshot of positions,\n  values, weights\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top/bottom\n  performers, max drawdown\n- `investorclaw.portfolio_bonds` — bond analytics (YTM, duration, FRED\n  yield curve)\n- `investorclaw.portfolio_analyst` — analyst ratings per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Sharpe / min-vol optimization\n- `investorclaw.portfolio_rebalance` — current vs target with tax impact\n- `investorclaw.portfolio_scenario` — what-if scenarios on holdings\n- `investorclaw.portfolio_cashflow` — projected cashflow from bonds\n- `investorclaw.portfolio_peer` — peer comparison vs benchmark\n- `investorclaw.portfolio_setup` — auto-discover portfolio files in\n  `/data/portfolios/`\n- `investorclaw.portfolio_refresh` — refresh market data without\n  re-uploading files\n- `investorclaw.portfolio_guardrails` — view educational-only guardrails\n\n### Memory (`mnemos.*`)\n\n- `mnemos.search_memories` — full-text + semantic search across\n  remembered observations\n- `mnemos.create_memory` — record an observation about the user's\n  preferences, prior questions, or current investing context\n- `mnemos.list_memories` — browse by category / date\n\n## How users interact with it\n\nUsers ask portfolio questions in openclaw chat. The LLM sees the MCP\ntools in its function-calling schema and routes the question to the\nright tool automatically. Examples:\n\n- \"What's in my portfolio?\" → `investorclaw.portfolio_holdings`\n- \"How am I doing this year?\" → `investorclaw.portfolio_performance`\n- \"What did I tell you about BABA last month?\" → `mnemos.search_memories`\n\n| Intent | Phrasing |\n|---|---|\n| Holdings | \"What's in my portfolio?\" • \"Show me my positions\" |\n| Performance | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" |\n| Bonds | \"Show me my bond exposure and yield-to-maturity\" |\n| Allocation | \"What's my sector exposure?\" |\n| Optimization | \"Help me rebalance to a 60/40 target\" |\n| Market data | \"What's the current price of NVDA?\" |\n| News | \"Today's news on my holdings\" |\n| Reports | \"Generate today's EOD report\" • \"Prepare an advisor brief\" |\n\nThe first call after a cold cache may take 30–60 seconds while the\ndeterministic pipeline builds the signed envelope; subsequent calls reuse\nthe cache.\n\nA typical flow:\n\n1. User asks: *\"What changed since last review?\"*\n2. openclaw's LLM calls `mnemos.search_memories` for prior portfolio\n   context.\n3. LLM calls `investorclaw.portfolio_holdings` for the current snapshot.\n4. LLM compares the two and synthesizes a narrative.\n5. LLM calls `mnemos.create_memory` to record salient observations from\n   the review.\n\n## Recommended narrative model\n\nopenclaw's chat completion goes through whichever provider is configured\nin `models.providers.<name>` of `~/.openclaw/openclaw.json`. **Anthropic\non openclaw — paid path only since 2026-04-04**: routing OAuth-\nsubscription tokens to a claws-agent violates Anthropic's ToS per their\nApr 3 announcement. To use Anthropic models you need either (a) the\ndiscounted \"extra usage bundle\" add-on for your subscription, or (b) a\ndirect Anthropic API key. Even with paid credits, Anthropic isn't\ncost-competitive with Together for InvestorClaw narrative work; we\ndon't deploy Anthropic on our own fleet for openclaw.\n\nRecommended:\n\n- **Default narrative** — Together AI `google/gemma-4-31B-it` — serverless\n  tier, ~100 tok/s, ~$0.0008 / 1 K tokens, fleet default. This is what the\n  InvestorClaw container expects via `INVESTORCLAW_NARRATIVE_MODEL`.\n- **Higher-quality alternative** — Together AI `MiniMaxAI/MiniMax-M2` —\n  larger context, but moved off Together's serverless tier 2026-05;\n  requires a paid dedicated endpoint.\n- **Local-only / offline** — Ollama `gemma4:e4b` on host — zero cloud\n  cost, GPU-bound, no key required.\n\nSet `TOGETHER_API_KEY` in the InvestorClaw container's\n`portfolios/keys.env` (or via `portfolio_keys_set`) so the engine can\nsynthesize narratives directly. openclaw's own model config is a\nseparate concern.\n\nAfter delivering analysis, the LLM should record only non-obvious\nobservations the user might want next time — not every detail, just the\nones that would be hard to recover from re-reading the data.\n\n## Important behaviors\n\n- **The investorclaw tools are deterministic at the data layer.** Each\n  response includes a structured `ic_result` envelope plus a narrative\n  text body. Trust the structured envelope — it is the source of truth.\n  The narrative is decoration. If a portfolio file format isn't\n  recognized, the tool returns a structured error with detected columns;\n  surface that error and direct the user to the dashboard's column-mapping\n  wizard at `http://localhost:18092/portfolios/map`.\n\n- **Educational only — never investment advice.** All outputs include\n  the disclaimer envelope. Echo it when summarizing for the user. Do not\n  recommend buying, selling, or holding specific securities.\n\n- **The MCP servers run on loopback by default.** `localhost:18090` and\n  `localhost:5002`. If the user deploys remotely (Tailscale VM, cloud\n  host), the URLs change but the tool surface is identical.\n\n- **openclaw's own LLM provider config is separate.** openclaw routes\n  *its* chat completions through `models.providers.<name>` in\n  `~/.openclaw/openclaw.json` (Together, OpenAI, Ollama, etc.). That is\n  unrelated to InvestorClaw's optional narrative tier, which is configured\n  inside the InvestorClaw dashboard at `http://localhost:18092/`.\n\n## v4.0 vs v2.x — what's different on openclaw\n\nv4.0 eliminates the v2.x openclaw install friction:\n\n- **No** `openclaw.plugin.json` manifest (there is no plugin)\n- **No** `dist/index.js` (there is no plugin shim to compile)\n- **No** install step inside an openclaw container\n- **No** workspace bootstrap files (`BOOTSTRAP.md` / `IDENTITY.md` /\n  `USER.md`) to seed\n- **No** schema-validation daemon to fight when writing provider config\n  for the plugin\n\nThe integration is just two MCP server URLs. openclaw's existing native\nMCP support handles the rest.\n\n## What this skill does NOT do\n\n- Does not manage money or execute trades\n- Does not give investment advice\n- Does not access user accounts or move funds\n- Educational outputs only\n\n## Install\n\n**OpenClaw / ZeroClaw / Hermes (ClawHub):**\n\n```bash\nclawhub install investorclaw\n```\n\n**Claude Code / Claude Desktop:**\n\n```\n/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw\n```\n\nSee `INSTALL.md` in this directory for manual install steps.\n\n## Reporting issues\n\nThis SKILL.md describes how openclaw connects to the InvestorClaw\nservice. If a tool returns an unexpected result, the issue is in the\nservice (Apache 2.0 — `mnemos-os/mnemos-ic-runtime` and\n`argonautsystems/InvestorClaw`), not in this file. If openclaw fails to register\nthe MCP servers, see `INSTALL.md` in this directory — in particular the\nnote about always using the validated `openclaw mcp set` /\n`openclaw config patch` CLI rather than editing `openclaw.json` by hand.\n\nFile v4.10.0:agent-skills/zeroclaw/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for ZeroClaw via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.10.0\",\"runtime\":\"zeroclaw\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.10.0-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n## Authoritative operating contract\n\nThese rules govern any agent using this skill. Examples elsewhere in this file\nare reference only and never override them.\n\n### Data integrity — InvestorClaw is the only source of truth\n- Every price, percent, dollar figure, or market fact an agent states MUST come\n  from an InvestorClaw tool result returned in the SAME turn. InvestorClaw\n  returns HMAC-signed envelopes; that signed data is the only source of truth.\n- Never invent, estimate, guess, or use the model's own training knowledge for\n  any number. If a tool did not return it this turn, do not state it — say\n  \"InvestorClaw returned no data for that\".\n- Tool prose with no concrete numbers = no data; never convert it into a figure.\n\n### Current tool surface (underscore namespace)\n- `investorclaw__portfolio_market_snapshot(symbols?, benchmarks?)` — real-time\n  prices + day-change% for holdings and benchmarks (SPX/NDX/DJI/VIX, BTC/ETH).\n  `symbols` is a COMMA-SEPARATED STRING (e.g. \"NVDA,AAPL\"), not a list. No args =\n  holdings + benchmarks. Use this (not portfolio_ask) for any \"price of X\" and to\n  read the portfolio against the market.\n- `investorclaw__portfolio_performance_window(period=...)` — return / P&L /\n  movers over a window. period: 1d, 1w, 1mo, 1y, 5y, 10y, 20y, max, or natural\n  phrases (\"today\", \"last week\", \"last year\", \"entire history\").\n- `investorclaw__portfolio_ask(question=...)` — analysis / explanation.\n\nOlder `investorclaw.*` dot-namespace examples below are stale; the underscore\nforms above are the current tool names.\n\n## Autonomous / always-on monitoring agents\n\nFor unattended agents (scheduled monitors and alerters — e.g. a MarketWatch\nagent), in addition to the contract above:\n- Drive each run from a tool call first; never answer a market question from\n  memory. A scheduled \"poll\" means call `portfolio_market_snapshot`.\n- Threshold scan: call `portfolio_market_snapshot`, then emit ONE terse line\n  only when a holding or benchmark breaches the configured move (e.g. ±3% a\n  holding, ±10% VIX); otherwise emit a single `NO_ALERT` token and stop.\n- If the required tool errors or returns no data, emit a fixed marker such as\n  `OPS_FAIL market_snapshot unavailable` and stop — never fabricate a reassuring\n  number to fill the gap.\n- No clarifying questions in unattended mode; map intent and act.\n- Periodic / EOD reports: pull `portfolio_performance_window` for the window,\n  then `portfolio_market_snapshot` for index closes; report numbers verbatim.\n- Always read holdings in the context of the benchmarks in the same snapshot.\n- Delivery is push, terse, numbers-first. Educational, not personalized advice.\n\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. The InvestorClaw service it connects to is\nApache 2.0. See the project LICENSE-MIT-0 for full text.\n\nThis skill is audit-compliant for zeroclaw 0.7.3+: no scripts, no\nsymlinks, no curl-pipe-shell patterns, no remote markdown links.\n-->\n\n# InvestorClaw — zeroclaw skill\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> Skill manifest is MIT; the underlying service is Apache 2.0.\n\n## What this is\n\nInvestorClaw is a containerized portfolio analysis service that exposes\nits analytical capabilities to your zeroclaw agent over MCP-HTTP. Two\nlocal servers register as separate MCP namespaces in your tool catalog:\n\n- `investorclaw` (port 8090) — deterministic portfolio analysis\n- `mnemos` (port 5002) — memory + knowledge graph\n\nYou speak to zeroclaw in natural language. zeroclaw routes the request\nto the right MCP tool, calls it, and synthesizes a reply. **The user is\nthe orchestrator; the service is the substrate; zeroclaw is the\ninterface.**\n\n## How zeroclaw connects\n\nzeroclaw on master supports MCP via the `[mcp.servers.<name>]` block in\n`~/.zeroclaw/config.toml`. Once that config is in place and the\nInvestorClaw containers are running, the tools are auto-registered at\nagent startup. No skill code, no shell-out, no per-tool wiring.\n\nThe two services run as a Docker compose stack, bound to localhost:\n\n- `mnemos-os/mnemos-rs:4.2` → `localhost:5002`\n- `argonautsystems/ic-engine:4.7.7-cpu` → `localhost:18090`\n\n**Quick install via ClawHub:**\n\n```bash\nclawhub install investorclaw\n```\n\n**Claude Code / Claude Desktop:**\n\n```\n/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw\n```\n\nClaude Code and Claude Desktop use this repo's container-first plugin;\nsee `docs/GETTING_STARTED.md`.\n\nIf the user has not installed yet, see `INSTALL.md` in this skill\ndirectory for full manual setup details. zeroclaw cannot install the service from\ninside a skill (audit rules forbid scripted execution from skill\npayload), but the future `zeroclaw services install <compose-url>`\nupstream subcommand will close that gap with a single command.\n\n## Tool surface\n\nOnce the MCP servers are registered, your tool catalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language question routed\n  through the deterministic engine; returns a structured `ic_result`\n  envelope plus narrative text\n- `investorclaw.portfolio_holdings` — current snapshot: positions,\n  values, weights, cost basis\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top/bottom\n  performers, max drawdown, returns over horizons\n- `investorclaw.portfolio_bonds` — bond analytics: YTM, duration,\n  convexity, FRED yield-curve overlay\n- `investorclaw.portfolio_analyst` — analyst consensus per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Modern Portfolio Theory: Sharpe-\n  max, min-vol, target-return frontiers\n- `investorclaw.portfolio_rebalance` — current vs. target allocation\n  with capital-gains impact\n- `investorclaw.portfolio_scenario` — what-if scenarios (rate shocks,\n  drawdowns, correlation breaks)\n- `investorclaw.portfolio_cashflow` — projected cashflow calendar\n  (coupons, dividends, maturities)\n- `investorclaw.portfolio_peer` — peer/benchmark comparison\n- `investorclaw.portfolio_setup` — auto-discover portfolio files in\n  `/data/portfolios/`\n- `investorclaw.portfolio_refresh` — refresh market data without\n  re-uploading files\n- `investorclaw.portfolio_guardrails` — view/configure educational-only\n  guardrails\n\n### Memory (`mnemos.*`)\n\n- `mnemos.search_memories` — full-text + semantic search\n- `mnemos.create_memory` — record an observation about the user's\n  preferences, prior questions, or current investing context\n- `mnemos.list_memories` — browse by category / date range\n\n## Usage idioms\n\nzeroclaw routes natural-language requests to MCP tools without manual\nhinting. These are the expected interaction shapes:\n\n### Cookbook — what to ask\n\n| Intent | Phrasing |\n|---|---|\n| Holdings | \"What's in my portfolio?\" • \"Show me my positions\" |\n| Performance | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" |\n| Bonds | \"Show me my bond exposure and yield-to-maturity\" |\n| Allocation | \"What's my sector exposure?\" |\n| Optimization | \"Help me rebalance to a 60/40 target\" |\n| Market data | \"What's the current price of NVDA?\" |\n| News | \"Today's news on my holdings\" |\n| Reports | \"Generate today's EOD report\" • \"Prepare an advisor brief\" |\n\nThe first call after a cold cache may take 30–60 seconds while the\ndeterministic pipeline builds the signed envelope; subsequent calls reuse\nthe cache.\n\n**Snapshot questions**\n\n- \"What's in my portfolio?\" → `investorclaw.portfolio_holdings`\n- \"How are my bonds doing?\" → `investorclaw.portfolio_bonds`\n- \"What's my Sharpe ratio?\" → `investorclaw.portfolio_performance`\n\n**Open-ended analysis**\n\n- \"Why is my portfolio down this week?\" →\n  `investorclaw.portfolio_ask` (the engine routes to the right\n  internal analyzer, e.g., `whatchanged` + `news`)\n- \"Should I rebalance?\" → `investorclaw.portfolio_rebalance` followed\n  by `investorclaw.portfolio_optimize` for a target allocation\n\n**Continuity questions**\n\n- \"What did we talk about last time?\" → `mnemos.search_memories` with\n  the recent date range, then summarize\n- \"Remember that I want to keep BABA no matter what.\" →\n  `mnemos.create_memory` with category=preferences\n\n**Composite workflows**\n\n- A portfolio review naturally chains:\n  `mnemos.search_memories` (prior context) →\n  `investorclaw.portfolio_holdings` (current state) →\n  `investorclaw.portfolio_performance` (returns since last review) →\n  `investorclaw.portfolio_news` (drivers) →\n  `mnemos.create_memory` (record salient new observations)\n\nzeroclaw will sequence these on its own when the user asks for a full\nreview. You don't have to script the chain.\n\n## Recommended narration config\n\nInvestorClaw narration is a 3-stage pipeline: the signed envelope →\nStage-2 **consultant** (compresses to a fact-faithful summary) →\nStage-3 **narrator** (enriches it into the user answer). Per the\nper-provider hallucination battery (`harness/cobol/PROVIDER_HALLUCINATION_REPORT.md`):\n\n- **Consultant — `deepseek-v4-flash`** (direct DeepSeek API). Matches the\n  former `gemma-4-31B` consultant on grounding at a fraction of the cost\n  ($0.14 / $0.28 per 1M tokens, $0.0028 cached) and lifts narration\n  coverage to ~30/30. Set `INVESTORCLAW_CONSULTATION_*` — endpoint\n  `https://api.deepseek.com/v1`, model `deepseek-v4-flash`.\n- **Narrator — `gemini`** (e.g. `gemini-2.5-flash`). Cleanest narrator in\n  the battery (lowest hallucination) with the best coverage. Set\n  `INVESTORCLAW_NARRATIVE_*` — endpoint\n  `https://generativelanguage.googleapis.com/v1beta/openai`.\n- **Legacy / offline alternative** — `gemma-4-31B-it` (Together, or local\n  Ollama `gemma4:e4b`, no key) still works as both consultant and narrator,\n  but with lower coverage and a higher timeout rate than the\n  deepseek-flash + gemini combo.\n\nThe HMAC-signed envelope is the real anti-fabrication guardrail: a narrator\nthat times out or is API-incompatible falls back to a grounded heuristic\nthat restates only signed data, so no provider can fabricate past the\nenvelope.\n\n## Pricing data sources & yfinance fallback\n\nPricing resolves through a provider chain: **Massive → Alpha Vantage →\nFinnhub → Yahoo Finance (yfinance)**. With a `MASSIVE_API_KEY`, Massive\nserves fast realtime/historical data. **Without any paid key, pricing\nfalls through to free Yahoo Finance (`yfinance`, no API key required)** —\nfully usable for typical portfolios.\n\n> ⚠️ **Disclaimer — large portfolios on yfinance.** Yahoo Finance is\n> unofficial and slow. **Large portfolios (many holdings) may hit request\n> timeouts (~30s)** when relying on the yfinance fallback. For large or\n> realtime-sensitive portfolios, configure a `MASSIVE_API_KEY`.\n\n\n## Important behaviors\n\n- **The investorclaw tools are deterministic.** If a portfolio CSV\n  format isn't recognized, you'll get a structured error listing\n  detected columns and supported formats. Surface the error verbatim;\n  don't ask the LLM to guess column mappings. Direct the user to the\n  dashboard wizard at `http://localhost:18092/portfolios/map`.\n\n- **Trust the structured output, decorate the narrative.** Every\n  `investorclaw.*` tool returns an `ic_result` envelope (the data) plus\n  a narrative text body. The data is canonical; the narrative is\n  decoration the agent can rewrite for tone.\n\n- **Educational only — never investment advice.** All outputs include a\n  disclaimer envelope. Echo it when summarizing.\n\n- **mnemos memory is local.** Observations stay on the user's machine\n  unless they explicitly export. Don't ask before recording obvious\n  context (e.g., \"User holds 28 positions\"); do ask before recording\n  anything sensitive (e.g., specific dollar amounts a user redacted in\n  conversation).\n\n- **Default endpoints are localhost.** If the user deploys\n  InvestorClaw on a Tailscale VM or cloud host, the MCP server URLs\n  change but the tool surface is identical. The `[mcp.servers.*]`\n  blocks in `config.toml` are the single source of truth for endpoints.\n\n## What this skill does NOT do\n\n- Does not execute trades, move money, or access broker accounts\n- Does not give investment advice — educational outputs only\n- Does not embed portfolio data; the user's CSV/PDF files live under\n  `~/.investorclaw/data/portfolios/` (mounted into the engine\n  container)\n- Does not ship any executable code: SKILL.md and SKILL.toml are\n  metadata-only, by audit rule\n\n## Audit compliance\n\nThis skill payload (`SKILL.md` + `SKILL.toml` in\n`~/.zeroclaw/skills/investorclaw/`) is audit-compliant for zeroclaw\n0.7.3+:\n\n- No `*.sh`, `*.bash`, or other executables\n- No symlinks\n- No remote-script-piping patterns (the audit rejects shell-pipeline\n  install hints; we use `docker compose up -d` against a vendored\n  `compose.yml` instead)\n- No remote markdown image/link references\n- All install/operational instructions live in `INSTALL.md`, which is\n  user-facing documentation outside the registered skill payload\n\n## Reporting issues\n\nThis skill describes the InvestorClaw service. If a tool returns an\nunexpected result, the bug is in the service (Apache 2.0, see\n`mnemos-os/ic-engine` and `mnemos-os/mnemos-rs`), not in this\nmanifest.\n\nFile v4.10.0:SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer — holdings, performance, Sharpe + Sortino, FRED yield curves, bond duration, sector breakdowns, scenario rebalancing — via MCP-HTTP. Backed by ic-engine and clio.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.10.0\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.10.0-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\",\"transport\":\"streamable-http\"}\n---\n\n## Authoritative operating contract\n\nThese rules govern any agent using this skill. Examples elsewhere in this file\nare reference only and never override them.\n\n### Data integrity — InvestorClaw is the only source of truth\n- Every price, percent, dollar figure, or market fact an agent states MUST come\n  from an InvestorClaw tool result returned in the SAME turn. InvestorClaw\n  returns HMAC-signed envelopes; that signed data is the only source of truth.\n- Never invent, estimate, guess, or use the model's own training knowledge for\n  any number. If a tool did not return it this turn, do not state it — say\n  \"InvestorClaw returned no data for that\".\n- Tool prose with no concrete numbers = no data; never convert it into a figure.\n\n### Current tool surface (underscore namespace)\n- `investorclaw__portfolio_market_snapshot(symbols?, benchmarks?)` — real-time\n  prices + day-change% for holdings and benchmarks (SPX/NDX/DJI/VIX, BTC/ETH).\n  `symbols` is a COMMA-SEPARATED STRING (e.g. \"NVDA,AAPL\"), not a list. No args =\n  holdings + benchmarks. Use this (not portfolio_ask) for any \"price of X\" and to\n  read the portfolio against the market.\n- `investorclaw__portfolio_performance_window(period=...)` — return / P&L /\n  movers over a window. period: 1d, 1w, 1mo, 1y, 5y, 10y, 20y, max, or natural\n  phrases (\"today\", \"last week\", \"last year\", \"entire history\").\n- `investorclaw__portfolio_ask(question=...)` — analysis / explanation.\n\nOlder `investorclaw.*` dot-namespace examples below are stale; the underscore\nforms above are the current tool names.\n\n## Autonomous / always-on monitoring agents\n\nFor unattended agents (scheduled monitors and alerters — e.g. a MarketWatch\nagent), in addition to the contract above:\n- Drive each run from a tool call first; never answer a market question from\n  memory. A scheduled \"poll\" means call `portfolio_market_snapshot`.\n- Threshold scan: call `portfolio_market_snapshot`, then emit ONE terse line\n  only when a holding or benchmark breaches the configured move (e.g. ±3% a\n  holding, ±10% VIX); otherwise emit a single `NO_ALERT` token and stop.\n- If the required tool errors or returns no data, emit a fixed marker such as\n  `OPS_FAIL market_snapshot unavailable` and stop — never fabricate a reassuring\n  number to fill the gap.\n- No clarifying questions in unattended mode; map intent and act.\n- Periodic / EOD reports: pull `portfolio_performance_window` for the window,\n  then `portfolio_market_snapshot` for index closes; report numbers verbatim.\n- Always read holdings in the context of the benchmarks in the same snapshot.\n- Delivery is push, terse, numbers-first. Educational, not personalized advice.\n\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n-->\n\n# InvestorClaw — portfolio analysis skill (v4.5.0)\n\nA deterministic-first portfolio analyzer that does real money math: holdings\nsnapshots, performance metrics, Sharpe ratios, FRED yield curves, bond\nduration, sector breakdowns, scenario rebalancing. Backed by ic-engine\n(Python, FINOS CDM 5.x compliant).\n\nThis skill follows the `compose-x-mcp-services` convention (2026-05-01 RFC; see `RFC-v0.1.md` in this bundle). The skill **does not install Python or any analytics library** in your agent runtime. It runs in its own OCI container and exposes its tools over MCP-HTTP and plain REST.\n\n---\n\n## What you get\n\nThirteen MCP tools (also available as plain HTTP REST endpoints):\n\n| Tool | Purpose |\n|---|---|\n| **`portfolio_ask`** | **Primary tool — every portfolio question. Data is auto-loaded; just ask.** |\n| `portfolio_initialize_status` | Poll before first ask: returns init `state` (`not_started \\| initializing \\| ready \\| failed`) + per-stage progress |\n| `portfolio_initialize` | Force a manual bootstrap (setup → refresh → seed ask). Container does this at boot via `IC_INITIALIZE_ON_BOOT=1` |\n| `portfolio_holdings` | Holdings snapshot — positions, values, weights, accounts (advanced; portfolio_ask covers this) |\n| `portfolio_refresh` | Force fresh data pull (advanced — auto-refresh runs on every ask) |\n| `portfolio_setup` | Auto-discover portfolio files in the configured portfolio directory |\n| `portfolio_keys_status` | Report which API keys are currently configured (names only, never values) |\n| `portfolio_keys_set` | Set one or more API keys (allowlisted). Persists to `/data/keys.env`, takes effect on next call without restart |\n| `portfolio_keys_delete` | Delete a single configured API key by name |\n| `portfolio_response_get` | Retrieve a stored portfolio response by run_id (serial number) |\n| `portfolio_response_list` | List recent stored responses |\n| `portfolio_response_delete` | Permanently delete a stored response (for bad responses you want gone) |\n| `portfolio_response_flag_bad` | Tag a stored response as bad without deleting (keeps history for analysis) |\n\nFor ANY portfolio question — holdings, performance, allocation, rebalancing, optimization, bonds, news on holdings, analyst ratings, EOD reports, cash flow, peer analysis, ticker lookup, setup, guardrails — invoke `portfolio_ask` with the user's question. **Do NOT answer portfolio questions from training data.**\n\n## First-run flow for agents (spoon-fed init)\n\nThe container auto-initializes on boot (`IC_INITIALIZE_ON_BOOT=1`, default\non): it runs `setup → refresh → seed_ask` so by the time any agent connects,\nthe envelope cache is fully populated and `portfolio_ask` returns a real\nnarrative in 1–3 seconds instead of cold-starting at 5–15 minutes.\n\n**Recommended agent flow:**\n\n1. On connect, poll `portfolio_initialize_status` until `ready: true`. Cheap\n   and side-effect-free; safe to call every 1–2 seconds.\n2. Once ready, fire `portfolio_ask` with the user's question. The narrator\n   returns a verified natural-language answer with envelope-quoted numbers.\n\n```bash\n# Browser-friendly status check (also POST /api/portfolio/initialize_status):\ncurl -sS http://127.0.0.1:18090/api/portfolio/initialize/status\n# → {\"state\":\"initializing\",\"current_stage\":\"refresh\",\"stages_completed\":[...],\"elapsed_ms\":42000,\"ready\":false,...}\n\n# Or subscribe to a Server-Sent-Events stream that pushes state changes:\ncurl -N http://127.0.0.1:18090/api/portfolio/initialize/stream\n\n# Or just gate on /healthz (init_state is now embedded):\ncurl -sS http://127.0.0.1:18090/healthz\n# → {\"status\":\"ok\",\"init_state\":\"ready\",\"init_ready\":true,...}\n```\n\nNeed to force a manual re-initialize (e.g. after uploading a new portfolio\nfile)? Call `portfolio_initialize` — it returns when the cache is warm again.\n\n---\n\n## Installation\n\n### OpenClaw / ZeroClaw / Hermes (ClawHub)\n\n```bash\nclawhub install investorclaw\n```\n\n### Claude Code / Claude Desktop\n\n```\n/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw\n```\n\nClaude Code and Claude Desktop install directly from this repo and use\nthe same container-first skill bundle as every other runtime. See\n`docs/GETTING_STARTED.md` for the canonical install flow.\n\n### Manual (Docker Compose, any agent)\n\nThe skill is a Docker Compose stack. With Docker or Podman installed:\n\n```bash\nmkdir -p portfolios     # IMPORTANT: pre-create so docker doesn't auto-create as root\ndocker compose up -d    # uses compose.yml shipped in this skill\n```\n\n**Agent install convention.** When a skills-installer\n(`openclaw skills install investorclaw`, `clawhub install\ninvestorclaw`, etc.) places this bundle, the agent **may** proceed\nto `mkdir -p portfolios && docker compose up -d` because the user's\ninstall command is itself an opt-in to the install completing. But\nthe agent **must** first surface the side effects to the user\nexplicitly:\n\n1. `docker pull` of `~600 MB` (the engine image) on first run\n2. `docker compose up -d` binds two TCP listeners to localhost:\n   `:18090` (MCP + REST) and `:18092` (dashboard)\n3. The container auto-initializes on boot\n   (`IC_INITIALIZE_ON_BOOT=1`) and will fetch market data from\n   the configured providers (yfinance free-tier by default; other\n   providers only if API keys have been added)\n4. Persistent state lands in the `ic-engine-data` Docker volume\n   (deleted only by `docker compose down -v`)\n\nA single one-line surfacing covering all four is sufficient. Example:\n\n> Starting the container will pull a ~600 MB image, bind localhost\n> ports `:18090` and `:18092`, auto-init against yfinance, and\n> persist state in a Docker volume. Proceeding…\n\nThe user retains the ability to interrupt (Ctrl-C, \"no don't\",\netc.). Don't ask a yes/no question by default — that's friction the\nuser has already cleared by typing the install command. **Do** ask\nwhen one of these conditions holds:\n\n- The host appears to be a CI runner, shared machine, or production\n  server where the user might want to review `compose.yml` first.\n- An existing `ic-engine` container is already running on the host\n  with a different image tag — confirm before disrupting.\n- The user explicitly added `--dry-run` or `--no-start` to the install\n  command (if the skills installer surfaces those flags).\n- The agent's runtime policy requires a confirmation prompt before\n  any container start (some enterprise / regulated deployments).\n\nThe first command (`mkdir -p portfolios`) is load-bearing. If skipped,\ndocker creates `./portfolios/` as `root:root` when starting the\nbind-mount, the engine runs as `uid=1000(ic)` inside the container,\nand init fails with\n`PermissionError: '/data/portfolios/setup_results.json'` and the\ncontainer goes into `init_state=failed`. Pre-creating the directory\nas the host user sidesteps the docker bind-mount UID inheritance\nquirk.\n\nThe compose pulls `ghcr.io/argonautsystems/ic-engine:4.10.0-cpu` (publicly hosted, no auth) and runs it on `localhost:18090` (MCP + REST) and `localhost:18092` (dashboard).\n\n### If Docker isn't installed\n\nInstall Docker Desktop or Docker Engine for your platform — **the user\nshould run the install themselves** rather than have an agent execute\nthe command. Pointers (verify with each OS's current docs at\n<https://docs.docker.com/engine/install/> before running):\n\n| OS | Suggested path |\n|---|---|\n| **macOS** | Docker Desktop: <https://docs.docker.com/desktop/install/mac-install/> (Homebrew users: `brew install --cask docker`) |\n| **Debian/Ubuntu** | Follow the official guide: <https://docs.docker.com/engine/install/debian/> or <https://docs.docker.com/engine/install/ubuntu/> |\n| **Fedora/RHEL** | <https://docs.docker.com/engine/install/fedora/> or <https://docs.docker.com/engine/install/rhel/> |\n| **Windows** | Docker Desktop with WSL2 backend: <https://docs.docker.com/desktop/install/windows-install/> |\n| **Podman alternative** | `podman compose up -d` is a drop-in replacement once Podman is installed (most distros ship it) |\n\nAfter install, verify with `docker --version` then run the compose-up\ncommand above.\n\n**For agent operators:** prefer surfacing these install URLs to the\nend user rather than running package-manager install commands directly\nthrough your shell tool. Docker installation typically requires sudo\nand adds the user to the `docker` group — operations that benefit from\nexplicit user consent.\n\n### Wait for ready\n\n```bash\nuntil curl -sf http://localhost:18090/healthz > /dev/null 2>&1; do sleep 1; done\necho \"ic-engine ready\"\n```\n\nThe first cold-start takes 5-10 seconds (image extract + Python import). Subsequent restarts are <2s.\n\n---\n\n## First-run experience — what to expect\n\nAfter `docker compose up -d` the container goes through an auto-init\nsequence (`IC_INITIALIZE_ON_BOOT=1`) that warms the envelope cache before\nyour agent talks to it. Expect this timeline on a fresh install:\n\n| Phase | Time | What's happening | What you'll see |\n|---|---|---|---|\n| Image extract | 5–30 s | First-time pull of `ic-engine:4.10.0-cpu` (~600 MB) | docker compose progress bars |\n| Bridge boot | 2–3 s | FastMCP server binds `:18090`, dashboard binds `:18092` | `/healthz` returns 200, `init_state: not_started` |\n| `portfolio_setup` | 1–60 s | Auto-discover portfolio files in `./portfolios/` | `init_state: initializing`, `current_stage: setup` |\n| `portfolio_refresh` | 30–120 s | Pull quotes / analyst / news / FRED yields for each symbol | `init_state: initializing`, `current_stage: refresh` |\n| `seed_ask` | 5–60 s | Run a primer ask so the cache is warm | `init_state: initializing`, `current_stage: seed_ask` |\n| **Ready** | — | All sections cached, `portfolio_ask` returns in 1–3 s | `init_state: ready`, `init_ready: true` |\n\n**Total cold-start budget**: ~60-200 s for a 100-position portfolio,\n~5-15 minutes for a 200+ position portfolio without paid quote keys.\nWatch progress via:\n\n```bash\ncurl -sS http://127.0.0.1:18090/api/portfolio/initialize/status | jq\n# or stream:\ncurl -N http://127.0.0.1:18090/api/portfolio/initialize/stream\n```\n\n### What InvestorClaw asks of you\n\nThe container does **not** prompt interactively. It surfaces what it\nneeds through structured responses:\n\n1. **A portfolio file.** If `./portfolios/` is empty, every `portfolio_ask`\n   call returns: *\"No portfolio file found … please add CSV/Excel/PDF\n   files to your portfolios directory.\"* Drop a broker export from\n   Schwab / Fidelity / Vanguard / UBS / ETrade / Robinhood (CSV/XLS/PDF/screenshot)\n   into the bind-mounted `./portfolios/` folder, then call\n   `portfolio_setup` to ingest it.\n\n2. **An LLM provider key for narrative synthesis.** Without one, the\n   engine still runs the deterministic pipeline (numbers are correct)\n   but the narrator returns a stub catalog blurb instead of a real\n   prose answer. The container ships pre-configured to use Together AI\n   (`google/gemma-4-31B-it`), so all you need is a `TOGETHER_API_KEY`.\n   Set it with:\n\n   ```bash\n   curl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_set \\\n     -H 'Content-Type: application/json' \\\n     -d '{\"keys\": {\"TOGETHER_API_KEY\": \"tgp_v1_...\"}}'\n   ```\n\n   Or drop into the dashboard at http://localhost:18092/ and paste it\n   into the Settings tab.\n\n3. **Optional: data-provider keys** for richer / faster results\n   on larger portfolios (see *Optional configuration → Which keys to\n   obtain (by portfolio size)* below). The engine works key-less in\n   degraded mode (yfinance-only, rate-limited).\n\n### What InvestorClaw recommends — by portfolio size\n\n| Size | Required | Recommended | Why |\n|---|---|---|---|\n| **≤ 50 symbols** | `TOGETHER_API_KEY` (narrative) | — | yfinance handles quotes/history at this scale; one key covers narrative |\n| **50–200 symbols** | `TOGETHER_API_KEY` | `FINNHUB_KEY` (free 60/min) + `NEWSAPI_KEY` (free 100/day) | Real-time quotes + analyst + per-symbol news without yfinance throttle |\n| **200+ symbols** | `TOGETHER_API_KEY` + `MASSIVE_API_KEY` (Massive, paid) | `FINNHUB_KEY` + `MARKETAUX_API_KEY` (free 100/day) + `FRED_API_KEY` (free, registration) + `ALPHA_VANTAGE_KEY` (free 25/day) | Yahoo's anonymous query1 endpoint rate-limits globally on 200+ symbols under barrage; Massive is required, the rest fill analyst + news + yields |\n\nWhy `TOGETHER_API_KEY` is the only hard requirement for narrative:\n\n- Cheapest serverless tier on Together AI (~$0.0008 / 1 K tokens)\n- Default model `google/gemma-4-31B-it` has good quality for portfolio\n  narrative + ~100 tok/s throughput\n- Single key replaces the older multi-tier model setup that v2.x used\n\nSign-up links (all have free tiers):\n\n| Provider | URL | Free-tier limit |\n|---|---|---|\n| Together AI | https://api.together.ai/settings/api-keys | $1 free credits |\n| Finnhub | https://finnhub.io/register | 60 calls/min |\n| Massive (Massive) | https://massive.com/dashboard/api-keys | paid only |\n| MarketAux | https://www.marketaux.com/account/dashboard | 100 calls/day |\n| NewsAPI | https://newsapi.org/register | 100 calls/day |\n| FRED | https://fred.stlouisfed.org/docs/api/api_key.html | unlimited (registration only) |\n| Alpha Vantage | https://www.alphavantage.co/support/#api-key | 25 calls/day |\n\nThe `TOGETHER_API_KEY` is the only one that's genuinely required.\nEverything else degrades gracefully.\n\n### First call — what your agent will see\n\nOnce `init_state: ready` and a portfolio is loaded, the very first\n`portfolio_ask` call returns a response shaped like:\n\n```json\n{\n  \"exit_code\": 0,\n  \"narrative\": \"I have holdings summary data in the envelope.\\n- bond_pct: 26.76\\n- bond_value: 705646.57\\n- cash_pct: 1.69\\n- equity_pct: 71.55\\n- equity_value: 1886470.25\\nTop holding symbols: MSFT, NVDA, SCHB, GOOG, AAPL, ...\",\n  \"ic_result\": {\n    \"hmac\": \"75ca79c...\",\n    \"engine_version\": \"2.5.2\",\n    \"command\": \"ask\",\n    \"run_id\": \"299d36b0-...\"\n  }\n}\n```\n\nThe `narrative` field is the agent-facing answer. The `ic_result`\ncontains the HMAC signature that proves the response came from the\ndeterministic engine (not LLM-fabricated).\n\nIf you see *\"is a general finance concept. ic-engine is portfolio-specific\"*\nin the narrative for a question that obviously is about your portfolio,\nyou're on a pre-v4.1.25 image — pull the latest:\n\n```bash\ndocker compose pull && docker compose up -d\n```\n\n---\n\n## How to call the tools\n\n### Option A: native MCP client (preferred)\n\nIf your runtime has a native MCP client, register the server:\n\n```\nURL:       http://127.0.0.1:18090/mcp\nTransport: streamable-http\nAuth:      none (localhost only)\n```\n\nPer-runtime CLI:\n\n| Runtime | Command |\n|---|---|\n| zeroclaw | Add `[[mcp.servers]]` with `name = \"ic-engine\"`, `url = \"http://127.0.0.1:18090/mcp\"`, `transport = \"http\"` to `~/.zeroclaw/config.toml` |\n| openclaw | `openclaw mcp set ic-engine '{\"url\":\"http://127.0.0.1:18090/mcp\",\"transport\":\"streamable-http\"}'` |\n| hermes | `hermes mcp add ic-engine --url http://127.0.0.1:18090/mcp` |\n| claude code | Add to `~/.claude/mcp_servers.json` per Claude Code docs |\n\nThen call tools by name (`portfolio_ask`, `portfolio_holdings`, etc.) via your runtime's tool-use API.\n\n### Option B: plain HTTP REST (works when MCP integration is flaky)\n\nEquivalent endpoints exist at `/api/portfolio/*`. Use your runtime's shell or HTTP tool:\n\n```bash\n# Ask any portfolio question\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/ask \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"question\": \"What is in my portfolio?\"}' \\\n  --max-time 120\n\n# Other endpoints (no body needed)\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/holdings -H 'Content-Type: application/json' -d '{}'\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/refresh  -H 'Content-Type: application/json' -d '{}'\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/setup    -H 'Content-Type: application/json' -d '{}'\n\n# Self-describing tool catalog\ncurl -sS http://127.0.0.1:18090/api/portfolio/tools\n```\n\nThe JSON response has a `narrative` field with the human-readable answer — quote that to the user. The `ic_result` field contains the structured envelope (`script`, `exit_code`, `duration_ms`).\n\n---\n\n## What to ask — example queries\n\nOnce installed, ask portfolio questions in natural language. The agent routes\nthrough `portfolio_ask`; ic-engine handles the deterministic computation and\nthe narrator quotes verbatim from the signed envelope.\n\n| Intent | Example phrasing |\n|---|---|\n| **Holdings snapshot** | \"What's in my portfolio?\" • \"Show me my positions\" • \"What do I own?\" |\n| **Performance** | \"How am I doing this year?\" • \"What's my Sharpe ratio?\" • \"Show me my drawdowns\" |\n| **Bonds** | \"Show me my bond exposure and yield-to-maturity\" • \"What's my bond ladder look like?\" |\n| **Allocation / risk** | \"What's my sector exposure?\" • \"How concentrated is my portfolio?\" • \"What's my risk profile?\" |\n| **Optimization / rebalancing** | \"Help me rebalance to a 60/40 target\" • \"Show me an efficient frontier\" |\n| **Market data** | \"What's the current price of NVDA?\" • \"How is the S&P performing today?\" |\n| **Fixed-income concepts** | \"What does yield-to-maturity mean?\" • \"Explain duration\" |\n| **News** | \"Today's news on my holdings\" • \"Crypto news today\" |\n| **Reports** | \"Generate today's EOD report\" • \"Prepare a full analysis for my advisor meeting\" |\n| **Fresh data** | \"Prices moved — refresh before answering\" → triggers `portfolio_refresh` |\n\nThe first call after a cold cache may take 30–60 seconds while the\ndeterministic pipeline builds the signed envelope. Subsequent calls reuse\nthe cache (TTL: 30s for news, 60s for other sections); ask for a refresh\nexplicitly if data feels stale.\n\n---\n\n## Agent routing rules\n\nThese rules apply when an agent has the InvestorClaw skill installed:\n\n**Use InvestorClaw — do NOT answer from training data, web search, or browsing — for:**\n- Any portfolio / holdings / positions question\n- Performance, returns, Sharpe/Sortino, drawdown\n- Bonds, yield-to-maturity, duration, ladders\n- Sector / asset / account allocation\n- Optimization, rebalancing, target allocation, scenarios\n- Cash flow, dividend / coupon calendars\n- Analyst ratings, price targets\n- Today's news on holdings or market-wide topics\n- Live ticker prices and quotes\n- EOD reports, peer comparison, what-changed analysis\n\n**Deterministic-first rules:**\n- Never calculate portfolio metrics in the agent — call the tool.\n- Never fabricate market, ticker, bond, portfolio, optimization, or news data.\n- Preserve quoted source passages, numbers, dates, timestamps, and freshness\n  labels exactly.\n- If the signed envelope lacks a requested fact, say InvestorClaw did not\n  provide it and quote the engine's limitation verbatim.\n- Use `portfolio_refresh` only when the user asks for fresh data or when\n  data appears stale.\n\n**Attachment handling:**\n- When the user attaches a CSV / XLS / XLSX / PDF / screenshot in the same\n  turn as a portfolio question, stage the file to the bind-mounted\n  `portfolios/` directory, call `portfolio_setup`, then ask the original\n  question.\n- Do not ask the user to move files manually; the agent owns staging.\n- Report low-confidence extraction or setup gaps exactly as InvestorClaw\n  returns them.\n\n**Educational guardrails:**\n- All output is educational, not investment advice.\n- Never present \"buy/sell\" recommendations as advice.\n- Never assess suitability for the user's situation.\n- Preserve the engine's disclaimer language verbatim.\n\n---\n\n## Required response format (when answering as an agent)\n\nEnd every portfolio reply with:\n\n```\nVerification: ic-engine ask completed (exit_code: 0)\n```\n\n(Substitute the actual `exit_code` from the response.) The harness depends on this exact line.\n\nFor finance-concept questions (\"what is YTM?\") or market-wide questions (\"how is the S&P performing?\"), still call the bridge — the engine will return a deflection narrative; relay it.\n\n---\n\n## Configure portfolios\n\nDrop your broker exports (CSV, XLS, PDF) into the bind-mounted directory:\n\n```bash\n# default mount: ./portfolios on the host -> /data/portfolios in the container\nmkdir -p portfolios\ncp ~/Downloads/UBS_Holdings_2026-05-02.xls portfolios/\n\n# Then ask the agent or curl the setup endpoint\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/setup -H 'Content-Type: application/json' -d '{}'\n```\n\nSupported formats: UBS, Schwab, Fidelity, Vanguard, ETrade, Robinhood (CSV/XLS); generic CSV with `symbol`/`quantity`/`value` columns; PDF statements (auto-extracted).\n\n### Broker export instructions\n\nMost major US brokers expose a CSV download of holdings. CSV is the highest-\ncompatibility format; XLS / XLSX / PDF / screenshot also work.\n\n| Broker | Path |\n|---|---|\n| Schwab | Accounts → Positions → Export CSV |\n| Fidelity | NetBenefits → Investments → Download CSV |\n| Vanguard | My Accounts → Download Holdings |\n| UBS | Wealth Management → Holdings → Export |\n| ETrade | Portfolio → Holdings → Download |\n| Robinhood | Account → Statements → CSV |\n\nWhen the user attaches a broker file directly to an agent chat, the agent\nstages it to the bind-mounted `portfolios/` directory, then calls\n`portfolio_setup` followed by `portfolio_ask`. Account numbers and SSNs are\nscrubbed at ingest before any data leaves the container.\n\n---\n\n## Optional configuration\n\nThe container reads optional env vars from `/data/keys.env` (host-mounted). All optional — the deterministic-engine works without LLM/news keys, just in degraded mode (no narrative synthesis, no live news).\n\n### Which keys to obtain (by portfolio size)\n\nThe bridge has built-in fallback across providers; the only **hard\nrequirement** is an LLM key for narrative synthesis. Below that, your\nchoice depends on portfolio size.\n\n**Small (≤50 symbols)** — yfinance-only is fine:\n- `TOGETHER_API_KEY` (or any LLM): required for narrative\n- That's it. Yahoo Finance handles quotes/history at this scale.\n\n**Medium (50–200 symbols)** — add Finnhub:\n- `TOGETHER_API_KEY`: LLM narrative\n- `FINNHUB_KEY`: real-time quotes + analyst ratings (60/min, free)\n- `NEWSAPI_KEY` *(optional)*: per-symbol news (100/day free)\n\n**Large (200+ symbols)** — Massive (Massive) is required:\n- `TOGETHER_API_KEY`: LLM narrative\n- `MASSIVE_API_KEY` (Massive): paid, un-rate-limited quotes + history\n- `FINNHUB_KEY`: analyst ratings + general/forex/crypto/merger news\n- `MARKETAUX_API_KEY` *(optional)*: broader news with category filters\n- `FRED_API_KEY` *(optional)*: Treasury yield curve (Treasury.gov fallback runs without)\n- `ALPHA_VANTAGE_KEY` *(optional)*: supplemental EOD prices (25/day free)\n\nWhy: Yahoo's anonymous query1 endpoint rate-limits globally (HTTP 429) on\n200+ symbol portfolios under barrage load. Massive (`massive`) handles the\nbulk of quotes/history without throttling; Finnhub fills analyst + news;\nthe no-key Frankfurter (FX) and Treasury Fiscal Data (yields) providers\ncover the remainder.\n\n### Full key reference\n\n| Key | Purpose | Cost note |\n|---|---|---|\n| `TOGETHER_API_KEY` | LLM narrative synthesis (Together google/gemma-4-31B-it) | serverless, fleet default |\n| `MASSIVE_API_KEY` | Massive quotes + history (200+ symbol portfolios) | paid, un-rate-limited |\n| `MASSIVE_API_KEY` (futures) | CME futures via Massive `/futures/vX` — snapshot + history + correct contract-multiplier notional (ES/NQ/CL/GC/ZB…). Only provider routed for futures. | paid |\n| `FINNHUB_KEY` | Real-time quotes + analyst ratings + category news | 60/min free |\n| `MARKETAUX_API_KEY` | Financial news with broader filters than NewsAPI | 100/day free |\n| `NEWSAPI_KEY` | Per-symbol news (US sources only) | 100/day free |\n| `ALPHA_VANTAGE_KEY` | Supplemental EOD prices | 25/day free |\n| `FRED_API_KEY` | FRED yield curve | free, registration required |\n| `OPENAI_API_KEY` | Alternative LLM (GPT-4o, GPT-5) | paid |\n\n### No-key providers (always available)\n\n| Provider | Coverage |\n|---|---|\n| **yfinance** | Quotes, history, news, analyst (rate-limited; safety-net only on 200+ portfolios) |\n| **Frankfurter** | FX spot rates (EUR/USD, USD/JPY, etc.) — ECB-sourced |\n| **Treasury Fiscal Data** | US Treasury yield curve fallback when FRED_API_KEY missing |\n\n### Configure keys via REST/MCP (preferred — no host shell needed)\n\nThe agent can set keys directly via the running container, no `/data/keys.env`\nedit required. Persists atomically (mode 0600), takes effect on the next\n`portfolio_ask` without a restart.\n\n```bash\n# What's configured?\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_status \\\n  -H 'Content-Type: application/json' -d '{}'\n# → {\"configured\":[\"FINNHUB_KEY\",\"NEWSAPI_KEY\"], \"settable\":[...], \"missing\":[...]}\n\n# Set one or more keys\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_set \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"keys\": {\"TOGETHER_API_KEY\": \"tgp_v1_...\", \"FRED_API_KEY\": \"...\"}}'\n# → {\"configured\":[\"FRED_API_KEY\",\"TOGETHER_API_KEY\"], \"rejected\":[], \"deleted\":[]}\n\n# Remove a key\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/keys_delete \\\n  -H 'Content-Type: application/json' -d '{\"name\": \"OPENAI_API_KEY\"}'\n```\n\nThe same operations are available as MCP tools: `portfolio_keys_status`,\n`portfolio_keys_set`, `portfolio_keys_delete`. Only the standard ic-engine\nkey names are accepted; arbitrary names are rejected with a structured\n`{\"rejected\": [...], \"settable\": [...]}` response.\n\n### Configure keys via host file (alternative)\n\nIf you prefer to manage keys outside the container, drop them into\n`portfolios/keys.env` on the host (the bind-mounted location), one\n`KEY=VALUE` per line:\n\n```env\nTOGETHER_API_KEY=tgp_v1_...\nFINNHUB_KEY=...\nNEWSAPI_KEY=...\n```\n\nThe container reads from `/data/keys.env` at boot.\n\n---\n\n## Model recommendations\n\nInvestorClaw uses two LLM roles when answering: **narrative** (synthesizes\nthe signed envelope into prose) and **validator** (checks the narrative\nagainst the envelope for fabrication and number-preservation). The\nrecommended model mix depends on your runtime.\n\n### Claude Code / Claude Desktop\n\nThe agent's own LLM does both roles — no external API key required.\n\n- **Narrative**: Haiku 4.5 — fast, cheap, ~10× lower output cost than\n  Sonnet. Synthesis with a clean envelope is mostly transcription, so the\n  cheap model is sufficient.\n- **Validator**: Sonnet 4.6 (default) or Opus 4.7 (escalation) — gates the\n  Haiku output for fabrication, mis-quoted numbers, and training-leak\n  drift. Validator output is short (~1 K tokens) so the smart-model bill\n  stays low.\n\nThis split is cost-shaped: cheap model on the long output, smart model on\nthe short safety check. Total session cost on a 100-position portfolio\ntypically lands well under $0.01.\n\n### openclaw / zeroclaw / hermes\n\n**Anthropic on the claws stack — three paths, two of them paid:**\nsince 2026-04-04 your Anthropic OAuth subscription no longer covers\nthird-party-tool usage. To use Anthropic models on a claws-agent\nruntime you need either (a) Anthropic's discounted \"extra usage\nbundles\" added to your subscription, or (b) a direct Anthropic API\nkey. Routing OAuth-subscription tokens to a claws-agent without one of\nthose is a ToS violation per Anthropic's Apr 3 announcement.\n\nEven with paid credits, Anthropic isn't cost-competitive with Together\nfor InvestorClaw narrative synthesis (~10–50× the per-token cost).\n**On our own fleet infrastructure we don't deploy Anthropic for these\nruntimes**; end-users should weigh ToS, cost, and quality before\nopting into it.\n\nBring a non-Anthropic provider via `TOGETHER_API_KEY` (or equivalent).\nFleet defaults:\n\n- **Default narrative**: Together AI `google/gemma-4-31B-it` — serverless\n  tier, ~100 tok/s, ~$0.0008 / 1 K tokens, ships as the container default.\n- **Higher-quality alternative**: Together AI `MiniMaxAI/MiniMax-M2` —\n  larger context, but **moved off Together's serverless tier in 2026-05**\n  and now requires a paid dedicated endpoint. Use only if you've\n  provisioned that endpoint.\n- **Local-only / offline**: Ollama `gemma4:e4b` on host — zero cloud cost,\n  GPU-bound, no key required.\n\nTo switch the narrative model, set `INVESTORCLAW_NARRATIVE_MODEL` in\n`portfolios/keys.env` (e.g. `INVESTORCLAW_NARRATIVE_MODEL=MiniMaxAI/MiniMax-M2`\nonce you have a dedicated endpoint configured at Together).\nThe container reads it on next call without restart.\n\n---\n\n## Data privacy\n\n**Stays on your machine:**\n- Raw broker exports (CSV / XLS / PDF) in `portfolios/`\n- Account numbers and SSNs (scrubbed at ingest)\n- Full position details (lot history, cost basis)\n- Python computation internals (intermediate calculations)\n\n**Sent to the configured LLM provider for narrative synthesis:**\n- The user's question\n- The HMAC-signed JSON envelope produced by ic-engine\n- Computed metrics needed for presentation\n\n**Never sent anywhere:**\n- Raw PII (account numbers, SSNs, names)\n- Pre-computation intermediate state\n- Other portfolios on the same disk\n\nInvestorClaw never executes trades, never moves money, never accesses\nbrokerage APIs for transactions. Output is educational only.\n\n---\n\n## Verify install + compliance\n\n```bash\n# Health check\ncurl -sS http://127.0.0.1:18090/healthz\n# → {\"status\":\"ok\",\"ic_engine_bin_found\":true,\"portfolio_dir\":\"/data/portfolios\",\"portfolio_dir_exists\":true,\"reports_dir\":\"/data/reports\"}\n\n# Smoke test the tool catalog\ncurl -sS http://127.0.0.1:18090/api/portfolio/tools | python3 -m json.tool\n\n# Smoke test a real question\ncurl -sS -X POST http://127.0.0.1:18090/api/portfolio/ask \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"question\": \"What is in my portfolio?\"}' \\\n  --max-time 120\n```\n\nIf your agent supports compliance testing, vendor `test_mcp_compliance.py`\nfrom the `mnemos-os/mcp-contracts` GitHub repository into your project, then run:\n\n```bash\npython3 test_mcp_compliance.py --url http://127.0.0.1:18090/mcp\n```\n\n---\n\n## Dashboard\n\nThe container exposes a single-page HTML dashboard on port `:18092`:\n\n```bash\nopen http://localhost:18092/        # macOS\nxdg-open http://localhost:18092/    # Linux\nstart http://localhost:18092/       # Windows\n```\n\nTabs cover: Holdings · Performance · Bonds · Analyst · News · Cashflow ·\nOptimize · Synthesis · What-changed · Tax · Scenarios · Peer · Reports ·\nSettings · About.\n\nThe dashboard reads the same signed envelope ic-engine produces for\n`portfolio_ask`, so metrics stay in sync. Use it for visual review of\nholdings / performance, or as a fallback interface when MCP integration\nis flaky.\n\n---\n\n## Troubleshooting\n\n### Container won't start\n\n```bash\ndocker compose logs ic-engine | tail -50\ndocker ps | grep ic-engine        # confirm running + healthy\ncurl -sS http://127.0.0.1:18090/healthz\n```\n\nIf `healthz` returns `{\"init_state\":\"failed\", ...}`, check the `init_error`\nfield for the engine's exact failure message.\n\n### \"No portfolio found\" when asking\n\n- Drop a CSV / XLS / PDF into `portfolios/` (the host bind mount).\n- Then call setup:\n  `curl -X POST http://127.0.0.1:18090/api/portfolio/setup -d '{}'`\n- Then ask again:\n  `curl -X POST http://127.0.0.1:18090/api/portfolio/ask -d '{\"question\":\"what's in my portfolio?\"}'`\n\nThe agent can stage attached files to `portfolios/` directly when the user\nsends them in chat.\n\n### \"API key errors\" / degraded data\n\nKeys are optional. The deterministic-engine works key-less in degraded\nmode (no narrative synthesis, no live news, yfinance-only quotes). To\ncheck what's configured:\n\n```bash\ncurl -X POST http://127.0.0.1:18090/api/portfolio/keys_status -d '{}'\n```\n\nSet the missing key via the REST endpoint shown in\n[Optional configuration](#optional-configuration).\n\n### \"First call is slow (5–15 minutes)\"\n\nOnly happens on a cold cache for portfolios with 200+ positions. The\ncontainer runs `IC_INITIALIZE_ON_BOOT=1` by default — initialization runs\nat container start, so by the time the agent connects, the cache is warm.\nIf you disabled that env var, expect cold-start latency on first ask.\n\nCheck init progress: `curl http://127.0.0.1:18090/api/portfolio/initialize/status`\n\n### \"Container is healthy but `portfolio_ask` times out\"\n\n- Bridge subprocess timeout is 1800 s on `portfolio_ask` and `portfolio_refresh`.\n- Engine P1 parallel-stage timeout is 600 s.\n- If you hit either, the engine ran out of upstream API budget (yfinance\n  429, Finnhub rate limit, etc.). Switch to Massive (`MASSIVE_API_KEY`)\n  for large portfolios; see \"Which keys to obtain (by portfolio size)\".\n\n### Reset cache + state\n\n```bash\ndocker compose down -v   # removes the data volume — all envelopes lost\ndocker compose up -d     # cold restart with auto-init\n```\n\n---\n\n## Stop / uninstall\n\n```bash\n# Stop (preserves data)\ndocker compose down\n\n# Stop and remove the data volume\ndocker compose down -v\n```\n\n---\n\n## Security model\n\nInvestorClaw is a single-user, localhost-bound, deterministic-first\nanalyzer. Several behaviors that automated scanners flag as \"warning\"\nare intentional design choices for this threat model. Documented here\nexplicitly so reviewers can audit the trade-offs:\n\n| Behavior | Why it's by design |\n|---|---|\n| **MCP + REST endpoints are unauthenticated on `127.0.0.1:18090`** | Localhost binding (`127.0.0.1:` prefix on the port spec, never `0.0.0.0`) is the security boundary. Any process running as the same user already has filesystem access to portfolios; adding token auth on a loopback API doesn't change that threat model. To expose the service to other hosts, put it behind your own auth layer (Tailscale, nginx + mTLS). |\n| **Container auto-initializes on boot** (`IC_INITIALIZE_ON_BOOT=1`) | The cold-cache cost on a 200+ position portfolio is 5–15 minutes; running setup → refresh → seed_ask at boot means agents see `init_state: ready` immediately on connect. Disable with `IC_INITIALIZE_ON_BOOT=0` if you want manual control. The init does not exfiltrate data — it just primes the engine's read-only cache against the providers you've configured. |\n| **API keys persist to `/data/keys.env` (mode 0600)** | Keys need to outlive container restarts. The named volume is `ic-engine-data`; on the host that's a docker volume root-owned but only readable by the container's `uid=1000(ic)`. To rotate or delete a key, use `portfolio_keys_set` / `portfolio_keys_delete` — both REST endpoints accept allowlisted names only, never logging values. |\n| **Portfolio summaries are sent to the configured narrative LLM provider** | This is the value prop: the engine produces a deterministic envelope, the narrator turns it into prose. To keep narratives local, point `INVESTORCLAW_NARRATIVE_ENDPOINT` at a local Ollama / llama-server / vLLM endpoint (set `INVESTORCLAW_NARRATIVE_PROVIDER=ollama`). To run keyless without any narrator, omit `TOGETHER_API_KEY` — the engine returns a stub catalog summary instead. See [`PRIVACY.md`](PRIVACY.md) for the full data-flow matrix. |\n| **Image pulled from `ghcr.io/argonautsystems/ic-engine`** | Pinned to a specific sha256 digest in `compose.yml`, not just the tag — guarantees reproducible builds even if the tag is later mutated. Verify the digest matches what your scanner expects before deploying. Container Apache 2.0 + bridge code MIT-0 in this repo; engine source at `argonautsystems/ic-engine` (pinned by SHA). |\n\nFor vulnerability disclosure see [`SECURITY.md`](SECURITY.md). For the\nprivacy model (what stays local vs what goes to which provider) see\n[`PRIVACY.md`](PRIVACY.md).\n\n## Behavior contract\n\n- `portfolio_ask` invokes the engine's deterministic refresh-aware path; if a section is stale (news TTL=30s, others 60s) it is refreshed before answering. Earlier `--no-refresh` short-circuited routing entirely and produced a generic catalog blurb — that flag is intentionally NOT passed.\n- The container clears yfinance cookies on subprocess timeout, breaking the rate-limit cascade documented in commit `50387b1` of `mnemos-os/mnemos-ic-runtime`.\n- Cross-container reach works via `http://172.17.0.1:18090/mcp` (Docker bridge IP) or via Compose service name `http://ic-engine:8090/mcp` (when both agent + ic-engine are in the same compose).\n\n## Known issues (v4.1.1)\n\n- **Earlier \"v4.0.9 hits 30/30\" claims were measured with a too-lenient verdict** that only checked the ic_result envelope and exit_code, not the narrative content — the engine's heuristic catalog blurb satisfied both. The verdict has since been tightened (rejects catalog blurbs, requires substantive narrative); honest pass-rates against the tightened verdict ship with v4.1.1 release notes.\n- **Cold-start `portfolio_ask` may take 5–15 minutes** on a 200+ position portfolio when the envelope cache is empty (engine runs P0 holdings → P1 parallel performance/bonds/analyst/news → P2 synthesis → P3 optimize+cashflow → P4 peer, each consuming yfinance / FRED / Finnhub bandwidth). Subsequent calls hit the warm cache and return in seconds. Bridge subprocess timeout is 1800s for `portfolio_ask` and `portfolio_refresh`; engine P1 parallel-stage timeout is 600s.\n\n### Fixed in v4.1.1 (was broken in v4.0.x → v4.1.0)\n\n- **Engine pipeline only persisting the analyst section** (`Section did not run` on every other section): root cause was the engine's P1 parallel-stage timeout of 60s — performance/bonds/analyst/news running in parallel against yfinance overflowed it on large portfolios, asyncio.gather raised TimeoutError, the entire P1 result set was lost. Bumped to 600s.\n- **Narrator falling through to a heuristic catalog blurb** for every `portfolio_ask`: chain of five bugs — litellm stripped from the container; narrator wrapped the LLM call in a bare try/except; consultation client misrouted IP-addressed local servers; narrator pulled the short-context CONSULTATION_* model instead of the long-context NARRATIVE_* model; full envelope (200k+ tokens) overflowed even MiniMax-M2.7. All five fixed.\n- **`--no-refresh` short-circuiting routing**: bridge passed `--no-refresh` to every `portfolio_ask` (commit `a3492f6`, v4.0.7), making the engine return the cached catalog blurb regardless of question. Reverted.\n\n---\n\n## License + provenance\n\n- Service code: Apache 2.0 (`mnemos-os/mnemos-ic-runtime`)\n- Distribution-edge artifacts (this `SKILL.md`, `compose.yml`, `install.yaml`, `agent-skills/**`): **MIT-0** (MIT No Attribution — `LICENSE-MIT-0`). Required for ClawHub plugin publishing; the no-attribution clause means downstream skill registries can re-host without preserving copyright notice.\n- Image: `ghcr.io/argonautsystems/ic-engine:4.10.0-cpu` (multi-arch amd64+arm64; also at `:latest`)\n- RFC: see `RFC-v0.1.md` in this bundle (`mnemos-os/mnemos-ic-runtime` GitHub repository)\n- Cross-project contract: `mnemos-os/mcp-contracts` GitHub repository\n\n---\n\n*InvestorClaw is a portfolio analysis service. Educational use only — not investment advice.*\n\nFile v4.10.0:README.md\n\n<p align=\"center\">\n  <picture>\n    <source srcset=\"assets/investorclaw-logo.webp\" type=\"image/webp\">\n    <img src=\"assets/investorclaw-logo.jpg\" alt=\"InvestorClaw\" width=\"192\">\n  </picture>\n</p>\n\n# InvestorClaw\n\n> Deterministic-first portfolio analysis. Real money math, no LLM math.\n\nPortfolio analysis and market intelligence for any MCP-capable agent.\n\nv4.1.34 | Apache 2.0 + MIT-0 | Educational Use Only\n\nInvestorClaw v4.x is a containerized portfolio analyzer that runs as a\nDocker Compose stack and exposes its tools over MCP-HTTP at\n`localhost:18090`. Any MCP-capable agent — Claude Code, Claude Desktop,\nopenclaw, zeroclaw, hermes — connects as a thin client. No Python\ninstall on the agent side, no per-runtime plugin shim, no\nlanguage-specific bootstrap.\n\n## Features\n\nInvestorClaw analyzes multi-account portfolios with deterministic\nPython computation. The agent presents the engine narrator's\nHMAC-signed envelope answer; it does not guess financial metrics.\n\n- Holdings snapshots for what you own and where you own it\n- Performance metrics for returns, Sharpe + Sortino ratios, max\n  drawdown, beta, value-at-risk\n- Bond analytics for yield-to-maturity, duration, credit quality, and\n  ladders\n- Analyst consensus and price targets on portfolio holdings\n- Today's news on holdings and market-wide topics (per-symbol +\n  general / forex / crypto / merger categories)\n- Portfolio synthesis, optimization, target allocation, drift, scenarios\n- Direct ingestion from CSV, XLS, XLSX, PDF, and broker screenshots\n- **End-of-day report generation** for daily summaries\n- **Stonkmode** — narrated commentary mode with rotating fictional\n  cable-finance personalities (Dr. Stonk, Mission Control, 30+ personas)\n- Educational guardrails; no investment advice\n\n## Install\n\n### OpenClaw / ZeroClaw / Hermes (ClawHub)\n\n```bash\nclawhub install investorclaw\n```\n\nClawHub handles the Docker Compose pull, MCP server registration, and\nport wiring automatically.\n\n### Claude Code / Claude Desktop\n\n```\n/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw\n```\n\nClaude Code and Claude Desktop install the plugin directly from this\nrepo. They use the same skill bundle and the same container-first\nruntime as OpenClaw, ZeroClaw, and Hermes. See\n[docs/GETTING_STARTED.md](../docs/GETTING_STARTED.md) for the full\ncontainer-first setup.\n\n### Manual (Docker Compose, any agent)\n\n## Quick Start\n\n```bash\ngit clone https://github.com/mnemos-os/mnemos-ic-runtime.git ~/.investorclaw\ncd ~/.investorclaw\nmkdir -p portfolios     # IMPORTANT: pre-create so docker doesn't auto-create as root\ndocker compose up -d    # uses the bundled compose.yml\n```\n\nThat's it. The compose pulls\n`ghcr.io/argonautsystems/ic-engine:4.7.7-cpu` (publicly hosted, no\nauth) and runs it on `localhost:18090` (MCP + REST) and\n`localhost:18092` (dashboard).\n\nAfter the container reports `init_state: ready`, ask your first\nquestion through your agent:\n\n```text\nWhat's in my portfolio?\n```\n\nConnect your agent — see [SKILL.md](SKILL.md) for per-runtime config\nblocks (Claude Code, Claude Desktop, openclaw, zeroclaw, hermes).\n\n## Prepare Your Portfolio\n\nExport holdings from your broker. CSV offers the highest compatibility.\n\n- Schwab: Accounts → Positions → Export CSV\n- Fidelity: NetBenefits → Investments → Download CSV\n- Vanguard: My Accounts → Download Holdings\n- UBS: Wealth Management → Holdings → Export\n- ETrade: Portfolio → Holdings → Download\n- Robinhood: Account → Statements → CSV\n\nAlso supported: XLS / XLSX, PDF broker statements, and screenshots of\nbroker positions pages. Drop the file into the bind-mounted\n`./portfolios/` directory under your compose project, or attach files\ndirectly in your agent chat — the agent stages them automatically when\nneeded and asks the original question through `portfolio_ask`.\n\n## Run Analysis\n\nAsk in natural language. Your agent will route through `portfolio_ask`.\n\n```text\nWhat's in my portfolio?\nHow am I doing this year?\nShow me my bond exposure and yield-to-maturity.\nWhat's my Sharpe ratio?\nWhat's my sector exposure?\nHelp me rebalance to a 60/40 target.\nWhat is the current price of NVDA?\nToday's news on my holdings.\n```\n\n### End-of-day report\n\n```text\nGenerate today's EOD report.\n```\n\nThe engine produces a daily summary covering holdings, performance,\nbonds, analyst consensus, news, cashflow projections, and synthesis.\nReports land in `./reports/YYYY-MM-DD/` on the host. Send the report\nto your advisor, archive it, or pass it back to the agent for\nfollow-up questions.\n\n### Stonkmode (narrated commentary)\n\nStonkmode wraps portfolio output in commentary from a randomly-selected\npair of fictional cable-finance TV personalities (a \"lead\" and a\n\"foil\"). The deterministic analysis runs unchanged — only the narrator\nvoice changes.\n\n```text\nSwitch to stonkmode.\nWhat's in my portfolio?\n```\n\nThe dashboard at `localhost:18092` exposes a `--stonkmode on/off`\ntoggle, a Mission Control side panel with Dr. Stonk avatars (30+\npersonas, WebP-embedded for offline use), a soundboard, and a\nCaptain's Log. State persists in `~/.investorclaw/stonkmode.json`.\n\n### Fresh data\n\nForce a fresh pipeline run when news, prices, or portfolio files may\nhave moved:\n\n```text\nRefresh my portfolio.\n```\n\n## Available MCP Tools (13 Total)\n\n| Tool | Purpose |\n|---|---|\n| **`portfolio_ask`** | **Primary tool — every portfolio question. Data is auto-loaded; just ask.** |\n| `portfolio_initialize_status` | Poll before first ask: returns init `state` + per-stage progress |\n| `portfolio_initialize` | Force a manual bootstrap (setup → refresh → seed ask) |\n| `portfolio_holdings` | Holdings snapshot (advanced; `portfolio_ask` covers this) |\n| `portfolio_refresh` | Force fresh data pull (auto-refresh runs on every ask) |\n| `portfolio_setup` | Auto-discover portfolio files in the configured directory |\n| `portfolio_keys_status` | Report which API keys are currently configured |\n| `portfolio_keys_set` | Set one or more API keys (allowlisted) |\n| `portfolio_keys_delete` | Delete a single configured API key by name |\n| `portfolio_response_get` | Retrieve a stored portfolio response by run_id |\n| `portfolio_response_list` | List recent stored responses |\n| `portfolio_response_delete` | Permanently delete a stored response |\n\nAll 13 tools also have plain-HTTP REST endpoints at\n`http://127.0.0.1:18090/api/portfolio/*` — useful when MCP integration\nis flaky or you want to drive the engine from a shell.\n\n## Dashboard / Web Portal\n\nThe dashboard runs at `http://localhost:18092` and is the human-facing\nsurface — separate from the MCP-HTTP agent surface at port 18090.\n\n### 17 tabs\n\n| Tab | What it shows |\n|---|---|\n| **Overview** | Portfolio summary + Regenerate sweep button |\n| **Holdings** | Positions, values, weights, accounts |\n| **Performance** | Returns, Sharpe, Sortino, max drawdown, beta, VaR |\n| **WhatChanged** | Delta snapshot vs. prior run |\n| **Scenarios** | Rate-shock, drawdown, and correlation-break what-if |\n| **Bonds** | YTM, duration, convexity, FRED yield-curve overlay |\n| **Optimize** | MPT: Sharpe-max, min-vol, target-return frontiers |\n| **Cashflow** | Projected dividends and bond coupons |\n| **Peer** | Peer and benchmark comparison |\n| **Analyst** | Analyst consensus ratings per holding |\n| **News** | News correlation for held positions |\n| **Markets** | Market-wide news and macro data |\n| **Lookup** | Ticker / account lookup |\n| **Synthesis** | LLM-synthesized portfolio narrative |\n| **Reports** | Browse and download EOD and advisor reports |\n| **Settings** | API keys, portfolio upload form, preferences |\n| **About** | Version, license, attribution |\n\nAll 30 natural-language queries in the agentic COBOL test suite map to\none of these 17 tabs — the tab coverage is complete.\n\n### Regenerate button\n\nThe **Regenerate** button on the Overview tab fires a background sweep:\n`setup → refresh → 12 section analyzers`. Use it to rebuild the full\ncache after uploading a new portfolio or at the start of a session.\n\n### Portfolio file upload\n\nThe Settings tab has a web upload form that accepts `.csv`, `.tsv`,\n`.xls`, `.xlsx`, `.pdf`, `.json`, `.ofx`, and `.qfx` files. The form\nsanitizes the filename, writes the file to `/data/portfolios/` inside\nthe container, and queues a refresh automatically.\n\n### API key configuration\n\nAll 8 provider keys are configurable via the Settings tab form (no\nshell or container restart required):\n\n| Key | Provider | Purpose |\n|---|---|---|\n| `TOGETHER_API_KEY` | Together AI | Narrative synthesis (required for prose output) |\n| `OPENAI_API_KEY` | OpenAI | Alternative narrative provider |\n| `FINNHUB_KEY` | Finnhub | Real-time quotes + analyst ratings |\n| `FRED_API_KEY` | FRED | Treasury yields + economic indicators |\n| `NEWSAPI_KEY` | NewsAPI | Per-symbol + market-wide news |\n| `ALPHA_VANTAGE_KEY` | Alpha Vantage | Quote fallback |\n| `MASSIVE_API_KEY` | Massive (via Massive) | High-scale quote coverage (200+ symbols) |\n| `MARKETAUX_API_KEY` | MarketAux | Alternative news source |\n\nKeys can also be set via the `portfolio_keys_set` MCP tool from your\nagent without opening the dashboard.\n\n## Power-User Endpoints\n\nThese REST endpoints don't compete with `portfolio_ask` for routing\nbut are available for power users:\n\n| Endpoint | Use for |\n|---|---|\n| `GET /healthz` | Liveness + init state probe |\n| `GET /api/portfolio/initialize/status` | Init progress JSON |\n| `GET /api/portfolio/initialize/stream` | SSE stream of init state changes |\n| `GET /api/portfolio/tools` | Self-describing tool catalog |\n| `POST /api/portfolio/keys_set` | Set provider keys without restart |\n\nThe `dashboard` at `localhost:18092` is a single-page HTML UI with\ntabs for Overview · Holdings · Performance · WhatChanged · Scenarios · Bonds · Optimize · Cashflow · Peer · Analyst · News · Markets · Lookup · Synthesis · Reports · Settings · About.\n\n## Recommended Model Combinations\n\nInvestorClaw uses two LLM roles when answering: **narrative**\n(synthesizes the signed envelope into prose) and **validator** (checks\nthe narrative against the envelope for fabrication and number\npreservation).\n\n### Claude Code / Claude Desktop\n\nThe agent's own Anthropic LLM does both — no external API key needed.\n\n- **Narrative**: Haiku 4.5 — fast, cheap, ~10× lower output cost than\n  Sonnet. With a clean signed envelope, narrative synthesis is mostly\n  transcription.\n- **Validator**: Sonnet 4.6 (default) or Opus 4.7 (escalation) — gates\n  Haiku's output for fabrication, mis-quoted numbers, training-leak\n  drift.\n\nCost-shaped: cheap model on the long output, smart model on the short\nsafety check. Total session cost on a 100-position portfolio typically\nlands well under $0.01.\n\n### openclaw / zeroclaw / hermes\n\nBring a non-Anthropic provider via `TOGETHER_API_KEY` (or equivalent).\nAnthropic on the claws stack is a paid-API-only path since 2026-04-04\n(OAuth-subscription tokens against a claws-agent runtime violate\nAnthropic's ToS). Fleet defaults:\n\n- **Default narrative**: Together AI `google/gemma-4-31B-it` —\n  serverless, ~100 tok/s, ~$0.0008 / 1 K tokens. Container default.\n- **Higher-quality alternative**: Together AI `MiniMaxAI/MiniMax-M2` —\n  larger context, but moved off Together's serverless tier 2026-05;\n  requires a paid dedicated endpoint.\n- **Local-only / offline**: Ollama `gemma4:e4b` on host — zero cloud\n  cost, GPU-bound, no key required.\n\n## Recommended API Keys by Portfolio Size\n\n| Size | Required | Recommended | Why |\n|---|---|---|---|\n| **≤ 50 symbols** | `TOGETHER_API_KEY` (narrative) | — | yfinance handles quotes/history at this scale |\n| **50–200 symbols** | `TOGETHER_API_KEY` | `FINNHUB_KEY` (free 60/min) + `NEWSAPI_KEY` (free 100/day) | Real-time quotes + analyst + per-symbol news without yfinance throttle |\n| **200+ symbols** | `TOGETHER_API_KEY` + `MASSIVE_API_KEY` (Massive, paid) | `FINNHUB_KEY` + `MARKETAUX_API_KEY` (free 100/day) + `FRED_API_KEY` (free, registration) + `ALPHA_VANTAGE_KEY` (free 25/day) | Yahoo's anonymous endpoint rate-limits globally on 200+ symbols; Massive is required, the rest fill analyst + news + yields |\n\n`TOGETHER_API_KEY` is the only key that meaningfully changes output\nquality. Everything else is for scale or richness on larger portfolios.\nThe deterministic engine works key-less in degraded mode (yfinance-only)\nbut the narrator returns stub catalog summaries instead of real prose.\n\nSign-up links (free tiers exist for everything except Massive):\n[Together AI](https://api.together.ai/settings/api-keys) ·\n[Finnhub](https://finnhub.io/register) ·\n[Massive](https://massive.com/dashboard/api-keys) ·\n[MarketAux](https://www.marketaux.com/account/dashboard) ·\n[NewsAPI](https://newsapi.org/register) ·\n[FRED](https://fred.stlouisfed.org/docs/api/api_key.html) ·\n[Alpha Vantage](https://www.alphavantage.co/support/#api-key)\n\n## How It Works\n\n1. You drop a portfolio (CSV / XLS / PDF / screenshot) into\n   `./portfolios/`, or attach one in your agent chat.\n2. Your agent calls `portfolio_setup` and `portfolio_ask` over MCP-HTTP\n   on `localhost:18090`.\n3. ic-engine pre-runs the deterministic backend pipeline for the\n   question.\n4. The result is stored as an HMAC-signed JSON envelope in\n   `./reports/`.\n5. A strict narrator receives only the signed envelope and the\n   question, quotes verbatim from authoritative sources, and refuses\n   to fabricate missing facts.\n6. Your agent returns the narrative to you.\n\nThe first prompt after a cold install can take 30–60 seconds because\nthe full deterministic pipeline is building the signed envelope.\nSubsequent prompts are cache-amortized (TTL: 30 s for news, 60 s for\nother sections) unless you call `portfolio_refresh`.\n\n## Data Privacy\n\nYour data stays on your machine by default.\n\n- Raw broker files stay local in `./portfolios/`\n- Account numbers and SSNs are scrubbed on import\n- Only computed summaries and the signed envelope are sent to the\n  configured narrative provider (Together AI by default)\n- InvestorClaw never executes trades, never moves money, never\n  authenticates to any brokerage\n- All analysis is educational and not investment advice\n\nSee [PRIVACY.md](PRIVACY.md) for the full data-handling policy and\n[DISCLAIMER.md](DISCLAIMER.md) for the educational-only framing.\n\n## Documentation\n\n- [SKILL.md](SKILL.md) — agent-readable install + usage spec, full\n  13-tool catalog, first-run timeline, REST endpoints, troubleshooting\n- [PRIVACY.md](PRIVACY.md) — full data-handling policy\n- [DISCLAIMER.md](DISCLAIMER.md) — educational-use disclaimer + provider\n  data flows\n- [SECURITY.md](SECURITY.md) — vulnerability disclosure\n- [CONTRIBUTING.md](CONTRIBUTING.md) — contribution workflow\n- [CHANGELOG.md](CHANGELOG.md) — release history\n- [CAPABILITIES.md](CAPABILITIES.md) — full feature catalog (the\n  master \"what can it do\" doc)\n- [STONKMODE.md](STONKMODE.md) — narrated commentary mode + 30\n  fictional cable-finance personas\n- [docs/GLOSSARY.md](docs/GLOSSARY.md) — financial terminology\n  reference (Sharpe, Sortino, YTM, duration, etc.)\n- [docs/PHILOSOPHY.md](docs/PHILOSOPHY.md) — \"deterministic-first,\n  no LLM math\" rationale\n- [docs/WINDOWS_SETUP_GUIDE.md](docs/WINDOWS_SETUP_GUIDE.md) —\n  Windows + WSL2 install gotchas\n- [docs/STONKMODE_ARCHITECTURE.md](docs/STONKMODE_ARCHITECTURE.md) —\n  Stonkmode pipeline (market detection → archetype weighting → pair\n  selection → narration)\n- [docs/STONKMODE_AVATAR_LEGEND.md](docs/STONKMODE_AVATAR_LEGEND.md) —\n  30-persona avatar reference\n- [docs/EOD_REPORT.md](docs/EOD_REPORT.md) — end-of-day report feature walkthrough (what is in the report, how to generate, performance, optional email delivery)\n- [docs/MCP_TOOLS_REFERENCE.md](docs/MCP_TOOLS_REFERENCE.md) —\n  detailed per-tool reference for all 13 MCP tools (input / output\n  schemas, latency, cache TTLs, allowlists, examples)\n- [docs/references/](docs/references/) — input / output / schema /\n  consultative-LLM contracts (`contract-input.md`, `contract-output.md`,\n  `schema-holdings-fields.md`, `runtime-gemma4-consult.md`,\n  `presentation-rules.md`, `presentation-nl-query-routing.md`)\n- [docs/INSTALL_MODELS.md](docs/INSTALL_MODELS.md) — *why* the v4.x\n  architecture splits along two install models\n- [docs/COBOL_TESTING.md](docs/COBOL_TESTING.md) — the Agentic COBOL\n  250-prompt regression suite that's the v4.x ship gate. Long-form\n  rationale at\n  [techbroiler.net/all-our-tests-passed-the-agent-was-still-broken](https://techbroiler.net/all-our-tests-passed-the-agent-was-still-broken/).\n- [RFC-v0.1.md](RFC-v0.1.md) — full v4.x architecture specification\n\n## Troubleshooting\n\n### \"ic-engine container won't start\"\n\n```bash\ndocker compose logs ic-engine | tail -50\ndocker ps | grep ic-engine\ncurl -sS http://127.0.0.1:18090/healthz\n```\n\nIf `healthz` returns `{\"init_state\":\"failed\", ...}`, check the\n`init_error` field for the engine's exact failure message. The most\ncommon cause is the `portfolios/` directory being root-owned because\nyou skipped `mkdir -p portfolios` before `docker compose up -d`.\n\n### \"No portfolio found\"\n\nDrop a CSV/XLS/PDF into `./portfolios/`, then call setup:\n```bash\ncurl -X POST http://127.0.0.1:18090/api/portfolio/setup -d '{}'\n```\nOr attach a file directly in your agent chat.\n\n### \"First call is slow (5–15 minutes)\"\n\nOnly happens on a cold cache for portfolios with 200+ positions. The\ncontainer runs `IC_INITIALIZE_ON_BOOT=1` by default — initialization\nruns at container start, so by the time the agent connects, the cache\nis warm. Check progress:\n`curl http://127.0.0.1:18090/api/portfolio/initialize/status`.\n\n### Reset cache + state\n\n```bash\ndocker compose down -v   # removes the data volume — all envelopes lost\ndocker compose up -d     # cold restart with auto-init\n```\n\nSee [SKILL.md § Troubleshooting](SKILL.md) for the full list.\n\n## Status\n\nProduction Ready | Apache 2.0 + MIT-0\n\nInvestorClaw v4.1.x. Portfolio analysis. Educational only. Not\nfinancial advice.\n\n## Related repos\n\n| Repo | Scope |\n|---|---|\n| [`argonautsystems/InvestorClaw`](https://github.com/argonautsystems/InvestorClaw) (this repo) | v4.x container-first plugin, skill bundle, Docker Compose runtime, and dashboard |\n| [`argonautsystems/ic-engine`](https://github.com/argonautsystems/ic-engine) | ic-engine analytical Python source (pulled into the container at build time) |\n\nFile v4.10.0:_meta.json\n\n{\n  \"ownerId\": \"kn73c3q5r5wscsrtcxbsnqj2dh835jvm\",\n  \"slug\": \"investorclaw\",\n  \"version\": \"4.10.0\",\n  \"publishedAt\": 1781551953909\n}\n\nFile v4.10.0:docs/references/contract-input.md\n\n<!--\nv4.x adaptation note: this reference contract is carried forward from\nv2.6 essentially unchanged — the engine's input/output schema, holdings\nfield mapping, and consultative-LLM setup are identical in v4.x. The\nonly surface change is invocation: replace v2.x `/portfolio X` slash\ncommands with the equivalent v4.x MCP tool (`portfolio_X`) or a\nnatural-language query through `portfolio_ask`. Paths like\n`~/portfolio_reports/` correspond to the bind-mounted `./reports/`\nunder your compose project; `portfolios/` corresponds to the\nbind-mounted `./portfolios/`.\n-->\n\n# Input Contract\n\nSupported portfolio file types: CSV, Excel (`.xls`, `.xlsx`). Place files in\n`portfolios/` or `$INVESTOR_CLAW_PORTFOLIO_DIR`.\n\n## Auto-detected column names\n\n| Column | Recognized names |\n|--------|-----------------|\n| Symbol | `SYMBOL`, `TICKER`, `symbol`, `Description` |\n| Quantity | `QUANTITY`, `SHARES`, `QTY`, `shares` |\n| Price | `PRICE`, `MARKET PRICE`, `current_price` |\n| Value | `VALUE`, `MARKET VALUE`, `value` |\n| Asset type | `ASSET TYPE`, `TYPE`, `asset_type` |\n| Cost basis | `COST BASIS`, `PURCHASE PRICE`, `purchase_price` |\n| Purchase date | `PURCHASE DATE`, `purchase_date` |\n| Coupon rate | `COUPON`, `COUPON RATE`, `coupon_rate` (bonds) |\n| Maturity date | `MATURITY`, `MATURITY DATE`, `maturity_date` (bonds) |\n\n## Bond metadata in description strings\n\nBond coupon and maturity embedded in description text (e.g.,\n`\"RATE 05.000% MATURES 11/01/28\"`) are extracted automatically during\ningestion. No explicit coupon/maturity columns are required for bonds if the\ndescription carries them.\n\n## Guided mapping\n\nRun `/portfolio setup` for guided column-mapping if your broker uses column\nnames that don't appear in the recognized-names table above.\n\nFile v4.10.0:docs/references/contract-output.md\n\n<!--\nv4.x adaptation note: this reference contract is carried forward from\nv2.6 essentially unchanged — the engine's input/output schema, holdings\nfield mapping, and consultative-LLM setup are identical in v4.x. The\nonly surface change is invocation: replace v2.x `/portfolio X` slash\ncommands with the equivalent v4.x MCP tool (`portfolio_X`) or a\nnatural-language query through `portfolio_ask`. Paths like\n`~/portfolio_reports/` correspond to the bind-mounted `./reports/`\nunder your compose project; `portfolios/` corresponds to the\nbind-mounted `./portfolios/`.\n-->\n\n# Output Contract\n\nFull spec of the output-response rules the skill commits to. SKILL.md links\nhere from `## Output Contracts`.\n\n## Directory layout\n\n```\n~/portfolio_reports/                  ← agent-readable compact files ONLY\n    holdings_summary.json\n    performance.json\n    bond_analysis.json\n    analyst_data.json\n    portfolio_news.json\n    portfolio_analysis.json\n    fixed_income_analysis.json\n    session_profile.json\n    portfolio_report.xlsx / *.csv\n\n~/portfolio_reports/.raw/             ← optional internal / enrichment artifacts\n    holdings.json\n    analyst_recommendations_tier1_immediate.json\n    analyst_recommendations_tier2_background.json\n    analyst_recommendations_tier3_enriched.json\n    performance.json\n    bond_analysis.json\n    portfolio_news_cache.json\n```\n\n**Never read files from `.raw/` directly.** If you need specific symbol detail\nnot in the compact output, use the lookup command instead.\n\n## Envelope format\n\nAll outputs use the mandatory disclaimer wrapper:\n\n```json\n{\n  \"disclaimer\": \"⚠️  EDUCATIONAL ANALYSIS - NOT INVESTMENT ADVICE\",\n  \"is_investment_advice\": false,\n  \"consult_professional\": \"Consult a qualified financial adviser\",\n  \"data\": { ... },\n  \"generated_at\": \"2026-04-07T...\"\n}\n```\n\n## Compact vs full output\n\nHoldings, performance, and analyst commands emit compact JSON to stdout\n(~1–5K tokens). Holdings also writes `portfolio_reports/holdings_summary.json`\nas the agent-readable compact file. The full data is written to\n`portfolio_reports/.raw/` for downstream script use only.\n\nWork exclusively from compact stdout output or the summary files in\n`portfolio_reports/`. If a user asks for a specific symbol or detail not in\nthe compact output, use the lookup command:\n\n```bash\n# Holdings detail for a symbol\ninvestorclaw lookup --symbol AAPL\ninvestorclaw lookup --symbol AAPL --file holdings\n\n# Analyst data for a symbol\ninvestorclaw lookup --symbol MSFT --file analyst\n\n# Top 10 performers from performance data\ninvestorclaw lookup --file performance --top 10\n\n# Account summary from holdings\ninvestorclaw lookup --accounts\n\n# Specific fields only\ninvestorclaw lookup --symbol AAPL --fields consensus,analyst_count,current_price\n```\n\nEnvironment variables are set automatically by the setup orchestrator. Lookup\nreturns a compact targeted slice — never the full file.\n\n## Verbatim quote blocks\n\nWhen a `quote` block is present in any output JSON with `verbatim_required: true`:\n\n- If `quote.card_path` is set, present the card path and cite `quote.attribution`.\n- Otherwise present `quote.text` **verbatim** — do not paraphrase or reorder.\n- Always include `quote.fingerprint` in your response for audit traceability.\n- Do not re-analyze or substitute your own synthesis.\n\n```json\n{\n  \"quote\": {\n    \"text\": \"Analyst consensus is Strong Buy with 54 analysts...\",\n    \"attribution\": \"gemma4-consult via local-inference (3420ms)\",\n    \"verbatim_required\": true,\n    \"fingerprint\": \"a1b2c3d4e5f6g7h8\",\n    \"card_path\": \"/Users/.../portfolio_reports/.raw/consultation_cards/MSFT.svg\"\n  },\n  \"consultation\": {\n    \"model\": \"gemma4-consult\",\n    \"endpoint\": \"http://localhost:11434\",\n    \"inference_ms\": 3420,\n    \"is_heuristic\": false\n  }\n}\n```\n\nThe consultation model is user-configured via `INVESTORCLAW_CONSULTATION_MODEL`.\nDefault: `gemma4-consult` — a tuned Ollama derivative of `gemma4:e4b`\n(num_ctx=4096, num_predict=1200, ~65 tok/s on RTX Ada). Other tested models:\n`gemma4:e4b`, `nemotron-3-nano`, `qwen2.5:14b`. Run `/portfolio setup` to\nauto-detect available models on your endpoint. Full setup steps in\n[runtime-gemma4-consult.md](runtime-gemma4-consult.md).\n\n## synthesis_basis confidence tiers\n\nEach symbol in compact output includes a `synthesis_basis` field:\n\n| Value | Source | Agent behavior |\n|-------|--------|---------------|\n| `enriched` | LLM synthesis (is_heuristic=false) | Present `quote.text` verbatim or show `quote.card_path` |\n| `structured` | Live Finnhub data, no synthesis | Cite structured fields only: `\"Analyst consensus: {consensus} ({analyst_count} analysts)\"` |\n| `failed` | No price or analyst data | State data unavailable — do not synthesize |\n\n**Never apply enriched-symbol quality inferences to `structured` positions.**\n\n## Turn-level enrichment status\n\nEvery analyst or portfolio response must begin with the\n`enrichment_status.display` string:\n\n```\n⏳ Enrichment: 20/215 · 9.3% · a1b2c3d4 · updating\n✅ Enrichment: 215/215 · 100.0% · a1b2c3d4 · complete\n⚠️ Enrichment status unknown\n```\n\nThe display string is sourced from `enrichment_status.display` in the compact\nstdout. If absent, output `⚠️ Enrichment status unknown`.\n\nFile v4.10.0:docs/references/presentation-nl-query-routing.md\n\n<!--\nv4.x adaptation note: this reference contract is carried forward from\nv2.6 essentially unchanged — the engine's input/output schema, holdings\nfield mapping, and consultative-LLM setup are identical in v4.x. The\nonly surface change is invocation: replace v2.x `/portfolio X` slash\ncommands with the equivalent v4.x MCP tool (`portfolio_X`) or a\nnatural-language query through `portfolio_ask`. Paths like\n`~/portfolio_reports/` correspond to the bind-mounted `./reports/`\nunder your compose project; `portfolios/` corresponds to the\nbind-mounted `./portfolios/`.\n-->\n\n# NL Query Routing — Seed Pattern Dictionary (v2.1.0)\n\nDirective rules for how the calling LLM should turn natural-language\nportfolio queries into canonical `/portfolio <command>` invocations.\n\nThis is a seed set. It targets the 10 intent clusters that produced the\nworst routing outcomes in the internal NL-250 harness run (2026-04-22):\nagents either refused to load the skill, or they hallucinated a\nportfolio answer without invoking any underlying script (`ic_result`\nabsent). Each pattern below includes a canonical invocation, expected\noutput envelope fields, and common anti-patterns.\n\nFull pattern coverage is planned for a follow-on release with fresh\nNL-N measurements backing each addition. For now, prefer these patterns\nover improvisation when the user's phrasing matches.\n\n## Pattern 1 — \"Show me my holdings\" (holdings basics)\n\n**NL phrases (non-exhaustive):**\n- \"Show my holdings\"\n- \"What do I own?\"\n- \"List my positions\"\n- \"What's in my portfolio?\"\n- \"What's my total portfolio value?\"\n\n**Canonical invocation:**\n```\n/portfolio holdings\n```\n\n**Output envelope to surface:** `holdings_summary.json` — `total_value`,\n`position_count`, top-5 positions by value, sector breakdown.\n\n**Anti-patterns:**\n- ❌ *\"Use the portfolio skill to run /portfolio holdings\"* — OpenClaw's\n  skill-loader heuristic rejects NL-wrapped slash commands. Invoke the\n  slash form directly.\n- ❌ Summarizing from memory / prior-session cache if `ic_result` is\n  absent — that is a stale-masquerade failure mode. Say so explicitly.\n\n## Pattern 2 — \"How am I doing?\" (performance)\n\n**NL phrases:**\n- \"How is my portfolio doing?\"\n- \"What's my return?\"\n- \"Am I beating the market?\"\n- \"Am I beating the S&P 500?\"\n- \"What's my Sharpe ratio?\"\n- \"What's my volatility?\"\n\n**Canonical invocation:**\n```\n/portfolio performance\n```\n\n**Output envelope:** `performance.json` — `total_return`, `annualized_return`,\n`sharpe_ratio`, `volatility`, `benchmark_comparison`.\n\n**Anti-patterns:**\n- ❌ Speaking to \"beating the market\" without the benchmark field\n  actually present in the envelope. If `benchmark_comparison` is null,\n  say benchmark comparison was not computed; do not synthesize a number.\n\n## Pattern 3 — \"Show my bonds\" (fixed-income basics)\n\n**NL phrases:**\n- \"Show my bond exposure\"\n- \"Analyze my fixed income\"\n- \"What's my bond allocation?\"\n- \"What's my bond YTM?\"\n- \"Show my bond ladder\"\n\n**Canonical invocation:**\n```\n/portfolio bonds\n```\n\n**Output envelope:** `bond_analysis.json` — `bond_count`, `total_value`,\n`weighted_ytm`, `weighted_duration`, per-bond detail.\n\n**Empty-state handling:** if `bond_count` is 0, respond exactly:\n\"No bonds in this portfolio — bond analysis skipped.\" Do NOT synthesize\na response about bonds; there aren't any. (Empty-set handling guaranteed\nby the envelope contract per commit `49e9d1c` / v2.1.0.)\n\n**Anti-patterns:**\n- ❌ Asserting a YTM or duration that isn't in the envelope.\n- ❌ Treating a missing bond envelope as \"TODO later\" — the command is\n  safe to run on any portfolio; empty results are a valid answer.\n\n## Pattern 4 — \"What does Wall Street think?\" (analyst consensus)\n\n**NL phrases:**\n- \"What does Wall Street think?\"\n- \"Show analyst ratings\"\n- \"Any analyst upgrades?\"\n- \"What are analysts saying about [TICKER]?\"\n\n**Canonical invocation:**\n```\n/portfolio analyst\n```\n\nFor a single symbol:\n```\n/portfolio lookup --symbol TICKER --file analyst\n```\n\n**Output envelope:** `analyst_data.json` — per-holding\n`consensus` / `analyst_count` / `price_target`. Each position carries a\n`synthesis_basis` tier (`enriched` / `structured` / `failed`) — see\n[contract-output.md](contract-output.md).\n\n**Anti-patterns:**\n- ❌ Presenting `structured` positions as if they were `enriched` (no\n  narrative inference on structured-only data).\n- ❌ Answering about a specific ticker without running the lookup\n  command — direct-from-envelope only.\n\n## Pattern 5 — \"Any news on my stocks?\" (news correlation)\n\n**NL phrases:**\n- \"Any news on my stocks?\"\n- \"Show recent headlines\"\n- \"What's happening with my holdings?\"\n- \"What's moving my portfolio today?\"\n\n**Canonical invocation:**\n```\n/portfolio news\n```\n\n**Output envelope:** `portfolio_news.json` — `sentiment_breakdown`,\n`top_positive_movers`, `top_negative_movers`, `symbol_digest`,\n`macro_themes`.\n\n**Presentation:** follow the \"News digest layout\" in\n[presentation-rules.md](presentation-rules.md) — stacked two-line\nmovers with dollar impact; never collapse all news into one sentence.\n\n**Anti-patterns:**\n- ❌ Reporting portfolio-wide sentiment without the per-symbol breakdown.\n- ❌ Summarizing article titles without `portfolio_impact` weighting.\n\n## Pattern 6 — \"Should I rebalance?\" (scenario + tax-aware)\n\n**NL phrases:**\n- \"Should I rebalance?\"\n- \"Do I need to rebalance?\"\n- \"Is it time to rebalance?\"\n- \"Would rebalancing help?\"\n- \"Show me a rebalancing scenario\"\n- \"Tax-aware rebalancing options\"\n- \"Calculate my tax loss harvesting opportunities\"\n\n**Canonical invocations (two-step):**\n```\n/portfolio scenario\n```\nfollowed by, if the user cares about tax efficiency:\n```\n/portfolio rebalance-tax\n```\n\n**Important — do not route to `/portfolio synthesize`:** \"Should I\nrebalance?\" sits close to \"recommend what to do\" semantically, but the\ncanonical answer lives in the scenario/rebalance-tax envelopes (trade\ntree + tax-lot impact), not in the synthesis envelope. Route to\n`/portfolio scenario` first; only escalate to `/portfolio synthesize`\nif the user explicitly asks for a broader recommendation pass.\n\n**Output envelopes:** `scenario` produces rebalancing trade trees;\n`rebalance-tax` adds unrealized-gain/loss impact + tax-lot selection.\n\n**Educational framing (non-negotiable):**\n- ❌ Never say \"You should rebalance\" as a directive.\n- ❌ Never use imperative-voice advice verbs (sell, buy, must, should).\n- ✅ Frame as \"If you were to rebalance to X target, the envelope shows\n  Y trades with Z tax impact.\" Educational output only.\n\n## Pattern 7 — \"Explain concept X\" (financial education)\n\n**NL phrases (representative):**\n- \"What's yield to maturity?\"\n- \"What is YTM?\"\n- \"Explain bond duration to me\"\n- \"What's a Sharpe ratio?\"\n- \"What's modern portfolio theory?\"\n- \"Explain tax-loss harvesting\"\n- \"What does alpha mean?\"\n- \"Define [any finance term]\"\n\n**Routing:** these are NOT InvestorClaw's job. InvestorClaw operates on\nthe user's own portfolio; it is not a financial-terminology glossary.\n\n**Mandatory behavior — not a suggestion:** when the user asks to\n**explain, define, describe, or elaborate on a finance concept** and\nthe question does **not name one of their specific holdings**, you\nMUST decline. **Do NOT answer from your own training data even if you\nknow the definition.** Answering from general knowledge produces an\n`ic_result`-absent response that looks authoritative but is\nunverifiable — the exact failure mode this skill's contract exists to\nprevent.\n\n**Canonical response (use verbatim or close to it):**\n\n> \"That's a general finance-concept question, not specific to your\n> portfolio. InvestorClaw is scoped to your actual holdings and does\n> not run a glossary or education layer. Try asking 'show me my\n> [bonds / performance / holdings]' instead, or use a general-purpose\n> knowledge source for concept explanations.\"\n\n**Self-check before answering any concept-shaped question:**\n1. Does the question name a symbol or asset in the user's portfolio?\n   If no → **decline, do not answer**.\n2. Does the question ask \"what is X\" / \"define X\" / \"explain X\" where\n   X is a term, ratio, or concept (not a holding)? → **decline, do\n   not answer**.\n3. Would my answer come from my pretraining rather than from a skill\n   command's output? → **decline, do not answer**.\n\n**Anti-patterns:**\n- ❌ Answering the concept question using general knowledge — this\n  bypasses the skill entirely and produces `ic_result`-absent output\n  that looks authoritative but is unverifiable.\n- ❌ Declining but appending \"but here's a quick definition anyway...\"\n  — the decline is absolute, not a preamble.\n- ❌ Running an InvestorClaw command just to pad a concept explanation\n  with synthetic portfolio data.\n\n## Pattern 8 — Market-wide / macro queries (out of scope)\n\n**NL phrases (representative):**\n- \"What's happening in the market today?\"\n- \"How is the S&P 500 performing?\"\n- \"What's the Fed doing?\"\n- \"Latest inflation data?\"\n- \"Show me economic calendar\"\n- \"What about Bitcoin?\"\n- \"What's the VIX at?\"\n\n**Routing:** InvestorClaw does not cover market-wide, macro, or\nnon-held-position queries. Its news and analyst layers join *on the\nuser's own holdings*, not on open-universe market data.\n\n**Canonical response:** decline and redirect:\n\n> \"InvestorClaw is scoped to your own portfolio — it joins news,\n> analyst, and performance data to positions you actually hold. For\n> open-market commentary, VIX levels, Fed policy, or macroeconomic\n> data, use a dedicated market-data tool instead.\"\n\n**Anti-patterns:**\n- ❌ Running `/portfolio news` and framing it as \"market news\" — it\n  is portfolio-joined news only.\n- ❌ Answering from general knowledge about today's market movement\n  — that fabricates recency and is unverifiable.\n\n## Pattern 9 — Multi-intent / \"full picture\" queries\n\n**NL phrases:**\n- \"Show my holdings and find tax-loss opportunities\"\n- \"Analyze my performance and tell me if I should rebalance\"\n- \"Give me the full picture\"\n\n**Canonical invocation:**\n```\n/portfolio analysis\n```\n\nOr the full 8-stage pipeline:\n```\n/portfolio complete\n```\n\n**Output envelope:** `portfolio_analysis.json` stitched from the\nprimary envelopes (holdings + performance + bonds + analyst + news +\nsynthesis).\n\n**When to split instead:**\n- If the user specified exactly two intents that don't overlap with\n  `/portfolio analysis`'s coverage (e.g., tax-loss + peer comparison),\n  invoke the two commands sequentially and splice their envelopes.\n\n**Anti-patterns:**\n- ❌ Invoking each sub-command separately when `/portfolio analysis`\n  already produces the combined envelope — wastes tokens and produces\n  divergent `ic_result` trails.\n- ❌ Narrating \"doing both\" without actually invoking anything.\n\n## Pattern 10 — \"Dashboard\" requests (v2.1.0 deferral)\n\n**NL phrases:**\n- \"Show me the dashboard\"\n- \"Open the portfolio dashboard\"\n- \"Generate the 15-tab view\"\n- \"Where's the dashboard?\"\n- \"Can I see the dashboard?\"\n\n**Routing:** the interactive PWA dashboard is in development and not\nshipped in the v2.1.0 default install. The `/investorclaw:ic-dashboard`\nslash command is moved to `claude/commands/_incomplete/` and is not\navailable after a standard marketplace install.\n\n**Signal to use this response:** if you try `/portfolio dashboard` and\nget back `❌ Unknown command: dashboard` (or an equivalent \"dashboard\nnot available\" signal from the skill router), switch to this canonical\nresponse template. Do NOT just relay the raw \"Unknown command\" error\nto the user — they will read it as a broken install. Explain the\ndeferral.\n\n**Canonical response (use verbatim or close to it):**\n\n> \"The interactive PWA dashboard is in development for a future release\n> and isn't shipped in the v2.1.0 install — you'll see an 'Unknown\n> command: dashboard' error if you try to run it directly. In place of\n> the dashboard I can run a narrative portfolio walkthrough right now\n> with `/portfolio analysis`, or the full 8-stage pipeline with\n> `/portfolio complete`. Both produce the same underlying data the\n> dashboard is going to visualize.\"\n\n**Anti-patterns:**\n- ❌ Trying to invoke `/investorclaw:ic-dashboard` — the slash file\n  won't be registered after install.\n- ❌ Relaying the raw `❌ Unknown command: dashboard` output as the\n  final answer — technically correct, operationally a failure; the\n  user needs the context that the dashboard is *deferred*, not broken.\n- ❌ Synthesizing what a dashboard *would* show from memory —\n  `ic_result`-absent answer that looks authoritative but isn't.\n\n## Coverage note\n\nThese ten patterns cover the highest-volume intent clusters observed\nin the NL-250 harness run: holdings basics, performance, fixed income,\nanalyst ratings, news correlation, rebalancing, finance-concept\ndeflection, market-wide deflection, multi-intent routing, and the\ndeferred dashboard surface. Queries that don't match a listed pattern\nshould fall back to either `/portfolio help` or the finance-concept\ndecline in Pattern 7.\n\nFull pattern coverage (targeting all 250 NL-250 categories with\nper-category `ic_result` measurements) is planned for a follow-on\nrelease. Until then, log any intent-cluster miss you observe and file\nit for inclusion in the next expansion.\n\nFile v4.10.0:docs/references/presentation-rules.md\n\n<!--\nv4.x adaptation note: this reference contract is carried forward from\nv2.6 essentially unchanged — the engine's input/output schema, holdings\nfield mapping, and consultative-LLM setup are identical in v4.x. The\nonly surface change is invocation: replace v2.x `/portfolio X` slash\ncommands with the equivalent v4.x MCP tool (`portfolio_X`) or a\nnatural-language query through `portfolio_ask`. Paths like\n`~/portfolio_reports/` correspond to the bind-mounted `./reports/`\nunder your compose project; `portfolios/` corresponds to the\nbind-mounted `./portfolios/`.\n-->\n\n# Agent-Side Presentation Rules\n\nDirective rules for how the calling LLM renders this skill's output to the\nuser. These are not user-facing docs; they govern the agent's turn.\n\n## Mobile-channel formatting\n\nMany users interact via mobile channels (320–430px display width). Format\nall output to be readable on small screens:\n\n- **No wide tables** — avoid pipe-separated columns that wrap badly.\n- **Max ~60 characters per line** — use stacked two-line formats instead of\n  horizontal layouts.\n- **No raw JSON to user** — always render the compact digest as prose or short\n  lists.\n- **Bold tickers** — use `**AAPL**` for symbol emphasis.\n- **Short separators** — use `---` or a brief label, not 60/80-char `===`\n  banners.\n- **Mobile-first default** — assume mobile unless `--verbose` is passed.\n\n## News digest layout\n\nPresent `portfolio_news.json` compact digest as follows — do NOT collapse\nall news into one sentence:\n\n1. **Overall sentiment** — `sentiment_breakdown` counts + net portfolio\n   impact.\n2. **Top positive movers** — top 5 from `top_positive_movers`, two-line\n   stacked format:\n   ```\n   📈 **AAPL** +$10,500\n      Apple Q1 Earnings Beat Estimates by 12%\n   ```\n3. **Top negative movers** — top 5 from `top_negative_movers`, same stacked\n   format:\n   ```\n   📉 **NVDA** -$8,200\n      Chip export restrictions widen to additional markets\n   ```\n4. **Symbol digest** — from `symbol_digest`, two lines per holding:\n   ```\n   **MSFT** · 12.4% · Bullish · 4 articles\n     → Azure growth accelerates in Q1 earnings call\n   ```\n5. **Macro themes** — shared themes across multiple holdings (AI capex,\n   rates, energy).\n6. **On-demand detail** — tell the user they can run\n   `/portfolio news --symbol TICKER` for full articles.\n\nSort movers by `portfolio_impact` (highest dollar-weighted first).\n\n## ETF / fund guidance\n\nETF and mutual-fund positions cannot be individually adjusted — the user can\nonly buy or sell the fund as a whole. Before suggesting any position change,\ncheck `is_etf`. If true, frame at fund level (e.g., \"To reduce IVV exposure,\nsell IVV shares — you cannot adjust S&P 500 components directly\"). Analyst\nratings and news for ETF tickers reflect the fund, not individual underlying\ncompanies.\n\nETF classification (`is_etf`, `security_type`) is provided but ETF constituent\nexpansion (detailed allocation view of underlying holdings) is not currently\nimplemented.\n\nFull holdings-field schema in [schema-holdings-fields.md](schema-holdings-fields.md).\n\nArchive v4.7.7: 76 files, 260948 bytes\n\nFiles: agent-skills/claude-code/INSTALL.md (3881b), agent-skills/claude-code/manifest-template.json (3548b), agent-skills/claude-code/SKILL.md (10388b), agent-skills/claude-desktop/config-snippet.json (1358b), agent-skills/claude-desktop/INSTALL.md (6743b), agent-skills/claude-desktop/SKILL.md (8218b), agent-skills/hermes/config-snippet.yaml (880b), agent-skills/hermes/DESCRIPTION.md (3701b), agent-skills/hermes/INSTALL.md (5185b), agent-skills/hermes/SKILL.md (11431b), agent-skills/openclaw/config-snippet.json5 (1066b), agent-skills/openclaw/INSTALL.md (6660b), agent-skills/openclaw/SKILL.md (9098b), agent-skills/zeroclaw/config-snippet.toml (656b), agent-skills/zeroclaw/INSTALL.md (5480b), agent-skills/zeroclaw/SKILL.md (11124b), agent-skills/zeroclaw/SKILL.toml (1826b), assets/investorclaw-logo.svg (1408b), bridge/frozendict_shim/__init__.py (2024b), bridge/investorclaw_bridge/__init__.py (629b), bridge/investorclaw_bridge/bundle_schema.py (10707b), bridge/investorclaw_bridge/bundle.py (21324b), bridge/investorclaw_bridge/dashboard.py (68910b), bridge/investorclaw_bridge/key_resolver.py (5061b), bridge/investorclaw_bridge/mcp_server.py (1088b), bridge/investorclaw_bridge/mcp/__init__.py (1587b), bridge/investorclaw_bridge/mcp/_runtime.py (7299b), bridge/investorclaw_bridge/mcp/tools/__init__.py (2343b), bridge/investorclaw_bridge/mcp/tools/keys.py (9146b), bridge/investorclaw_bridge/mcp/tools/portfolio.py (15906b), bridge/investorclaw_bridge/mcp/tools/responses.py (14063b), bridge/investorclaw_bridge/mcp/transport.py (13916b), bridge/investorclaw_bridge/mnemos_client.py (4849b), bridge/investorclaw_bridge/serve.py (15759b), bridge/investorclaw_bridge/setup_api.py (15397b), bridge/patches/lazy_matplotlib_optimize.py (2141b), bridge/pyproject.toml (1181b), CAPABILITIES.md (22070b), CHANGELOG.md (17868b), CODE_OF_CONDUCT.md (4898b), compose.yml (3886b), CONTRIBUTING.md (3164b), dashboard/index.html (3670b), DISCLAIMER.md (2615b), docs/COBOL_TESTING.md (25660b), docs/EOD_REPORT.md (4827b), docs/GETTING_STARTED_MASSIVE.md (6493b), docs/GLOSSARY.md (9239b), docs/INSTALL_MODELS.md (13278b), docs/MCP_TOOLS_REFERENCE.md (12633b), docs/PHILOSOPHY.md (4892b), docs/references/contract-input.md (1758b), docs/references/contract-output.md (5232b), docs/references/presentation-nl-query-routing.md (13264b), docs/references/presentation-rules.md (3099b), docs/references/runtime-gemma4-consult.md (1557b), docs/references/schema-holdings-fields.md (2103b), docs/STONKMODE_ARCHITECTURE.md (10414b), docs/STONKMODE_AVATAR_LEGEND.md (2014b), docs/WINDOWS_SETUP_GUIDE.md (9567b), install.yaml (6440b), PRIVACY.md (7809b), PUBLISH.md (423b), README.md (18410b), RFC-v0.1.md (25149b), SECURITY.md (4035b), skill-card.md (3005b), SKILL.md (39381b), STONKMODE.md (5820b), tests/test_bundle_atomic_replace.py (6112b), tests/test_bundle_schema.py (6603b), tests/test_key_resolver.py (6198b), tests/test_mcp_server_envelope.py (6557b), tools/cobol_barrage_v4.py (14794b), tools/generate_sbom.py (14984b), _meta.json (131b)\n\nFile v4.7.7:agent-skills/claude-code/SKILL.md\n\n---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Claude Code via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"claude-code\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. It describes the Claude Code marketplace\nplugin that connects to InvestorClaw v4.0 (Apache 2.0). The plugin\nships only this file, INSTALL.md, and a manifest — no Python, no bundle.\n-->\n\n# InvestorClaw — Claude Code Plugin (v4.0)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This plugin is MIT-0-licensed.\n\n## What this is\n\nInvestorClaw is a containerized portfolio analysis service. The user\nruns it locally as two Docker containers via `docker compose up -d`;\nthis Claude Code plugin is the thin client that registers the service's\nMCP servers with your agent and exposes two convenience slash commands.\n\nThe plugin is a manifest + this SKILL.md + a one-time config write\nthat points Claude Code at two HTTP MCP endpoints on localhost. All\nanalysis happens inside the user's Docker containers — the agent\nnever installs or imports anything.\n\nThis is the current Claude Code / Claude Desktop path. The plugin\ninstalls directly from this repo and uses the same skill bundle and\nsame container-first runtime as every other agent. See\n`docs/GETTING_STARTED.md` for the canonical setup.\n\n## Slash commands the plugin exposes\n\nThe plugin registers two slash commands so portfolio questions don't\ndepend on the LLM spontaneously deciding to call MCP tools:\n\n- **`/ask <question>`** — routes to the `investorclaw.portfolio_ask`\n  tool. Pass the user's natural-language portfolio question (e.g.,\n  `/ask what are my top 5 dividend payers?`). The deterministic engine\n  picks the right analyzer and returns a structured `ic_result` plus\n  narrative text.\n\n- **`/refresh`** — routes to `investorclaw.portfolio_refresh`. Pulls\n  fresh market data without re-uploading portfolio files. Use this when\n  the user has been chatting for a while and quotes may be stale.\n\nThese commands are deterministic entry points: the user types the slash\ncommand, Claude Code dispatches it to the named MCP tool, the engine\nreturns structured output. **No LLM routing decision is involved at the\nslash-command boundary.** This is by design — slash commands are\nload-bearing for reliability.\n\n## MCP tools available (after install)\n\nWhen InvestorClaw is running and the plugin is loaded, your tool\ncatalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language question router (also\n  invoked by `/ask`)\n- `investorclaw.portfolio_refresh` — market-data refresh (also invoked\n  by `/refresh`)\n- `investorclaw.portfolio_holdings` — current snapshot of positions,\n  values, weights\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top/bottom\n  performers, max drawdown\n- `investorclaw.portfolio_bonds` — bond analytics (YTM, duration, FRED\n  yield curve)\n- `investorclaw.portfolio_analyst` — analyst ratings per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Sharpe / m...","readmeExcerpt":"Skill: Skill Owner: perlowja Summary: Deterministic-first portfolio analyzer — holdings, performance, Sharpe + Sortino, FRED yield curves, bond duration, sector breakdowns, scenario rebalancing —... Tags: analytics:4.1.35, arm64:4.1.36, dashboard:4.1.36, deterministic:4.1.22, docs:4.1.33, eod:4.1.32, finance:4.1.33, latest:4.10.0, mcp:4.1.22, multi-arch:4.1.36, portfolio:4.1.36, reference:4.1.29, security:4.1.31, sto","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"/plugin marketplace add argonautsystems/InvestorClaw\n/plugin install investorclaw"},{"language":"bash","snippet":"clawhub install investorclaw"},{"language":"bash","snippet":"git clone https://github.com/mnemos-os/mnemos-ic-runtime.git ~/.investorclaw\ncd ~/.investorclaw\nmkdir -p portfolios\ndocker compose up -d"},{"language":"bash","snippet":"clawhub install investorclaw"},{"language":"text","snippet":"hermes (host)\n  │\n  │  config.yaml mcp_servers:\n  │     investorclaw → http://localhost:18090/mcp\n  │     mnemos       → http://localhost:5002/mcp\n  ▼\nDocker compose (~/.investorclaw/compose.yml)\n  ├── argonautsystems/ic-engine:4.7.7-cpu       :8090   portfolio analysis MCP\n  └── mnemos-os/mnemos-rs:4.2       :5002   memory + KG MCP\n       (dashboard at :8092 for portfolio upload + key config)"},{"language":"bash","snippet":"hermes chat -q \"What's in my portfolio?\" \\\n  --provider together -m google/gemma-4-31B-it --yolo\n\nhermes chat -q \"What changed since last week?\" \\\n  --provider together -m google/gemma-4-31B-it --yolo\n\nhermes chat -q \"Refresh my market data and show me the worst\n                performer.\" \\\n  --provider together -m google/gemma-4-31B-it --yolo"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"agent-skills/claude-code/SKILL.md","content":"---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Claude Code via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"claude-code\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. It describes the Claude Code marketplace\nplugin that connects to InvestorClaw v4.0 (Apache 2.0). The plugin\nships only this file, INSTALL.md, and a manifest — no Python, no bundle.\n-->\n\n# InvestorClaw — Claude Code Plugin (v4.0)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This plugin is MIT-0-licensed.\n\n## What this is\n\nInvestorClaw is a containerized portfolio analysis service. The user\nruns it locally as two Docker containers via `docker compose up -d`;\nthis Claude Code plugin is the thin client that registers the service's\nMCP servers with your agent and exposes two convenience slash commands.\n\nThe plugin is a manifest + this SKILL.md + a one-time config write\nthat points Claude Code at two HTTP MCP endpoints on localhost. All\nanalysis happens inside the user's Docker containers — the agent\nnever installs or imports anything.\n\nThis is the current Claude Code / Claude Desktop path. The plugin\ninstalls directly from this repo and uses the same skill bundle and\nsame container-first runtime as every other agent. See\n`docs/GETTING_STARTED.md` for the canonical setup.\n\n## Slash commands the plugin exposes\n\nThe plugin registers two slash commands so portfolio questions don't\ndepend on the LLM spontaneously deciding to call MCP tools:\n\n- **`/ask <question>`** — routes to the `investorclaw.portfolio_ask`\n  tool. Pass the user's natural-language portfolio question (e.g.,\n  `/ask what are my top 5 dividend payers?`). The deterministic engine\n  picks the right analyzer and returns a structured `ic_result` plus\n  narrative text.\n\n- **`/refresh`** — routes to `investorclaw.portfolio_refresh`. Pulls\n  fresh market data without re-uploading portfolio files. Use this when\n  the user has been chatting for a while and quotes may be stale.\n\nThese commands are deterministic entry points: the user types the slash\ncommand, Claude Code dispatches it to the named MCP tool, the engine\nreturns structured output. **No LLM routing decision is involved at the\nslash-command boundary.** This is by design — slash commands are\nload-bearing for reliability.\n\n## MCP tools available (after install)\n\nWhen InvestorClaw is running and the plugin is loaded, your tool\ncatalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language question router (also\n  invoked by `/ask`)\n- `investorclaw.portfolio_refresh` — market-data refresh (also invoked\n  "},{"path":"agent-skills/claude-desktop/SKILL.md","content":"---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Claude Desktop via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"claude-desktop\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. The InvestorClaw service it connects to is\nApache 2.0. See ../../LICENSE-MIT-0 for the full MIT text.\n-->\n\n# InvestorClaw — Claude Desktop Reference\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This reference doc is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## What this is\n\n[InvestorClaw](https://investorclaw.app) is a containerized, deterministic\nportfolio analysis service. It runs on your machine as two Docker\ncontainers (a Rust memory server and a Python analysis engine) and\nexposes its capabilities to Claude Desktop over MCP-HTTP.\n\nClaude Desktop has no plugin system — instead, it connects to MCP servers\ndeclared in `claude_desktop_config.json`. Once you run\n`docker compose up -d` and add two short blocks to that config file\n(see `INSTALL.md`), Claude Desktop gains an entire portfolio-analysis\ntoolkit that you can invoke just by chatting.\n\nThere is no marketplace step. There is no plugin to install. The\nservice is the substrate; Claude Desktop is the interface.\n\n## Tools that become available after install\n\nOnce both MCP servers are wired up and Claude Desktop has been fully\nquit and relaunched, the model gains two new tool namespaces.\n\n### Portfolio analysis (`investorclaw.*`)\n\n| Tool | What it does |\n|---|---|\n| `investorclaw.portfolio_ask` | Natural-language question routed through the deterministic engine |\n| `investorclaw.portfolio_holdings` | Current snapshot of positions, values, and weights |\n| `investorclaw.portfolio_performance` | Sharpe, volatility, top/bottom performers, max drawdown |\n| `investorclaw.portfolio_bonds` | Bond analytics — YTM, duration, FRED yield curve |\n| `investorclaw.portfolio_analyst` | Analyst consensus ratings per holding |\n| `investorclaw.portfolio_news` | News correlation for held positions |\n| `investorclaw.portfolio_lookup` | Ticker / account lookup |\n| `investorclaw.portfolio_optimize` | Modern Portfolio Theory (Sharpe / min-vol) |\n| `investorclaw.portfolio_rebalance` | Current vs. target with tax impact |\n| `investorclaw.portfolio_scenario` | What-if scenarios (rate moves, drawdowns) |\n| `investorclaw.portfolio_cashflow` | Projected dividends and bond coupons |\n| `investorclaw.portfolio_peer` | Peer comparison vs. benchmark |\n| `investorclaw.portfolio_setup` | Auto-discover portfolio files in `/data/portfolios/` |\n| `investorclaw.portfolio_refresh` | Refresh market data without re-uploading"},{"path":"agent-skills/hermes/SKILL.md","content":"---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for Hermes via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"hermes\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed and tailored for the NousResearch Hermes\nAgent (v0.12+). The InvestorClaw service it connects to is Apache 2.0.\nSee LICENSE-MIT-0 in this directory.\n-->\n\n# InvestorClaw — Hermes Skill (v4.0)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This skill file is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## TL;DR for hermes operators\n\nInvestorClaw v4.0 turns hermes into a **first-class portfolio-analysis\nagent**. The service runs as two local Docker containers and exposes\nits capabilities over MCP-HTTP. Hermes 0.12+ registers the MCP servers\nas native function-callable tool sources — the LLM sees\n`investorclaw.portfolio_ask`, `mnemos.search_memories`, and friends in\nthe same tool catalog as `browser_*`, `terminal`, and `skill_view`.\n\n**Headline upgrade — HER-1 is gone.** Read the next section if you\nremember v2.x.\n\n## What changed since v2.x — HER-1 elimination\n\nIf you ran InvestorClaw v2.x against hermes, you hit **HER-1**: the\n\"skill-as-doc-hint\" caveat. In v2.x, InvestorClaw shipped as a hermes\nskill bundle injected into the system prompt. The LLM had to use\nhermes meta-tools (`skill_view`, `terminal`) to *read* the skill\ndocumentation and then *imitate* the analyst commands by shelling out.\nThat indirection layer was lossy and slow, and the Linux baseline\nempirical reliability landed around **8% (2.3/30)** on the standard\nprompt barrage — vs **77%** on zeroclaw, which had real tool\nregistration.\n\n**v4.0 ends that.** There is no skill bundle to inject. The\ndeterministic engine runs as a containerized service and publishes its\nanalytical surface over MCP-HTTP. Hermes 0.12+ registers MCP servers\ndeclaratively in `~/.hermes/config.yaml` and exposes their tools to\nthe LLM directly — same dispatch path as any other built-in tool.\n\nWhat this means in practice for hermes users:\n\n- **No more meta-tool indirection.** The LLM calls\n  `investorclaw.portfolio_ask` directly, not via `skill_view` →\n  `terminal` → fragile shell parsing.\n- **Reliability now matches other agent runtimes.** Expect the same\n  routing accuracy as zeroclaw / openclaw — roughly an order of\n  magnitude better than v2.x on the same prompts.\n- **Memory is built in.** The `mnemos.*` tool family gives hermes a\n  persistent memory layer it never had before, scoped to InvestorClaw\n  observations and user preferences.\n- **No skill bundle to keep in sync.** Bumping the service to a newer\n  ic-engine ver"},{"path":"agent-skills/openclaw/SKILL.md","content":"---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for OpenClaw via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.7.7\",\"runtime\":\"openclaw\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.7.7-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n<!--\nSPDX-License-Identifier: MIT-0\nCopyright 2026 InvestorClaw Contributors\n\nThis SKILL.md is MIT-0-licensed. The InvestorClaw service it connects to\nis Apache 2.0. See the InvestorClaw repository for that license.\n-->\n\n# InvestorClaw — Skill (openclaw runtime)\n\n> Powered by [InvestorClaw](https://investorclaw.app) (Apache 2.0).\n> This skill file is MIT-0-licensed; the underlying service is Apache 2.0.\n\n## What this is\n\nInvestorClaw is a containerized portfolio-analysis service exposed to\nopenclaw as **two MCP-HTTP servers**:\n\n- `investorclaw` — portfolio analysis tools at `http://localhost:18090/mcp`\n- `mnemos` — memory + knowledge graph at `http://localhost:5002/mcp`\n\nBoth run inside a Docker compose stack on the user's machine\n(`docker compose up -d` is the entire service install). openclaw connects\nto them as native MCP servers via its `mcp.servers` config block —\nno plugin manifest, no `dist/index.js`, no npm install, no skill\nbootstrap files.\n\nIf openclaw runs in a container itself, the two MCP URLs reach the host's\nloopback through the compose bridge network or `host.docker.internal`,\ndepending on how the openclaw container is launched. See `INSTALL.md`.\n\n## Tool surface\n\nWhen the service is running, openclaw's tool catalog gains:\n\n### Portfolio analysis (`investorclaw.*`)\n\n- `investorclaw.portfolio_ask` — natural-language portfolio question\n  routed through the deterministic engine\n- `investorclaw.portfolio_holdings` — current snapshot of positions,\n  values, weights\n- `investorclaw.portfolio_performance` — Sharpe, volatility, top/bottom\n  performers, max drawdown\n- `investorclaw.portfolio_bonds` — bond analytics (YTM, duration, FRED\n  yield curve)\n- `investorclaw.portfolio_analyst` — analyst ratings per holding\n- `investorclaw.portfolio_news` — news correlation for held positions\n- `investorclaw.portfolio_lookup` — ticker / account lookup\n- `investorclaw.portfolio_optimize` — Sharpe / min-vol optimization\n- `investorclaw.portfolio_rebalance` — current vs target with tax impact\n- `investorclaw.portfolio_scenario` — what-if scenarios on holdings\n- `investorclaw.portfolio_cashflow` — projected cashflow from bonds\n- `investorclaw.portfolio_peer` — peer comparison vs benchmark\n- `investorclaw.portfolio_setup` — auto-discover portfolio files in\n  `/data/portfolios/`\n- `investorclaw.portfolio_refresh` — refresh market data without\n  re-uploading files\n- `investorclaw.portfolio_guardrails` — view educational-only guardrails\n\n### Memory (`mnemos.*`)\n\n- `mnemos.search_memories` — full-text + "},{"path":"agent-skills/zeroclaw/SKILL.md","content":"---\nname: investorclaw\ndescription: Deterministic-first portfolio analyzer for ZeroClaw via MCP-HTTP at localhost:18090. Holdings, performance, Sharpe + Sortino, FRED yields, bond duration, scenario rebalancing.\nhomepage: https://github.com/argonautsystems/InvestorClaw\nuser-invocable: true\nmetadata: {\"license\":\"MIT-0\",\"version\":\"4.10.0\",\"runtime\":\"zeroclaw\",\"image\":\"ghcr.io/argonautsystems/ic-engine:4.10.0-cpu\",\"mcp-endpoint\":\"http://localhost:18090/mcp\"}\n---\n\n## Authoritative operating contract\n\nThese rules govern any agent using this skill. Examples elsewhere in this file\nare reference only and never override them.\n\n### Data integrity — InvestorClaw is the only source of truth\n- Every price, percent, dollar figure, or market fact an agent states MUST come\n  from an InvestorClaw tool result returned in the SAME turn. InvestorClaw\n  returns HMAC-signed envelopes; that signed data is the only source of truth.\n- Never invent, estimate, guess, or use the model's own training knowledge for\n  any number. If a tool did not return it this turn, do not state it — say\n  \"InvestorClaw returned no data for that\".\n- Tool prose with no concrete numbers = no data; never convert it into a figure.\n\n### Current tool surface (underscore namespace)\n- `investorclaw__portfolio_market_snapshot(symbols?, benchmarks?)` — real-time\n  prices + day-change% for holdings and benchmarks (SPX/NDX/DJI/VIX, BTC/ETH).\n  `symbols` is a COMMA-SEPARATED STRING (e.g. \"NVDA,AAPL\"), not a list. No args =\n  holdings + benchmarks. Use this (not portfolio_ask) for any \"price of X\" and to\n  read the portfolio against the market.\n- `investorclaw__portfolio_performance_window(period=...)` — return / P&L /\n  movers over a window. period: 1d, 1w, 1mo, 1y, 5y, 10y, 20y, max, or natural\n  phrases (\"today\", \"last week\", \"last year\", \"entire history\").\n- `investorclaw__portfolio_ask(question=...)` — analysis / explanation.\n\nOlder `investorclaw.*` dot-namespace examples below are stale; the underscore\nforms above are the current tool names.\n\n## Autonomous / always-on monitoring agents\n\nFor unattended agents (scheduled monitors and alerters — e.g. a MarketWatch\nagent), in addition to the contract above:\n- Drive each run from a tool call first; never answer a market question from\n  memory. A scheduled \"poll\" means call `portfolio_market_snapshot`.\n- Threshold scan: call `portfolio_market_snapshot`, then emit ONE terse line\n  only when a holding or benchmark breaches the configured move (e.g. ±3% a\n  holding, ±10% VIX); otherwise emit a single `NO_ALERT` token and stop.\n- If the required tool errors or returns no data, emit a fixed marker such as\n  `OPS_FAIL market_snapshot unavailable` and stop — never fabricate a reassuring\n  number to fill the gap.\n- No clarifying questions in unattended mode; map intent and act.\n- Periodic / EOD reports: pull `portfolio_performance_window` for the window,\n  then `portfolio_market_snapshot` for index closes; report numbers verbatim.\n- Always read holdings in the co"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2655,"uniquenessScore":37,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T05:12:30.107Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T10:45:01.997Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}