From lurii-cc
Produce a ranked, sourced quantitative portfolio report. Reads `memory/` for all user-specific values (tickers, currencies, platforms, thresholds, language). Hands off memory writes to `memory-curator`. Use when the user says "analyze my portfolio", "rebalance", "investment recommendations", "what should I buy", "monthly report", or invokes /portfolio-advisor.
How this skill is triggered — by the user, by Claude, or both
Slash command
/lurii-cc:portfolio-advisorThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Mechanism only. Every user-specific value comes from `memory/` frontmatter — never hardcode tickers, currencies, platforms, thresholds, or language. **Read memory first. Honor it. Halt loud on missing fields.**
Mechanism only. Every user-specific value comes from memory/ frontmatter — never hardcode tickers, currencies, platforms, thresholds, or language. Read memory first. Honor it. Halt loud on missing fields.
get_transactions with a date filter for claims about recent activity.patterns.md data_quirks. Apply each quirk's rule field. Common pattern: trust get_allocation by:source over get_yield_positions.profile.md buffers[].amount_usd before computing deployable capital.pfm refresh is the user's call.memory/ directly. All memory writes route through memory-curator in Step 9 with a handoff payload.Style: numbers not adjectives ("+$340, +1.8 pp" not "meaningful increase"); cite every external claim; output in patterns.output_language with tickers/acronyms in ticker_language.
Before doing anything else, ask the user once via AskUserQuestion whether to update the manual cash balance. Stale cash skews every gap-analysis number downstream, but most runs do not need it — keep the prompt cheap and default to skip.
Single AskUserQuestion call. Question: Update cash balance before running the report? Options:
skip — proceed with current cash from the DB. (Default suggestion.)update now — invoke the cash-update skill via the Skill tool, wait for it to return, then continue with Step 1.cancel — exit cleanly, no report.Branches:
skip → continue.update now → call Skill(skill="cash-update"). After it returns (success, cancel, or halt), continue with Step 1 — do not re-prompt. If cash-update halted because the cash source is missing or ambiguous, surface its halt message verbatim and stop the advisor too.cancel → stop. No memory read, no MCP calls, no report.Read all five files in parallel. Parse each YAML frontmatter block. Required fields:
profile.md: base_currency, foreign_currencies, buffers, portfolio_size_usd_range, rebalance_cadencetargets.md: targets, gap_thresholds, priority_orderplatforms.md: stablecoin_yield_venues, blockedpatterns.md: output_language, report_path_template, research_windows, recommendation_buckets, clarification_triggers, data_quirks, principleson-horizon.md: itemsIf any required field is missing or null, halt with this exact message format and stop:
Memory schema incomplete. Missing:
<file>:<field>,<file>:<field>. Run/memory-update(memory-curator) to fill, then re-invoke /portfolio-advisor.
Do not default. Do not invent. Halt.
After validation, hold the parsed frontmatter in working memory. Also read the most recent prior report at <patterns.report_path_template with date=*> — pick the file with the largest date suffix — for the diff section (Step 7b).
Run in parallel:
mcp__lurii-finance__get_portfolio_summarymcp__lurii-finance__get_allocation with by: assetmcp__lurii-finance__get_allocation with by: sourcemcp__lurii-finance__get_allocation with by: categorymcp__lurii-finance__get_yield_positionsmcp__lurii-finance__get_currency_exposuremcp__lurii-finance__get_risk_metricsmcp__lurii-finance__get_pnlmcp__lurii-finance__get_transactions (last 30 days)Skip get_snapshots unless explicit multi-month trend is needed (500-record truncation per data_quirks.snapshot_truncate_500).
For each entry in targets.targets[], compute current vs target:
asset against get_allocation by:asset. Report current_pct, gap_pp = weight_pct - current_pct, and $ shortfall at current price.direction: increase and gap_pp > 0 → flag for deployment.direction: trim and gap_pp < 0 → flag for trimming.Apply targets.gap_thresholds:
profile.foreign_currencies, compute its share of total. If any exceeds gap_thresholds.idle_cash_pct (excluding buffers), flag.gap_thresholds.single_holding_max_pct is set and exceeded, flag.gap_thresholds.hhi_warn is set and exceeded, flag.platforms.yield_venues[].custodial_risk == high, sum its share. If exceeds gap_thresholds.custodial_concentration_pct, flag.Apply targets.overlap_groups[]:
tickers[]. Note non-zero positions outside consolidation_target as candidates for the consolidation plan in on-horizon.md (do not fabricate sells — defer to horizon items).Yield rates: per platforms.stablecoin_yield_venues, list current APY by asset. Rank. Flag rotation candidates if Δ APY ≥ 2 pp between any two accessible venues.
Use WebSearch; pull full content with WebFetch when snippets are insufficient. Aim for 3+ independent sources per theme; vary query phrasing.
For each key in patterns.research_windows, run searches across the listed keywords[] over days lookback:
macro, equities, crypto, fx, yield are the canonical buckets — but iterate whatever keys the memory file declares.equities.keywords containing top-5 holdings, resolve to actual top-5 from get_allocation by:asset and search per ticker.fx.keywords containing pairs (e.g. <ccy>/<base> — actual pairs come from memory), iterate; if profile.foreign_currencies includes a currency without a listed pair, add <ccy>/<base_currency> to the search set.yield.keywords, run a spot check on each platforms.stablecoin_yield_venues venue's current rate vs the DB.Store every source URL with its section.
After Step 5, walk through patterns.clarification_triggers[]. For each triggered condition, queue a question. Batch all questions into a single AskUserQuestion call. If no triggers fire, skip silently.
Standard triggers (driven by memory, not hardcoded here):
description is the user-facing wording (translate to output_language if needed).horizon_decision_pending: enumerate items from on-horizon.items[] where decision_pending: true. Ask one question per such item, batched in the same call.Use the answers to:
Build recs grouped by patterns.recommendation_buckets[], ordered by priority. For each bucket:
platforms.blocked[]), source link(s).Bucket-resolution hints (driven by memory, not hardcoded):
foreign_cash_deployment: deploy idle foreign-currency cash toward the largest open direction: increase target gaps in priority order (targets.priority_order).pending_sells: source from on-horizon.items[] with executable next-steps and from targets.overlap_groups[] non-canonical positions.stablecoin_rotation: across platforms.stablecoin_yield_venues, recommend moves with Δ APY ≥ 2 pp; cite venue lockup_days.opportunistic_stocks: 1–2 picks if Step 5 surfaces a clear thesis. Skip otherwise.risk_adjustments: triggered by Step 4 flags (custodial concentration, single-holding cap, HHI).Compare to the most recent prior report. Include the diff section only if at least one of: allocation shift > 1 pp in any asset or category; position opened or zeroed; a prior rec executed (detected via transactions). Otherwise omit.
Write the report to the path resolved from patterns.report_path_template with {date} = today (YYYY-MM-DD). Create parent dirs if missing.
Render the markdown report per references/report-template.md (full section order + headings template). Translate headings to output_language; keep tickers/platforms in ticker_language.
If patterns.report_artifact_format is cowork, also render an HTML version. Start from references/report-template.html — copy the file, then replace every {{PLACEHOLDER}} with computed values per the comments in the file. The styling (CSS, colors, classes) is fixed and identical across reports — visual consistency is part of the contract. Drop optional blocks (corrections, gap-card, lockdown banner, anomaly-note, drift section, T-bill card) when not applicable per the rules in cowork-html-style.md. Do NOT redesign the visual or change CSS class names; if data needs a presentation that doesn't fit the existing classes, prefer text inside an existing card over inventing new structure.
After writing the report:
Branch on patterns.report_artifact_format:
cowork — render the HTML artifact per references/report-template.html (CSS catalog + section schema in references/cowork-html-style.md) and call mcp__cowork__create_artifact (or update_artifact on id collision).inline — return the markdown directly in chat.none — skip artifact rendering.Return to chat: one-paragraph summary in output_language + path to the new report file.
Hand off to memory-curator via the Skill tool with a handoff brief covering:
get_transactions since the prior report — which prior-report recommendations are now done, with $ amounts and dates.Memory-curator owns all Edit calls, confirmation prompts, and CHANGELOG entries.
profile.buffers[].amount_usd from deployable capital.platforms.blocked[]. Filter every rec target against this list.data_quirks rules — typically get_allocation by:source is canonical.output_language. Tickers, platform names, acronyms (FX, DTE, IV, HHI, APY), and code stay as-is.memory/ files from inside the advisor. Even small fixes route through memory-curator in Step 9.npx claudepluginhub chizhovyui/lurii-cc --plugin lurii-ccCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.