/SKILL.md
Finds every tradeable thesis in a source and routes each to an executable trade. Works with tweets, podcasts, articles, screenshots, hunches, and market observations. Also answers questions about existing trades on paste.trade -- who's bullish/bearish, what's performing, what others are trading. Use when the user says "/trade", "trade this", "what's the trade", pastes a source and wants the trade, states a directional belief, or asks about market positions and trades on paste.trade. Stay dormant for generic market chat.
npx skillsauth add rohunvora/paste-trade-skill tradeInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Think through trades live. The user is watching the work, not just the final card. Narrate what changed your mind, what has no clean expression, and why one instrument beats another.
Supporting docs: skill/references/ (skill index, ASCII map, CLI cheatsheet, routing decision rules, event types, trade data index, Hyperliquid thematic universe, prediction markets, search API).
When the user is thinking through a trade idea -- not pasting a URL -- query paste.trade for context first:
curl -s -H "Authorization: Bearer $PASTE_TRADE_KEY" "https://paste.trade/api/search?ticker=GOLD&limit=5"
See skill/references/search-api.md for all query modes, response shape, and how to present results.
If the query returns 0 results, suggest the user add data -- every gap is a contribution prompt. "Nobody's tracking AAPL on paste.trade yet. Want to be the first?"
If the input is exactly "update": pull the latest version of the skill repo, show what changed, and stop.
git -C <repo_root> pull origin main.git -C <repo_root> log --oneline -5 to show recent changes.If the input contains a paste.trade/s/ URL plus a thesis or trade idea: load references/add-to-source.md and follow that flow. Do not run the normal extraction pipeline.
Expressions, not advice. Do your own research.Running /trade now. I will send a live link shortly.On it. Pulling transcript now. Longer videos can take a few minutes.create-source.ts, send Watch live: {source_url} immediately unless your runtime already delivers it./trade run.Before running any script, verify bun is available (command -v bun). If missing, install it: curl -fsSL https://bun.sh/install | bash, then restart the shell.
Run before every /trade:
bun run skill/scripts/onboard.ts
# Returns: { status, env_path, keys, handle?, profile_url? }
If status is "ready", continue to §3.
If status is "onboarding":
status: "missing", share the hint text.install_command, offer to run it (e.g., "Want me to install yt-dlp?").KEY=value to the env_path from onboard output. Confirm what was saved and where. Never echo the full key value back in chat.onboard.ts after saving to verify the key is detected./trade input.If status is "failed", stop and show the error. Do not proceed without a working PASTE_TRADE_KEY.
quotes[]. Choose headline_quote as the sharpest exact substring of the user's words. If it's <120 characters, can include whole thing. Put the cleaned interpretation in thesis.paste.trade/s/:id or paste.trade/t/:id, treat as normal source input.Primary extraction:
bun run skill/scripts/extract.ts "URL"
# Returns: { source, word_count, saved_to, title?, published_at?, channel_handle?, description?, duration_seconds?, image_files? }
# YouTube: transcript omitted from output; read the file at saved_to.
# Tweet images: downloaded to local files listed in image_files[]. Read them for visual context.
Create the source page as soon as you know the source metadata:
bun run skill/scripts/create-source.ts '{ "url": "...", "title": "...", "platform": "...", "author_handle": "...", "author_avatar_url": "...", "source_date": "...", "source_images": [...], "body_text": "...", "word_count": N, "duration_seconds": N, "speakers_count": N }'
# Returns: { source_id, source_url, status: "processing", run_id }
extract.ts.image_files are present in the output, read them now. Charts, screenshots, and diagrams are critical source context — use them to inform thesis extraction, ticker identification, and derivation reasoning. Describe what you see.GEMINI_API_KEY is missing: ask the user now — before creating the source. Offer to paste a key or continue without speaker attribution.create-source.ts. Send the Watch live link immediately unless your runtime handles delivery, then continue the pipeline in the same run. Do not stop or wait for user input. (See §2 Chat UX.)saved_to file before this point.author_handle here means the source publisher/channel handle.channel_handle, not a guest speaker.author_avatar_url is the author's profile picture URL from extract output. Always include it — the source page and feed cards display it immediately.body_text is the full original source text (e.g., the complete tweet, article body). Always include it — the source page displays it verbatim.word_count, duration_seconds, speakers_count are optional extraction metadata for the live stats bar.run_id and thread it through every later adapter call for this source run.run_id=...), pass that value as run_id in the create-source.ts payload.Status update payload shape:
bun run skill/scripts/status.ts <source_id> '{ "event_type": "status", "data": { "message": "..." } }'
Runs after the source page exists and the user has a live link. Runs before thesis extraction.
author_handle, source_date, title.source_date missing: scan text for date indicators, web search, or "now" as last resort. For user-typed theses, always use "now". Scripts resolve it to actual current time. Never guess a time like noon UTC.→ Read skill/references/dense.md for diarization, speaker identity, and transcript handling. Sparse sources skip to §6.
ensureAuthor + enqueueAssetJob.Push enriched metadata:
If enrichment resolved new metadata (author handle, source date, speakers, or thumbnail), push it now so the source page updates before thesis extraction:
bun run skill/scripts/update-source.ts <source_id> --run-id <run_id> '{ "author_handle": "...", "source_date": "...", "thumbnail_url": "...", "speakers": [...] }'
Read the canonical source artifact and find every tradeable thesis.
A thesis is a directional belief about what changes and what that means for price.
skill/references/dense.md for three-pass extraction, thesis map, parallelization, and chunking.skill/references/sparse.md. Handles extraction through routing (§6-§9). Resume at §10 Post.Both paths use the thesis schema and save commands below.
{
"thesis": "author's directional belief in one sentence, in your words not theirs",
"horizon": "author's timing language, if any",
"route_status": "unrouted",
"unrouted_reason": "pending_route_check",
"who": [
{ "ticker": "NVDA", "direction": "long" },
{ "ticker": "AI infrastructure companies", "direction": "long" }
],
"why": ["reasoning step from author", { "text": "researched fact", "url": "...", "origin": "research" }],
"quotes": ["exact words from source that anchor the thesis"],
"headline_quote": "the single best card-ready exact quote or exact substring from quotes[]. Choose the sharpest self-contained claim. Must read cleanly out of context, avoid dangling setup, target <=100 chars when possible, hard cap 120. Frozen at extraction. post.ts validates exact match or exact substring.",
"source_date": "ISO 8601 datetime with time (e.g. 2026-03-10T14:30:00Z), or \"now\" for user-typed theses. Scripts resolve \"now\" to actual current time. Date-only resolves to midnight UTC → wrong price.",
}
who captures 1-3 trade ideas per thesis. These are starting points for routing, not final selections. Can range from specific tickers to broad descriptions. During routing, who is overwritten with the final selected expression.
A thesis is one belief. If the same belief could be traded through different instruments, those are who entries, not separate theses.
Include the most direct expression of the thesis alongside any specific ticker names.
For unresolved candidates, do not drop them. Save them as:
{
"thesis": "...",
"route_status": "unrouted",
"unrouted_reason": "no clean liquid instrument / weak directional expression / evidence gap",
"who": [],
"why": ["..."],
"quotes": ["..."],
"headline_quote": "..."
}
Save all theses from extraction in one batch call (pass --total on first save if using individual saves instead):
# Preferred: batch save all theses at once:
echo '[{...}, {...}]' | bun run skill/scripts/batch-save.ts --run-id <run_id> --total 5
# Returns: [{ id, index }, ...]
# Individual save (when extracting one at a time):
bun run skill/scripts/save.ts --run-id <run_id> --total 5 '<thesis JSON>'
# Returns: { id, file, count }
# Update a saved thesis (used during routing):
echo '<partial JSON>' | bun run skill/scripts/save.ts --run-id <run_id> --update <id>
Track the returned thesis IDs. You need every one for finalization.
Before starting research, narrate the transition so the live page stays active:
bun run skill/scripts/stream-thought.ts --run-id <run_id> "Researching market context..."
Save and post return {"ok": false, "error": "..."} on validation errors (exit 0),
so parallel calls are safe -- one failure does not cancel siblings. Always check the
ok field (or presence of error) in tool output before proceeding.
Do not use routing difficulty as a filter at extraction time. Capture first, then route or explicitly mark unrouted.
Sparse sources: §7-§9 are handled in skill/references/sparse.md. Skip to §10.
For each thesis, determine the best executable expression on supported venues. On adapter error, retry the failed step once. If it fails again, try an alternative ticker or skip the thesis.
Supported venues:
who. Your training data is stale for
tickers and listings. Search to find what's actually available.
Cite findings in why as { "text": "...", "url": "...", "origin": "research" }.skill/scripts/discover.ts --query "<keywords>"):
search available instruments across all venues (Hyperliquid + Polymarket) using
terms from who. Works best with single concrete terms, not multi-word abstractions.
Use --catalog for a full listing of non-crypto HL instruments.
For HIP-3/non-crypto results, prefer entries whose reference_symbols and
routing_note show the same ETF, benchmark, commodity, or private company
the thesis is really about.skill/scripts/source-excerpt.ts --run-id <run_id> --file <saved_to> --query "<thesis keywords>"):
retrieve surrounding context from the original source for this thesis.
After extraction splits a source into theses, adjacent details get lost.
Use this to find what the author said around each claim: qualifications,
supporting numbers, competitive landscape, or nuance that strengthens
the derivation. Also use --around "<exact quote>" to expand a specific quote.skill/scripts/route.ts): validate the best candidates
from both sources against supported venues and get pricing. Takes ticker symbols only.who are starting context, not decisions.
Routing may confirm them, improve on them, or find something better entirely.
Prefer sector-level instruments over single equities for broad theses.
Persist via save.ts --update.discover.ts --query "<theme>" to check. See skill/references/hl-universe.md.discover.ts --query "<event keywords>" to check.
See skill/references/prediction-markets.md.
If discover.ts returns zero PM results for a thesis, do not route to Polymarket.direct: original author would recognize this as their trade.derived: author did not name it, but market link is immediate and defensible.{
"route_status": "routed",
"who": [{ "ticker": "SMR", "direction": "short" }],
"route_evidence": {
"subjects": [{ "label": "NuScale Power", "subject_kind": "company" }],
"direct_checks": [
{
"subject_label": "NuScale Power",
"ticker_tested": "SMR",
"executable": true,
"shares_available": true,
"author_price": 12.54
}
],
"selected_expression": {
"ticker": "SMR",
"direction": "short",
"instrument": "shares",
"platform": "robinhood",
"trade_type": "direct",
"author_price": 12.54
}
}
}
Mapping rule from route output:
route.selected_expression.routed_ticker -> route_evidence.selected_expression.tickerinstrument/platform strings exactly as returned (shares/perps, robinhood/hyperliquid)fallback_reason_tag (and fallback_reason_text when direct executable exists)These fields cross-reference each other. save.ts validates consistency:
every subjects[].label needs a matching direct_checks[].subject_label,
and the selected ticker must appear in who. Include updated who,
route_evidence, and derivation in the same --update call.
Build a derivation chain for every routed trade:
{
"explanation": "1-2 sentences that explain the trade in plain English. No filler, no em dashes.",
"segments": [
{ "quote": "verbatim source quote", "speaker": "speaker name", "speaker_handle": "@handle", "timestamp": "14:22", "source_url": "https://..." }
],
"steps": [
{ "text": "observation grounded in source", "segment": 0 },
{ "text": "researched fact or confirming evidence", "url": "https://..." },
{ "text": "trade conclusion or implication" }
]
}
Write an explanation for every routed trade. Lead with the sharp insight and explain the reasoning in 1-2 sentences. No jargon.
Prefer exactly 3 steps. Each step must advance the chain, no filler. Max 70 chars per step — write like a headline, not a sentence. Cut dates, parentheticals, and asides. No em dashes. No jargon.
Steps should earn the conclusion, not summarize it. If the author named the
ticker, the chain can be short. If routing required a leap, earn it. When a
step depends on external research or a factual check, cite it with numbered
inline citations in Markdown: [1](url), [2](url). Include timestamps when
available.
segment = sourced from quote, has url = backed by research, has neither = agent inference[1](url), [2](url); treat this as part of the format, not decorationurl on a step is a fallback when numbered inline linking does not fitspeaker: "user"timestamp (MM:SS or H:MM:SS from diarized transcript) and source_url (the video URL). These power click-to-seek on the source page. Resolve speaker X handles when it materially helps attribution.timestamp and source_url can be omitted (no timestamp concept for tweets)After writing derivation, rewrite each step into a chain_steps_card array on the trade body. These are the steps shown on the share card — a completely separate field from derivation.steps.
Take each derivation step and compress it: strip citations, URLs, dates, parentheticals, ticker context. Keep only the core claim. Max 60 chars per step. Exactly 3 steps. No jargon. No em dashes. Write like a headline a friend can understand.
discover.ts --query "TICKER" to check for an HL perp on the same underlying. Route the HL perp, not the ETF.bun run skill/scripts/route.ts --run-id <run_id> --thesis-id <id> TICKER direction --source-date "ISO-8601-datetime-or-YYYY-MM-DD" --horizon "timing"
# Returns: { tool: "route", route: { ticker, direction, executable, selected_expression, alternatives, price_context, candidate_routes, note }, diagnostics }
# selected_expression and candidate_routes include HIP-3 routing metadata (see routing.md).
# price_context: { current_price, source_date, author_price }
# If perps route selected and routed_ticker is provided, post that routed_ticker as ticker.
Use tool numbers directly. Do not estimate or recompute.
After routing completes for a thesis, persist everything in one update: who (updated to final ticker), route_status, route_evidence, and derivation together:
echo '<JSON with who + route_evidence + derivation>' | bun run skill/scripts/save.ts --run-id <run_id> --update <id>
This emits thesis_routed (or thesis_dropped) events automatically, updating the live source page with derivation data as each thesis resolves.
Post each trade:
echo '<JSON payload>' | bun run skill/scripts/post.ts --run-id <run_id>
headline_quote must match one saved quotes[] entry or be an exact substring of one.ticker, direction, instrument, platform, and trade_type must match route_evidence.selected_expression.author_price from route price_context whenever present.post.ts will attempt baseline enrichment via /api/skill/assess if author_price is missing, but treat that as fallback not primary path.After all trade POSTs succeed, finalize the source explicitly:
echo '{ "source_id": "...", "source_theses": [...], "source_summary": "...", "message": "All trades posted" }' | bun run skill/scripts/finalize-source.ts --run-id <run_id>
source_id: source page being completedsource_theses: all extracted theses, routed and unroutedsource_theses entry must carry thesis_id (or id) from save.tssource_theses entry must include non-empty whosource_theses entry must include non-empty unrouted_reasonsource_theses (no drops, no duplicates)source_summary: one-line summary of the whole source, especially important for grouped sources like timelinesmessage: optional completion messageDo not rely on a trade POST to resolve the live source page.
| Field | Notes |
|-------|-------|
| ticker | Use routed_ticker value from route output. Post as ticker, not as routed_ticker |
| direction | "long" or "short" |
| author_price | Price at author's publish date. Use route price_context.author_price |
| thesis | Thesis text |
| headline_quote | Must match one saved quotes[] entry or be an exact substring of one, and be <=120 chars |
| ticker_context | 1-3 sentences that explain the instrument to someone who doesn't know what it is. No jargon. |
| author_handle | Speaker/author whose quote anchors this trade; user thesis -> current authenticated user handle |
| author_platform | "youtube", "x", "substack", "podcast", "pdf", "direct", etc. |
| source_url | string or null |
| author_date | ISO 8601 — when the author said it |
| trade_type | "direct" or "derived" |
| instrument | "shares" or "perps" |
| platform | "robinhood" or "hyperliquid" |
| thesis_id | ID from save.ts |
| derivation | { explanation, segments, steps } where explanation is the 1-2 sentence summary and steps are the main chain. |
source_title: title/headline when the source has onesource_images: image URLs extracted from the sourceFinalization-only fields:
source_theses: all theses from this source, passed to finalize-source.tssource_summary: one-line source summary, passed to finalize-source.tsUseful optional trade_data fields:
horizonalt_venuesavatar_urlFor Polymarket trades, also include:
outcome: "yes" or "no" — canonical field for which token was boughtpm_side: "yes" or "no" — legacy compatibility alias for outcomepm_yes_no_price: raw YES price in the 0-1 rangeauthor_daterun_id explicit throughout the run. Do not rely on implicit context lookup.When done, reply in one block.
When 3+ trades come from one source, open with 1-2 sentences framing the portfolio logic, then map them:
[N] trades from @[handle]'s [source type]:
"headline quote" -> TICKER direction
"headline quote" -> TICKER direction
...
-> Reply to dig deeper
If both direct and derived trades exist, show direct first.
Do not include trade card URLs (paste.trade/t/...) in the reply — they are already linked from the live board. Only include the live board URL (paste.trade/s/...) if it hasn't been shared yet.
If posting fails: Board unavailable. Skipping post.
tools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.