8 Commits

Author SHA1 Message Date
Alex Yang 7d411cbecc feat: refresh upstream integrations and skill content (#85) 2026-08-15 16:17:50 -04:00
Alex Yang f47e703e1d chore: update deps and CI action versions (#83)
- actions/checkout v4 -> v7, actions/setup-node v4 -> v7
- pnpm 11.1.2 -> 11.20.0
- CI node-version 22 -> 24, and engines.node >=22 -> >=24 to match

BREAKING: Node 22 is no longer supported — Node 22 users will get an
engine error on `opencli plugin install`. Node 22 entered maintenance in
Oct 2025; 24 is the current Active LTS.

Docs updated to match, including the tradingview-reader skill (which
installs this repo's plugin, so engines.node — not opencli's own ">= 21"
floor — is the binding constraint) and stale rationales that justified
the old floor ("built-in fetch"/"built-in WebSocket" stabilised in Node
22; Bun 1.0 does not satisfy engines.node >= 24).

The social readers keep ">= 21 (or Bun >= 1.0)" — they install no plugin
from this repo, so opencli's own floor applies.

ccbump@0.2.1 and skill-lint@v3 were already latest; the opencli
">=1.8.0" peer range is a minimum floor, not a pin, and already admits
1.8.6.
2026-08-05 15:52:51 -04:00
Alex Yang 8072082fda feat: add hyperliquid-reader skill + opencli plugin (#76)
* feat: add hyperliquid-reader skill + opencli plugin

Add a read-only Hyperliquid (app.hyperliquid.xyz) reader, mirroring the
tradingview-reader pattern. Unlike TradingView's CDP attach, Hyperliquid
exposes a fully public info API (POST https://api.hyperliquid.xyz/info),
so this needs no API key, wallet, login, or desktop app.

opencli plugin (opencli-plugins/hyperliquid/) — 12 read-only commands:
- Market data: markets, spot-markets, mids, book, candles,
  funding-history, funding-compare (cross-venue HL/Binance/Bybit
  funding-arb screen).
- Account by 0x address: account, positions, spot-balances,
  open-orders, fills.

Skill (plugins/data-providers/skills/hyperliquid-reader/) — SKILL.md
(5-step + error reference), README.md, references/commands.md.

Registrations: root opencli-plugin.json, data-providers plugin.json
(description + keywords), marketplace.json, root README table.

Verification: 31 unit tests pass against captured live wire shapes;
all 12 command data paths smoke-tested end-to-end against the live API.
SKILL.md description is 1019 chars (< 1024 lint cap), no angle brackets.

No trade execution: the plugin exposes no write/exchange endpoints.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

* refactor: scope hyperliquid-reader to market data only

Drop the account-by-address commands (account, positions, spot-balances,
open-orders, fills) and their lib/account.js + lib/orders.js helpers and
tests. Remove the now-unused normalizeAddress helper from lib/api.js.

The reader is now market-data only: markets, spot-markets, mids, book,
candles, funding-history, funding-compare (7 commands). Updated SKILL.md,
both READMEs, references/commands.md, the plugin/marketplace manifests,
and the root README table accordingly.

21 unit tests pass; all 7 market-data data paths re-verified live.
2026-06-07 16:21:26 -07:00
Alex Yang e27857eb60 chore: bump opencli peer dep to >=1.8.0 (#71)
1.8.0 ships reliability fixes that benefit the CDP-attach adapter:
retryable CDP -32000, Page.goto stale-identity self-recovery, and
undici pinned back to 6.x so Node 20 users stay supported.
2026-05-19 13:03:26 -07:00
Alex Yang 7d67321a31 Fix tradingview plugin func signature for browser:false commands (#69)
opencli runtime (1.7.19) calls `cmd.func(kwargs, debug)` for `browser: false`
commands, but every data command in this plugin declared the legacy
two-arg `(_page, args)` form. That made `args` receive `debug` (undefined)
and every ticker / strike / filter argument deserialize to `undefined` —
e.g. `quote --ticker SMTC` failed with `No quote returned for UNDEFINED:UNDEFINED`.

Drop the unused `_page` parameter so the signature matches the runtime
contract for non-browser commands. Affected commands: alerts, chart-state,
launch, news, options-chain, options-expiries, quote, screener, screenshot,
search, watchlists. (status was already correct — takes no args.)

Verified: `opencli tradingview quote --ticker SMTC --exchange NASDAQ` returns
`NASDAQ:SMTC close 139.74` after the fix. Plugin tests (42/42) still pass.
2026-05-13 16:38:53 -07:00
Fallenhh 37b6910c4a Adding opencli plugin acess (#66) 2026-05-12 21:59:31 -07:00
Alex Yang c6c78c03ef Switch skill to the MCP server (#60)
* Add MCP support to ; keep REST as raw-data fallback

exposes two surfaces backed by the same data:
- MCP server at https:///api/mcp — single agent_chat tool for
  analyst-grade research synthesis (DCF, sector deep-dives, transcript
  digestion, etc.). OAuth via `claude mcp add`, no API key.
- REST API at https://api./v1 — 60+ endpoints for raw structured
  data. Bearer auth.

The skill now routes by intent: prefer MCP for synthesis/analysis
questions, fall back to REST for raw data the MCP declines (real-time
quotes, intraday candles, raw options chains, single line items, bulk
downloads, AI-company hiring signals).

Structure:
- Step 1 — decide surface (MCP vs REST)
- Step 2 — MCP flow (verify, frame, call), with budget-awareness and
  multi-turn guidance
- Step 3 — REST flow (key resolution, endpoint table, curl)
- Step 4 — shared response formatting

Other fixes:
- MCP-detection grep was `^[[:space:]]` but `claude mcp list`
  outputs `:` (colon, not whitespace) — fixed to `^:`.
- Conversation URL was `agent-chat/<id>` but the route reads `c` from
  query params (chat-v2-layout.tsx) — fixed to `agent-chat?c=<id>`.
- Subscription_required (403) note moved from Step 1 (registration) to
  Step 2c (tool call) where the error actually fires.

Adds research-topics.md reference for the MCP path; keeps the 11
existing REST endpoint references in place.

* Fix date-bound test in tradingview summarizeExpiries

`summarizeExpiries` called `daysToExpiry(expiry)` without forwarding the
caller's `now` reference, so the function used wall-clock time. The
matching test pinned `NOW = 2026-05-10` and asserted `dte === 12` for an
expiry of 2026-05-22 — passed on 2026-05-10, started failing on
2026-05-11 as the calendar advanced. Caught by CI on PR #60 today.

Forward `now` through to `daysToExpiry` (which already supports the
optional second arg) and pass `NOW` from the test. Same pattern the rest
of the file already uses for `normalizeChainRow(..., NOW)` and the
`daysToExpiry — future / past` tests.

42/42 tradingview tests pass locally and on any future date.
2026-05-12 21:14:38 -07:00
Alex Yang 2728886d93 Add tradingview-reader skill (#62)
* Add tradingview-reader skill

Read-only skill for the TradingView desktop macOS app via opencli + the
opencli-plugin-tradingview plugin. Exposes spot quotes, full options chains
with greeks/IV, expiries, chart state, and screenshots — all by attaching
to a logged-in TradingView.app over Chrome DevTools Protocol (no API key).

The plugin lives in a separate repo (himself65/opencli-plugin-tradingview)
and must be installed before this skill is functional.

* Add tradingview opencli plugin under opencli-plugins/ monorepo

Scaffolds the actual TradingView adapter the tradingview-reader skill
depends on, inside this repo via opencli's monorepo subpath syntax.
Install path becomes:

  opencli plugin install github:himself65/finance-skills/tradingview

What's in opencli-plugins/tradingview/:
- 7 commands (launch, status, quote, options-chain, options-expiries,
  chart-state, screenshot) following opencli's cli({...}) registry API
- lib/scanner.js + lib/symbols.js — POST helpers, {fields,symbols}
  decoder, OPRA parser, ATM-band slicer
- 15 node:test units covering the pure helpers, all passing

Top-level opencli-plugin.json declares the monorepo. CLAUDE.md gets a
new "opencli plugins" section explaining the layout, install path, and
authoring flow. Skill SKILL.md/README.md/commands.md updated to use the
new monorepo install command.

The Node port of the data-path logic follows the spec from the original
PoC handoff but has not been smoke-tested against a live TradingView.app
yet — needs PoC verification before users rely on it. Lib unit tests
pass; integration (CDP attach + scanner replay) is unverified.

* Add 5 Tier-1 tradingview commands: screener, search, news, watchlists, alerts

Expands the plugin from 7 → 12 commands, covering the highest-value
research surface beyond options chains and chart state.

New commands:
- screener: generic stock/crypto/forex/futures/bond screener via
  scanner.tradingview.com/{market}/scan2 — supports the full scan2
  grammar (timeframe-suffixed columns, filter clauses, sort, pagination).
  ~70 country codes + cross-class markets. The same backend powers all of
  TradingView's movers, heatmaps, and screener pages.
- search: symbol/instrument autocomplete via symbol-search/v3 — useful
  before any other command when the ticker is ambiguous.
- news: /v2/headlines list mode + /v2/story detail mode (--id <story-id>).
  Filterable by symbol, category, area, section, provider. Story body
  flattened from TradingView's AST to plain text.
- watchlists: read-only access to user's custom watchlists (all, by id,
  or by colored flag). Write endpoints (append/replace) intentionally
  not exposed.
- alerts: read-only access to pricealerts.tradingview.com — list, active,
  triggered, offline-fires, and full log. Write endpoints
  (create/edit/remove) intentionally not exposed.

lib/scanner.js: buildScreenerBody() builder with proper limit clamping
(1..500), filter/filter2 passthrough, explicit-tickers mode, and offset.
scannerFetch() now accepts an optional labelProduct (defaults to
symbols-options for backward compat).

lib/news.js: new module — buildHeadlinesUrl, buildStoryUrl,
normalizeHeadline, astToText (recursive AST walker handling p/h*/list/br/
text nodes), epochToIso (auto seconds-vs-ms detection).

Tests: 18 new node:test units covering AST flattening, headline
normalization, screener body builder. Total now 33/33 passing.

Skill docs (SKILL.md + references/commands.md) updated with the new
commands' tables, output schemas, key rules, presentation guidance, and
detailed reference sections per command. Plugin README updated to list
the new commands and tests in the layout tree.

All commands remain unverified against a live TradingView.app — pure
helpers (lib/) are unit-tested but the wire shapes (response field
names, especially for /list_alerts and /api/v1/symbols_list/all/) follow
community-documented conventions and may need adjustment after first
PoC run.

* Fix tradingview-reader skill-lint failures

skill-lint v2 enforces:
- description ≤ 1024 chars (was 1070)
- no angle brackets in description (had "RSI < 30" in a trigger phrase)

Trim trigger list and replace the "<" example with "oversold stocks".
Now 987 chars, no angle brackets.

* Add CI workflow for opencli plugin unit tests

New workflow walks opencli-plugins/*/ and runs `npm test` for each
plugin that has a package.json and tests/*.test.js. Currently exercises
the 33 pure-helper tests under opencli-plugins/tradingview/.

Coverage scope (intentional):
-  Pure data-transformation helpers: parsers, decoders, normalizers,
     URL builders, AST walkers
-  cli({...}) registration, page.evaluate, real network responses,
     CDP attach — those need PoC verification against a live desktop app

CLAUDE.md CI section updated to document the new workflow and call out
that wire-level integration is out of test scope.

* Fix tradingview plugin: cookies-from-CDP path, working live against MU

The previous architecture (Strategy.UI + page.evaluate(fetch)) does not
work — browser CORS preflight rejects cross-origin POSTs from any
tradingview.com page to scanner.tradingview.com, even from the
options-chain page itself. Verified by direct CDP test on every TV tab.

How TradingView's own pages get around this: their Electron main process
makes the requests via Node's network stack, bypassing browser CORS.
This commit replicates that path:

  1. Connect to CDP /json/version
  2. Open browser-level WebSocket
  3. Storage.getCookies → harvest .tradingview.com cookies
  4. fetch() from Node directly with Cookie header

Smoke-tested live against MU on TradingView desktop:
  quote → $746.81 (+15.49%)
  options-chain → 7,426 contracts; ATM band on 2026-05-15 returns 10 rows
  news --symbol NASDAQ:MU → 200 headlines, top "Chip-Stock Juggernaut..."
  options-expiries → 22 expiries
  screener (top mcap) → NVDA $5.23T, GOOGL $4.84T, AAPL $4.31T, MSFT $3.08T
  search Micron → NASDAQ:MU
  watchlists → 4 lists with section markers
  alerts → KORU cross_down (read-only)
  chart-state → layout 5DjR42GB, symbol EWY
  screenshot → 350KB PNG

What changed:

- New lib/cookies.js: CDP Storage.getCookies harvest + tradingViewFetch
  helper. Caches cookie header per process. Uses Node 22's built-in
  WebSocket (no `ws` dep).
- New lib/cdp.js: CDP tab finder, Runtime.evaluate, Page.captureScreenshot.
  Eliminates the apps.yaml registration requirement — plugin works with
  zero opencli config beyond install.
- lib/scanner.js: scannerFetch signature dropped `page`; uses
  tradingViewFetch. buildChainBody rewritten to use the live wire shape
  (index_filters: [{name:'underlying_symbol', values:[...]}] + filter2
  boolean composition + ignore_unknown_fields). The prior {markets,
  filter, range} shape returns HTTP 400.
- lib/news.js: added fetchHeadlines() and fetchStory() routed via
  tradingViewFetch.
- 8 data commands (quote, options-chain, options-expiries, screener,
  search, news, alerts, watchlists): converted from Strategy.UI +
  browser:true to Strategy.PUBLIC + browser:false. No more `domain`
  field, no `page` arg in func.
- chart-state and screenshot: also Strategy.PUBLIC now, using lib/cdp.js
  helpers directly. Multi-selector cascade for chart-state symbol detection.
- alerts.js normalizeAlerts: response key is `r` (live shape:
  {s:"ok", r:[...]}), with fallbacks. Symbol parsing extracts ticker
  from JSON-encoded resolution blobs.
- options-chain + options-expiries: added --include-expired flag,
  default false (filters out DTE < 0).

Tests: +12 cases (cookies endpoint resolution, alerts normalizer with
live `r:[]` shape, buildChainBody wire-shape regression, buildQuoteBody).
42/42 passing.

Engines: Node ≥22 required (built-in WebSocket).

Setup is now: `opencli plugin install ...` + `opencli tradingview launch`.
No apps.yaml, no Browser Bridge, no other config.

* Fix CI: move alerts normalizer to lib/ so tests don't load opencli

CI exit 1 — tests/alerts.test.js was importing normalizeAlerts from
../alerts.js, which loaded the cli({...}) registration and pulled in
@jackwener/opencli. CI doesn't install opencli before running plugin
tests (and doesn't need to), so the import failed.

Move normalizeAlerts (+ its private helpers) to lib/alerts.js. The
command file now imports from there. Test imports from ./lib/alerts.js
so it never touches opencli.

Verified: `grep -E "^import.*@jackwener" lib/ tests/` is empty. 42/42
passing locally; CI should now match.
2026-05-10 02:37:02 -07:00