@vike-io/cli 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +164 -63
- package/package.json +9 -7
- package/scripts/postinstall.js +2 -1
- package/skills/vike/SKILL.md +51 -106
- package/skills/vike-candles/SKILL.md +61 -0
- package/skills/vike-hl-position-match/SKILL.md +3 -3
- package/skills/vike-perp-screener/SKILL.md +0 -1
- package/skills/vike-router/SKILL.md +4 -6
- package/skills/vike-token-research/SKILL.md +0 -5
- package/skills/vike-token-search/SKILL.md +0 -1
- package/skills/vike-token-transfers/SKILL.md +0 -1
- package/skills/vike-wallet-balances/SKILL.md +0 -2
- package/skills/vike-wallet-batch/SKILL.md +0 -1
- package/skills/vike-wallet-ens/SKILL.md +0 -1
- package/skills/vike-wallet-label-provenance/SKILL.md +0 -2
- package/skills/vike-wallet-pnl-history/SKILL.md +0 -1
- package/skills/vike-wallet-portfolio/SKILL.md +1 -3
- package/skills.sh.json +6 -18
- package/src/commands/candles.js +57 -0
- package/src/commands/init.js +1 -1
- package/src/commands/labels.js +0 -32
- package/src/commands/token.js +1 -16
- package/src/index.js +4 -9
- package/src/mcp-client.js +5 -6
- package/skills/vike-defi-positions/SKILL.md +0 -59
- package/skills/vike-fund-holdings/SKILL.md +0 -53
- package/skills/vike-ohlcv/SKILL.md +0 -65
- package/skills/vike-options-flow/SKILL.md +0 -49
- package/skills/vike-web-fetch/SKILL.md +0 -55
- package/skills/vike-web-research/SKILL.md +0 -58
- package/skills/vike-web-search/SKILL.md +0 -60
- package/src/commands/ohlcv.js +0 -33
- package/src/commands/options.js +0 -24
- package/src/commands/web.js +0 -41
package/src/commands/labels.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { callTool } from '../mcp-client.js';
|
|
2
2
|
import { emit, emitError } from '../format.js';
|
|
3
|
-
import { parseInt10 } from '../util.js';
|
|
4
3
|
|
|
5
4
|
export function registerLabels(program) {
|
|
6
5
|
// `vike labels <address>` — multi-source label provenance for one wallet
|
|
@@ -14,35 +13,4 @@ export function registerLabels(program) {
|
|
|
14
13
|
emit(r, opts);
|
|
15
14
|
} catch (err) { emitError(err, opts); }
|
|
16
15
|
});
|
|
17
|
-
|
|
18
|
-
// `vike funds` — top labeled funds / MM / treasury / CEX by recent net inflow
|
|
19
|
-
program
|
|
20
|
-
.command('funds')
|
|
21
|
-
.description('Top labeled fund / market-maker / treasury / CEX wallets by net inflow')
|
|
22
|
-
.option('--kind <k>', 'funds | cex | mm | treasury', 'funds')
|
|
23
|
-
.option('--window <w>', '7d | 30d | 90d | 180d | all', '30d')
|
|
24
|
-
.option('--limit <n>', 'Max wallets (max 25)', '10')
|
|
25
|
-
.option('--json', 'Emit JSON')
|
|
26
|
-
.action(async (opts) => {
|
|
27
|
-
try {
|
|
28
|
-
const r = await callTool('fund_holdings', {
|
|
29
|
-
kind: opts.kind,
|
|
30
|
-
window: opts.window,
|
|
31
|
-
limit: parseInt10(opts.limit, 10),
|
|
32
|
-
});
|
|
33
|
-
emit(r, opts);
|
|
34
|
-
} catch (err) { emitError(err, opts); }
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// `vike defi <address>` — DeBank protocol positions for a wallet
|
|
38
|
-
program
|
|
39
|
-
.command('defi <address>')
|
|
40
|
-
.description('DeFi protocol positions for a wallet across all DeBank-supported chains')
|
|
41
|
-
.option('--json', 'Emit JSON')
|
|
42
|
-
.action(async (address, opts) => {
|
|
43
|
-
try {
|
|
44
|
-
const r = await callTool('defi_positions', { address });
|
|
45
|
-
emit(r, opts);
|
|
46
|
-
} catch (err) { emitError(err, opts); }
|
|
47
|
-
});
|
|
48
16
|
}
|
package/src/commands/token.js
CHANGED
|
@@ -5,7 +5,7 @@ import { parseInt10 } from '../util.js';
|
|
|
5
5
|
export function registerToken(program) {
|
|
6
6
|
const cmd = program
|
|
7
7
|
.command('token')
|
|
8
|
-
.description('Token search, transfers, and
|
|
8
|
+
.description('Token search, transfers, screener and holders');
|
|
9
9
|
|
|
10
10
|
cmd
|
|
11
11
|
.command('search <query>')
|
|
@@ -43,21 +43,6 @@ export function registerToken(program) {
|
|
|
43
43
|
} catch (err) { emitError(err, opts); }
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
-
cmd
|
|
47
|
-
.command('chart <token_address>')
|
|
48
|
-
.description('OHLCV candle data for a token')
|
|
49
|
-
.option('--interval <m>', '5 | 30 | 120 minutes', '30')
|
|
50
|
-
.option('--json', 'Emit JSON')
|
|
51
|
-
.action(async (tokenAddress, opts) => {
|
|
52
|
-
try {
|
|
53
|
-
const r = await callTool('token_chart', {
|
|
54
|
-
token_address: tokenAddress,
|
|
55
|
-
interval: opts.interval,
|
|
56
|
-
});
|
|
57
|
-
emit(r, opts);
|
|
58
|
-
} catch (err) { emitError(err, opts); }
|
|
59
|
-
});
|
|
60
|
-
|
|
61
46
|
cmd
|
|
62
47
|
.command('screener')
|
|
63
48
|
.description('Token discovery filter — rank tokens by volume / inflow / holders / smart-money inflow')
|
package/src/index.js
CHANGED
|
@@ -3,15 +3,12 @@ import { Command } from 'commander';
|
|
|
3
3
|
import { registerToken } from './commands/token.js';
|
|
4
4
|
import { registerWallet } from './commands/wallet.js';
|
|
5
5
|
import { registerPerp } from './commands/perp.js';
|
|
6
|
-
import { registerOptions } from './commands/options.js';
|
|
7
6
|
import { registerAlerts } from './commands/alerts.js';
|
|
8
7
|
import { registerPolymarket } from './commands/polymarket.js';
|
|
9
8
|
import { registerLabels } from './commands/labels.js';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
//
|
|
13
|
-
// commands. New wallet subcommands (counterparties, pnl-history, balances,
|
|
14
|
-
// ens) are added under registerWallet.
|
|
9
|
+
import { registerCandles } from './commands/candles.js';
|
|
10
|
+
// New wallet subcommands (counterparties, pnl-history, balances, ens) are
|
|
11
|
+
// added under registerWallet.
|
|
15
12
|
import { registerInit } from './commands/init.js';
|
|
16
13
|
import { registerInstall } from './commands/install.js';
|
|
17
14
|
import { registerDoctor } from './commands/doctor.js';
|
|
@@ -63,12 +60,10 @@ registerSchema(program);
|
|
|
63
60
|
registerToken(program);
|
|
64
61
|
registerWallet(program);
|
|
65
62
|
registerPerp(program);
|
|
66
|
-
registerOptions(program);
|
|
67
63
|
registerAlerts(program);
|
|
68
64
|
registerPolymarket(program);
|
|
69
65
|
registerLabels(program);
|
|
70
|
-
|
|
71
|
-
registerOhlcv(program);
|
|
66
|
+
registerCandles(program);
|
|
72
67
|
|
|
73
68
|
const _parseT0 = Date.now();
|
|
74
69
|
program.parseAsync(process.argv)
|
package/src/mcp-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { requireApiKey, getEndpoint
|
|
1
|
+
import { requireApiKey, getEndpoint } from './auth.js';
|
|
2
2
|
|
|
3
3
|
let _id = 0;
|
|
4
4
|
function nextId() { return ++_id; }
|
|
@@ -78,14 +78,13 @@ export async function listTools(opts = {}) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
export async function ping(opts = {}) {
|
|
81
|
-
//
|
|
81
|
+
// /mcp authenticates every method, initialize included: no key gets a
|
|
82
|
+
// JSON-RPC "Invalid or missing API key" error (soon HTTP 401), so fail early.
|
|
82
83
|
const endpoint = opts.endpoint ?? getEndpoint();
|
|
83
|
-
const apiKey = opts.apiKey ??
|
|
84
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
85
|
-
if (apiKey) headers['X-API-KEY'] = apiKey;
|
|
84
|
+
const apiKey = opts.apiKey ?? requireApiKey();
|
|
86
85
|
const resp = await fetch(endpoint, {
|
|
87
86
|
method: 'POST',
|
|
88
|
-
headers,
|
|
87
|
+
headers: { 'Content-Type': 'application/json', 'X-API-KEY': apiKey },
|
|
89
88
|
body: JSON.stringify({
|
|
90
89
|
jsonrpc: '2.0', id: nextId(), method: 'initialize', params: {},
|
|
91
90
|
}),
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-defi-positions
|
|
3
|
-
description: DeFi protocol positions for a wallet across all DeBank-supported chains (Aave, Uniswap LP, Curve, Pendle, EigenLayer, etc.) — net USD, asset USD, debt USD per protocol. Use when the user asks "what DeFi positions does this wallet have" / "is wallet X farming yields" / "show me the protocol breakdown for Y".
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-defi-positions
|
|
8
|
-
|
|
9
|
-
## Command
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
vike defi <address> [--json]
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Example
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
vike defi 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 # vitalik.eth
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## Output shape
|
|
22
|
-
|
|
23
|
-
```json
|
|
24
|
-
{
|
|
25
|
-
"address": "0x...",
|
|
26
|
-
"total_balance": {
|
|
27
|
-
"total_usd": 12345.67,
|
|
28
|
-
"chains": [
|
|
29
|
-
{ "chain": "eth", "usd": 9000.00 },
|
|
30
|
-
{ "chain": "arb", "usd": 2000.00 },
|
|
31
|
-
{ "chain": "base", "usd": 1345.67 }
|
|
32
|
-
]
|
|
33
|
-
},
|
|
34
|
-
"protocols": [
|
|
35
|
-
{ "protocol": "Aave V3", "chain": "eth", "net_usd": 5000.00, "asset_usd": 8000.00, "debt_usd": 3000.00, "positions": 2 },
|
|
36
|
-
{ "protocol": "Uniswap V3", "chain": "eth", "net_usd": 2500.00, "asset_usd": 2500.00, "debt_usd": 0.00, "positions": 4 },
|
|
37
|
-
...
|
|
38
|
-
]
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Reading
|
|
43
|
-
|
|
44
|
-
- `net_usd = asset_usd - debt_usd` — what the position is actually worth
|
|
45
|
-
- A protocol row with `debt_usd > 0` means the wallet is **borrowing** (Aave / Compound / Morpho). High debt + low asset = leveraged.
|
|
46
|
-
- `positions` count tells you how many active positions inside one protocol (e.g. 4 Uniswap LP positions)
|
|
47
|
-
- `total_balance.total_usd` includes both DeFi positions AND wallet token balances; the `protocols` array is DeFi-only
|
|
48
|
-
|
|
49
|
-
## Anti-patterns
|
|
50
|
-
|
|
51
|
-
- DeBank may not cover every L2/protocol — a missing protocol doesn't mean the wallet has no position there
|
|
52
|
-
- The `chain` field uses DeBank's IDs (`eth`, `bsc`, `matic`, `arb`, `op`, `base`, etc.) — translate to user-friendly names when reporting
|
|
53
|
-
- Stale data: DeBank refresh varies; freshly-opened positions may not show for 5-15 min
|
|
54
|
-
- If you get `balance_error` or `positions_error`, the DeBank API is rate-limited / down — retry once, then surface the error honestly
|
|
55
|
-
|
|
56
|
-
## Pairs well with
|
|
57
|
-
|
|
58
|
-
- `vike labels <addr>` — combine label provenance with DeFi positions for a full institutional view
|
|
59
|
-
- `vike wallet summary <addr>` — on-chain transfer activity vs DeFi positions for the same wallet
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-fund-holdings
|
|
3
|
-
description: Top labeled fund / market-maker / treasury / CEX wallets ranked by recent net inflow USD. Use when the user asks "what are funds buying" / "which whales are accumulating" / "track institutional flows".
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-fund-holdings
|
|
8
|
-
|
|
9
|
-
## Command
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
vike funds [--kind funds|cex|mm|treasury] [--window 7d|30d|90d|180d|all] [--limit N] [--json]
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Examples
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
vike funds --kind funds --window 30d --limit 10
|
|
19
|
-
vike funds --kind cex --window 7d --limit 20
|
|
20
|
-
vike funds --kind treasury --window 90d
|
|
21
|
-
vike funds --kind mm --window 30d
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Kind filters
|
|
25
|
-
|
|
26
|
-
| Kind | Includes |
|
|
27
|
-
|---|---|
|
|
28
|
-
| `funds` (default) | Treasury wallets + market-makers + custody anchors + Fund / Hedge / VC / Foundation / DAO categories |
|
|
29
|
-
| `cex` | Exchanges (Binance, Coinbase, Bybit, OKX, etc.) |
|
|
30
|
-
| `mm` | Market-makers (Wintermute, GSR, Jump, etc.) |
|
|
31
|
-
| `treasury` | DAO + corporate treasury wallets |
|
|
32
|
-
|
|
33
|
-
## Output columns
|
|
34
|
-
|
|
35
|
-
`wallet`, `entity`, `label` (raw provider tag, when available), `wallet_type`, `confidence`, `net_flow_usd` (window), `volume_usd` (window), `tx_count` (window)
|
|
36
|
-
|
|
37
|
-
## Reading
|
|
38
|
-
|
|
39
|
-
- **Sort is descending by net_flow_usd** — top accumulators come first
|
|
40
|
-
- A wallet with `entity = "Binance"` and `wallet_type = "cex"` showing massive net inflow = users depositing TO Binance (bearish for prices on the way in), or Binance moving inventory internally
|
|
41
|
-
- `confidence = "High"` rows have multi-source label agreement; `Low` rows are heuristic-only
|
|
42
|
-
- Negative `net_flow_usd` in a list sorted descending = no accumulators above this row; everyone is net-selling
|
|
43
|
-
|
|
44
|
-
## Anti-patterns
|
|
45
|
-
|
|
46
|
-
- Don't quote "Binance bought $50M of X" from this view — it's wallet-level flow, not per-token attribution. For per-token, use `vike token holders` then filter for CEX labels.
|
|
47
|
-
- Treasury wallets often have huge one-time inflows (e.g. ICO unlocks); a single 30d window can be misleading. Check `--window all` for context.
|
|
48
|
-
|
|
49
|
-
## Pairs well with
|
|
50
|
-
|
|
51
|
-
- `vike labels <addr>` — drill into any specific wallet's full label cascade
|
|
52
|
-
- `vike token holders <addr>` — see which of these wallets hold a specific token
|
|
53
|
-
- `vike-smart-money-discovery` — find unlabeled smart wallets vs labeled funds
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-ohlcv
|
|
3
|
-
description: Historical CEX candles for a canonical ticker (BTC) or exchange pair (BTCUSDT) at any timeframe (1m–1w), spot or perp. Use when the user asks "BTC hourly candles" / "ETH 4h chart on Binance" / "give me daily OHLCV for SOL" / needs look-ahead-safe candle data for a backtest.
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-ohlcv
|
|
8
|
-
|
|
9
|
-
CEX OHLCV candles by ticker or pair. Distinct from `vike token chart`, which serves DEX candles by **contract address** at only 5/30/120-min resolution.
|
|
10
|
-
|
|
11
|
-
## Command
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
vike ohlcv <symbol> [--interval 1m|3m|5m|15m|30m|1h|2h|4h|6h|8h|12h|1d|1w] \
|
|
15
|
-
[--exchange binance|bybit|okx|gate|kucoin|coinbase|mexc|pyth] \
|
|
16
|
-
[--market spot|perp] [--start <ts>] [--end <ts>] \
|
|
17
|
-
[--limit N] [--cursor <c>] [--json]
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
- `<symbol>` — canonical ticker (`BTC`, `ETH`) or an exchange pair (`BTCUSDT`, `BTCUSDT_PERP`).
|
|
21
|
-
- `--exchange` — **omit for the merged best-source series** (best venue per minute, gaps backfilled). Pin a venue only for that venue's raw series.
|
|
22
|
-
- `--interval` defaults to `1h`. `--market` defaults to `spot`.
|
|
23
|
-
- `--start` / `--end` — ISO-8601 UTC (`2026-01-01`) or epoch ms. Buckets are left-aligned UTC.
|
|
24
|
-
- `--limit` defaults to 500, hard max 5000.
|
|
25
|
-
|
|
26
|
-
## Examples
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Last 500 hourly candles, merged best-source:
|
|
30
|
-
vike ohlcv BTC --json
|
|
31
|
-
|
|
32
|
-
# 4h Binance perp candles for ETH:
|
|
33
|
-
vike ohlcv ETH --interval 4h --market perp --exchange binance --json
|
|
34
|
-
|
|
35
|
-
# Daily candles over an explicit range:
|
|
36
|
-
vike ohlcv SOL --interval 1d --start 2026-01-01 --end 2026-03-01 --json
|
|
37
|
-
|
|
38
|
-
# Page forward with the cursor from a previous call:
|
|
39
|
-
vike ohlcv BTC --interval 1m --limit 5000 --cursor <next_cursor> --json
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Output
|
|
43
|
-
|
|
44
|
-
`{ symbol, pair, exchange, interval, market, tz, candles[], next_cursor }`
|
|
45
|
-
|
|
46
|
-
Each candle: `{ ts (epoch ms, UTC), open, high, low, close, volume }`, ascending by `ts`.
|
|
47
|
-
|
|
48
|
-
## Reading
|
|
49
|
-
|
|
50
|
-
- **Look-ahead-safe**: the in-progress (partial) bucket is excluded, so the last candle is always closed — safe to feed into a backtest.
|
|
51
|
-
- `exchange: "merged"` means no `--exchange` was pinned; each minute is sourced from the best available venue with gaps backfilled.
|
|
52
|
-
- `pair` echoes how the symbol resolved — `BTCUSDT` for spot, `BTCUSDT_PERP` for perp.
|
|
53
|
-
- Use `next_cursor` to page; pass it back via `--cursor`. A null/absent cursor means the series is exhausted.
|
|
54
|
-
|
|
55
|
-
## Anti-patterns
|
|
56
|
-
|
|
57
|
-
- Don't use this for an on-chain/DEX-only token with no CEX listing — use `vike token chart <contract_address>` instead.
|
|
58
|
-
- Don't omit `--market perp` when the user clearly means a perpetual; spot and perp candles differ.
|
|
59
|
-
- Don't request 1m candles over a multi-month range in one call — page with `--cursor` (hard max 5000 candles/call).
|
|
60
|
-
|
|
61
|
-
## Pairs well with
|
|
62
|
-
|
|
63
|
-
- `vike token chart <addr>` — DEX candles when there's no CEX pair
|
|
64
|
-
- `vike perp funding` / `vike perp spreads` — pair candle context with funding/spread arb
|
|
65
|
-
- `vike options flow` — overlay options positioning on the underlying's candles
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-options-flow
|
|
3
|
-
description: Deribit options flow — call/put volume, put-call ratios, and direction signals for BTC / ETH / SOL. Use when the user asks "options flow on X" / "put call ratio" / "options positioning".
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-options-flow
|
|
8
|
-
|
|
9
|
-
## Command
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
vike options flow --symbol BTC|ETH|SOL [--window 1d|1w|1m] [--json]
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Default: BTC, 1d.
|
|
16
|
-
|
|
17
|
-
## Output
|
|
18
|
-
|
|
19
|
-
Per-window aggregates: call volume, put volume, put-call ratio, net delta, open-interest deltas.
|
|
20
|
-
|
|
21
|
-
## Reading the put-call ratio (PCR)
|
|
22
|
-
|
|
23
|
-
| PCR (volume basis) | Read |
|
|
24
|
-
|---|---|
|
|
25
|
-
| < 0.5 | **Aggressive call buying** — bullish positioning, or call-overwrite unwind |
|
|
26
|
-
| 0.5–0.8 | Normal bullish |
|
|
27
|
-
| 0.8–1.2 | Balanced |
|
|
28
|
-
| 1.2–1.8 | Bearish hedging or directional put buying |
|
|
29
|
-
| > 1.8 | Heavy put demand — fear / hedge spike |
|
|
30
|
-
|
|
31
|
-
PCR is **not a contrarian signal** on its own. Cross-reference with spot price action and funding:
|
|
32
|
-
- High PCR + price falling + negative funding = real bearish capitulation
|
|
33
|
-
- High PCR + price flat + positive funding = hedging into a rally (not panic)
|
|
34
|
-
|
|
35
|
-
## Window choice
|
|
36
|
-
|
|
37
|
-
- `1d` — intraday sentiment shifts, useful around major events
|
|
38
|
-
- `1w` — positioning trend; cleaner read for narrative
|
|
39
|
-
- `1m` — structural positioning; useful for IV-rank and term-structure context
|
|
40
|
-
|
|
41
|
-
## Anti-patterns
|
|
42
|
-
|
|
43
|
-
- Don't quote raw call/put volume without context — Deribit's BTC notional is in the tens of billions weekly; a $100M day means little in isolation.
|
|
44
|
-
- Don't conflate flow (new positions) with open interest (cumulative). Flow is the change; OI is the stock.
|
|
45
|
-
|
|
46
|
-
## Pairs well with
|
|
47
|
-
|
|
48
|
-
- `vike-perp-funding-arb` for the corresponding perp positioning
|
|
49
|
-
- `vike-perp-screener` for the broader market read
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-web-fetch
|
|
3
|
-
description: Fetch a URL's content (via Tavily extract) and optionally answer a question about it using Cerebras Llama 3.3 70B. Use when the user gives a URL and asks "what does this page say" / "summarise X" / "extract Y from this article".
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-web-fetch
|
|
8
|
-
|
|
9
|
-
## Command
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
vike web fetch <url> [--ask "<question>"] [--json]
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Examples
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
vike web fetch https://example.com/article
|
|
19
|
-
vike web fetch https://example.com/article --ask "what's the launch date?"
|
|
20
|
-
vike web fetch https://docs.hyperliquid.xyz/funding --ask "how often does funding settle?"
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Output
|
|
24
|
-
|
|
25
|
-
```json
|
|
26
|
-
{
|
|
27
|
-
"url": "https://...",
|
|
28
|
-
"content_length": 12345,
|
|
29
|
-
"content": "First 8K chars of extracted content...",
|
|
30
|
-
"answer": "Answer to your question if --ask was provided"
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
If `--ask` is omitted, you get raw extracted content only.
|
|
35
|
-
|
|
36
|
-
## How it works
|
|
37
|
-
|
|
38
|
-
1. Tries Tavily's `/extract` endpoint first — returns clean markdown-like text
|
|
39
|
-
2. Falls back to raw HTTP GET if Tavily extract is unavailable
|
|
40
|
-
3. If `--ask` is provided, sends content + question to Cerebras Llama 3.3 70B for a focused answer
|
|
41
|
-
|
|
42
|
-
## Why we use Cerebras (not Gemini / OpenAI)
|
|
43
|
-
|
|
44
|
-
Cerebras Llama 3.3 70B is ~10x cheaper than Gemini 2.5 Flash and ~3-5x faster (1000+ tok/sec inference). Same answer quality for short Q&A on supplied content.
|
|
45
|
-
|
|
46
|
-
## Anti-patterns
|
|
47
|
-
|
|
48
|
-
- Don't fetch pay-walled URLs and expect text — you'll get a paywall page. Cite the URL and tell the user instead.
|
|
49
|
-
- Don't fetch huge files (PDFs > 10MB, videos) — the extract will be truncated and likely garbage.
|
|
50
|
-
- Don't ask `--ask` questions the content can't possibly answer — Cerebras will hallucinate. Stay tight to what's on the page.
|
|
51
|
-
|
|
52
|
-
## Pairs well with
|
|
53
|
-
|
|
54
|
-
- `vike web search` — find URLs to fetch first
|
|
55
|
-
- `vike-web-research` — composite multi-step research workflow
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-web-research
|
|
3
|
-
description: Multi-step web research playbook — search → fetch the most relevant URL → synthesize answer. Use when the user asks an open question that requires fresh web info ("what did Trump say about crypto yesterday", "latest exchange listing announcement", "summarize the latest Pendle update").
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-web-research
|
|
8
|
-
|
|
9
|
-
Composite playbook combining `vike web search` and `vike web fetch` for cross-source synthesis.
|
|
10
|
-
|
|
11
|
-
## Workflow
|
|
12
|
-
|
|
13
|
-
### 1. Search (gather candidate URLs)
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
vike web search "<query>" --max 5 --json
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Capture the top results' URLs and titles. If the response includes an `answer` field, that's often enough for simple factual queries — surface it directly and skip step 2.
|
|
20
|
-
|
|
21
|
-
### 2. Fetch (only when search snippets are insufficient)
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
vike web fetch <top-result-url> --ask "<focused question>" --json
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Fetch only the highest-scoring (Tavily) or most-credible (Serper) URL. Re-fetching all 5 search results burns credits and adds noise.
|
|
28
|
-
|
|
29
|
-
### 3. Synthesize
|
|
30
|
-
|
|
31
|
-
> **Question:** `<user query>`
|
|
32
|
-
> **Answer (from `<source URL>`):** `<extracted answer>`
|
|
33
|
-
> **Other relevant sources:** `<url1>`, `<url2>` (with one-line summaries each)
|
|
34
|
-
|
|
35
|
-
Always link the source URL so the user can verify.
|
|
36
|
-
|
|
37
|
-
## When to skip the workflow
|
|
38
|
-
|
|
39
|
-
- **One-shot fact lookup** (price, date, contract address) → if `web search` returns it in the `answer` field, just quote that
|
|
40
|
-
- **The user already gave you a URL** → skip search, jump to `web fetch`
|
|
41
|
-
- **On-chain question** → don't web-research; use vike's on-chain tools (`token holders`, `wallet labels`, `perp funding`, etc.)
|
|
42
|
-
|
|
43
|
-
## Anti-patterns
|
|
44
|
-
|
|
45
|
-
- Don't fetch 5 URLs and average them — pick the most authoritative
|
|
46
|
-
- Don't quote Reddit / Twitter as primary sources for hard claims (price, dates, addresses); use them for sentiment only
|
|
47
|
-
- Don't combine web research with `vike-smart-money-discovery` results without saying so — they're different evidence types
|
|
48
|
-
|
|
49
|
-
## Cost
|
|
50
|
-
|
|
51
|
-
- Step 1: 2 credits (Tavily basic)
|
|
52
|
-
- Step 2: 3 credits (web_fetch with --ask = Tavily extract + Cerebras Q&A)
|
|
53
|
-
- Total: ~5 credits per research round
|
|
54
|
-
|
|
55
|
-
## Pairs well with
|
|
56
|
-
|
|
57
|
-
- `vike-token-research` — combine on-chain data with off-chain news
|
|
58
|
-
- `vike-polymarket-screener` — narrative-driven prediction markets often need news context
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: vike-web-search
|
|
3
|
-
description: Web search using Tavily (LLM-tuned snippets, primary) with Serper Google fallback. Use when you need current events, project announcements, exchange listing news, or anything not in the vike on-chain databases.
|
|
4
|
-
allowed-tools: Bash(vike:*)
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# vike-web-search
|
|
8
|
-
|
|
9
|
-
## Command
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
vike web search "<query>" [--max N] [--depth basic|advanced] [--json]
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
The query can contain multiple words (no quoting required if you don't have shell-special chars).
|
|
16
|
-
|
|
17
|
-
## Examples
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
vike web search "hyperliquid funding rate explained"
|
|
21
|
-
vike web search "polymarket trump 2026 latest" --max 8
|
|
22
|
-
vike web search "ETH ETF inflows last week" --depth advanced
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Output
|
|
26
|
-
|
|
27
|
-
```json
|
|
28
|
-
{
|
|
29
|
-
"provider": "tavily",
|
|
30
|
-
"query": "...",
|
|
31
|
-
"answer": "Optional one-paragraph synthesised answer (Tavily only)",
|
|
32
|
-
"results": [
|
|
33
|
-
{ "title": "...", "url": "...", "snippet": "...", "score": 0.88 },
|
|
34
|
-
...
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
`score` is a 0-1 relevance from Tavily (higher = more relevant). Serper doesn't include it.
|
|
40
|
-
|
|
41
|
-
## When to use vs on-chain tools
|
|
42
|
-
|
|
43
|
-
- **News / sentiment / project context** → `vike web search`
|
|
44
|
-
- **On-chain flows / wallet activity / token prices** → use the dedicated `vike token`/`vike wallet`/`vike perp` tools first
|
|
45
|
-
- **"What did X tweet" / "did Binance announce Y"** → web search
|
|
46
|
-
|
|
47
|
-
## Cost note
|
|
48
|
-
|
|
49
|
-
Web search calls cost 2 credits + an external API fee on our side. Use it when you genuinely need fresh / non-onchain info, not as a first-resort.
|
|
50
|
-
|
|
51
|
-
## Anti-patterns
|
|
52
|
-
|
|
53
|
-
- Don't web-search for things our on-chain tools answer faster ("top wallets holding PEPE" → `vike token holders` is faster, cheaper, and more accurate)
|
|
54
|
-
- Don't request `--max > 5` unless you genuinely need a wide net — agents waste tokens summarising 10 results when 3 would do
|
|
55
|
-
- `--depth advanced` doubles the cost; reserve for hard-to-answer queries
|
|
56
|
-
|
|
57
|
-
## Pairs well with
|
|
58
|
-
|
|
59
|
-
- `vike-web-fetch` — once you have a promising URL, fetch its full content
|
|
60
|
-
- `vike-web-research` — composite playbook for multi-step research
|
package/src/commands/ohlcv.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { callTool } from '../mcp-client.js';
|
|
2
|
-
import { emit, emitError } from '../format.js';
|
|
3
|
-
import { parseInt10 } from '../util.js';
|
|
4
|
-
|
|
5
|
-
export function registerOhlcv(program) {
|
|
6
|
-
program
|
|
7
|
-
.command('ohlcv <symbol>')
|
|
8
|
-
.description('Historical CEX candles for a ticker (BTC) or pair (BTCUSDT) across any timeframe')
|
|
9
|
-
.option('--interval <i>', '1m | 3m | 5m | 15m | 30m | 1h | 2h | 4h | 6h | 8h | 12h | 1d | 1w', '1h')
|
|
10
|
-
.option('--exchange <e>', 'Pin one venue: binance | bybit | okx | gate | kucoin | coinbase | mexc | pyth. Omit for merged best-source.')
|
|
11
|
-
.option('--market <m>', 'spot | perp', 'spot')
|
|
12
|
-
.option('--start <t>', 'ISO-8601 UTC or epoch ms (inclusive)')
|
|
13
|
-
.option('--end <t>', 'ISO-8601 UTC or epoch ms (exclusive)')
|
|
14
|
-
.option('--limit <n>', 'Max candles (default 500, max 5000)', '500')
|
|
15
|
-
.option('--cursor <c>', 'Opaque paging cursor from a previous call')
|
|
16
|
-
.option('--json', 'Emit JSON')
|
|
17
|
-
.action(async (symbol, opts) => {
|
|
18
|
-
try {
|
|
19
|
-
const args = {
|
|
20
|
-
symbol,
|
|
21
|
-
interval: opts.interval,
|
|
22
|
-
market: opts.market,
|
|
23
|
-
limit: parseInt10(opts.limit, 500),
|
|
24
|
-
};
|
|
25
|
-
if (opts.exchange !== undefined) args.exchange = opts.exchange;
|
|
26
|
-
if (opts.start !== undefined) args.start = opts.start;
|
|
27
|
-
if (opts.end !== undefined) args.end = opts.end;
|
|
28
|
-
if (opts.cursor !== undefined) args.cursor = opts.cursor;
|
|
29
|
-
const r = await callTool('ohlcv', args);
|
|
30
|
-
emit(r, opts);
|
|
31
|
-
} catch (err) { emitError(err, opts); }
|
|
32
|
-
});
|
|
33
|
-
}
|
package/src/commands/options.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { callTool } from '../mcp-client.js';
|
|
2
|
-
import { emit, emitError } from '../format.js';
|
|
3
|
-
|
|
4
|
-
export function registerOptions(program) {
|
|
5
|
-
const cmd = program
|
|
6
|
-
.command('options')
|
|
7
|
-
.description('Deribit options flow');
|
|
8
|
-
|
|
9
|
-
cmd
|
|
10
|
-
.command('flow')
|
|
11
|
-
.description('Call/put flow, volume, and put-call ratios')
|
|
12
|
-
.option('--symbol <s>', 'BTC | ETH | SOL', 'BTC')
|
|
13
|
-
.option('--window <w>', '1d | 1w | 1m', '1d')
|
|
14
|
-
.option('--json', 'Emit JSON')
|
|
15
|
-
.action(async (opts) => {
|
|
16
|
-
try {
|
|
17
|
-
const r = await callTool('options_flow', {
|
|
18
|
-
symbol: opts.symbol,
|
|
19
|
-
window: opts.window,
|
|
20
|
-
});
|
|
21
|
-
emit(r, opts);
|
|
22
|
-
} catch (err) { emitError(err, opts); }
|
|
23
|
-
});
|
|
24
|
-
}
|
package/src/commands/web.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { callTool } from '../mcp-client.js';
|
|
2
|
-
import { emit, emitError } from '../format.js';
|
|
3
|
-
import { parseInt10 } from '../util.js';
|
|
4
|
-
|
|
5
|
-
export function registerWeb(program) {
|
|
6
|
-
const cmd = program
|
|
7
|
-
.command('web')
|
|
8
|
-
.description('Web search + fetch (Tavily / Serper / Cerebras)');
|
|
9
|
-
|
|
10
|
-
cmd
|
|
11
|
-
.command('search <query...>')
|
|
12
|
-
.description('Web search (Tavily primary, Serper Google fallback)')
|
|
13
|
-
.option('--max <n>', 'Max results (default 5, max 10)', '5')
|
|
14
|
-
.option('--depth <d>', 'Tavily depth: basic | advanced', 'basic')
|
|
15
|
-
.option('--json', 'Emit JSON')
|
|
16
|
-
.action(async (queryParts, opts) => {
|
|
17
|
-
try {
|
|
18
|
-
const r = await callTool('web_search', {
|
|
19
|
-
query: queryParts.join(' '),
|
|
20
|
-
max_results: parseInt10(opts.max, 5),
|
|
21
|
-
search_depth: opts.depth,
|
|
22
|
-
});
|
|
23
|
-
emit(r, opts);
|
|
24
|
-
} catch (err) { emitError(err, opts); }
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
cmd
|
|
28
|
-
.command('fetch <url>')
|
|
29
|
-
.description('Fetch URL and optionally answer a question about it')
|
|
30
|
-
.option('--ask <question>', 'Question to answer from the content (uses Cerebras)')
|
|
31
|
-
.option('--json', 'Emit JSON')
|
|
32
|
-
.action(async (url, opts) => {
|
|
33
|
-
try {
|
|
34
|
-
const r = await callTool('web_fetch', {
|
|
35
|
-
url,
|
|
36
|
-
question: opts.ask,
|
|
37
|
-
});
|
|
38
|
-
emit(r, opts);
|
|
39
|
-
} catch (err) { emitError(err, opts); }
|
|
40
|
-
});
|
|
41
|
-
}
|