@haoxdong/marquee-cli 0.2.0 → 0.3.0
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/LICENSE.md +3 -4
- package/README.md +6 -2
- package/dist/cli.js +76 -125
- package/package.json +23 -11
- package/scripts/install-skill.mjs +7 -2
- package/skills/marquee/SKILL.md +29 -26
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haoxdong/marquee-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
5
5
|
"repository": "https://github.com/haoxdong/marquee-cli.git",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
|
-
"node": ">=
|
|
8
|
+
"node": ">=24.0.0"
|
|
9
9
|
},
|
|
10
10
|
"bin": {
|
|
11
11
|
"marquee": "dist/cli.js"
|
|
@@ -22,23 +22,35 @@
|
|
|
22
22
|
},
|
|
23
23
|
"scripts": {
|
|
24
24
|
"clean": "node -e \"const fs = require('node:fs'); for (const path of ['dist', 'tsconfig.tsbuildinfo']) fs.rmSync(path, { recursive: true, force: true })\"",
|
|
25
|
-
"build": "npm run clean && esbuild cli/main.ts --bundle --platform=node --format=esm --minify --external:agent-browser --banner:js=\"import{createRequire}from'node:module';const require=createRequire(import.meta.url);\" --outfile=dist/cli.js && node -e \"require('node:fs').chmodSync('dist/cli.js', 0o755)\"",
|
|
26
|
-
"build:coverage": "npm run clean && tsc -p tsconfig.json && node -e \"const fs = require('node:fs'); fs.writeFileSync('dist/cli.js', ['#!/usr/bin/env node', \\\"import './cli/main.js';\\\", ''].join('\\n')); fs.chmodSync('dist/cli.js', 0o755)\"",
|
|
25
|
+
"build": "npm run clean && esbuild cli-composition/main.ts --bundle --platform=node --format=esm --minify --external:agent-browser --external:tinycolor2 --external:@opentelemetry/* --banner:js=\"import{createRequire}from'node:module';const require=createRequire(import.meta.url);\" --outfile=dist/cli.js && node -e \"require('node:fs').chmodSync('dist/cli.js', 0o755)\"",
|
|
26
|
+
"build:coverage": "npm run clean && tsc -p tsconfig.json && node -e \"const fs = require('node:fs'); fs.writeFileSync('dist/cli.js', ['#!/usr/bin/env node', \\\"import './cli-composition/main.js';\\\", ''].join('\\n')); fs.chmodSync('dist/cli.js', 0o755)\"",
|
|
27
27
|
"postinstall": "node scripts/install-skill.mjs",
|
|
28
28
|
"prepack": "npm run build",
|
|
29
29
|
"test": "vitest run",
|
|
30
30
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
33
|
+
"@opentelemetry/api": "1.9.1",
|
|
34
|
+
"@opentelemetry/instrumentation-undici": "0.32.0",
|
|
35
|
+
"@opentelemetry/sdk-node": "0.222.0",
|
|
36
|
+
"agent-browser": "0.38.2",
|
|
37
|
+
"commander": "^14.0.3",
|
|
38
|
+
"d3-format": "^3.1.2",
|
|
39
|
+
"d3-time-format": "^4.1.0",
|
|
40
|
+
"jq-wasm": "3.0.0-jq-1.8.2",
|
|
41
|
+
"proper-lockfile": "^4.1.2",
|
|
42
|
+
"tinycolor2": "^1.6.0"
|
|
36
43
|
},
|
|
37
44
|
"devDependencies": {
|
|
38
|
-
"@types/
|
|
45
|
+
"@types/d3-format": "^3.0.4",
|
|
46
|
+
"@types/d3-time-format": "^4.0.3",
|
|
47
|
+
"@types/node": "^24.19.1",
|
|
39
48
|
"@types/proper-lockfile": "^4.1.4",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
49
|
+
"@types/tinycolor2": "^1.4.6",
|
|
50
|
+
"esbuild": "^0.28.2",
|
|
51
|
+
"fast-check": "^4.10.2",
|
|
52
|
+
"type-fest": "^5.10.0",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vitest": "^3.2.7"
|
|
43
55
|
}
|
|
44
56
|
}
|
|
@@ -38,6 +38,10 @@ function selectedAgentNames() {
|
|
|
38
38
|
return new Set(configured.split(',').map((name) => name.trim()).filter(Boolean));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @param {string} target
|
|
43
|
+
* @param {import('node:fs').Stats} installed
|
|
44
|
+
*/
|
|
41
45
|
function packageOwns(target, installed) {
|
|
42
46
|
if (installed.isSymbolicLink()) {
|
|
43
47
|
try {
|
|
@@ -57,11 +61,12 @@ function packageOwns(target, installed) {
|
|
|
57
61
|
try {
|
|
58
62
|
return readFileSync(resolve(target, ownerMarker), 'utf8').trim() === owner;
|
|
59
63
|
} catch (error) {
|
|
60
|
-
if (error
|
|
64
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code === 'ENOENT') return false;
|
|
61
65
|
throw error;
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
/** @param {(typeof agents)[number]} agent */
|
|
65
70
|
function install(agent) {
|
|
66
71
|
const configDirExists = existsSync(agent.configDir);
|
|
67
72
|
if (!configDirExists && !agent.installWhenMissing) return;
|
|
@@ -72,7 +77,7 @@ function install(agent) {
|
|
|
72
77
|
try {
|
|
73
78
|
installed = lstatSync(target);
|
|
74
79
|
} catch (error) {
|
|
75
|
-
if (error
|
|
80
|
+
if (/** @type {NodeJS.ErrnoException} */ (error).code !== 'ENOENT') throw error;
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
if (installed && !packageOwns(target, installed)) {
|
package/skills/marquee/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: marquee
|
|
3
|
-
description: Use when querying Marquee for market data
|
|
3
|
+
description: Use when querying Marquee for market data or research content, or when asked to open, read, or interact with any web page — `marquee browser` is your browser.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
## Response format
|
|
@@ -9,7 +9,7 @@ description: Use when querying Marquee for market data, research content, or pag
|
|
|
9
9
|
|
|
10
10
|
**Direct.** Answer the question asked, nothing adjacent. Tables over paragraphs for structured data.
|
|
11
11
|
|
|
12
|
-
**Concise.** Numbers over narrative. One sentence where one suffices; a table cell where a sentence would pad. Never restate the question. Most answers
|
|
12
|
+
**Concise.** Numbers over narrative. One sentence where one suffices; a table cell where a sentence would pad. Never restate the question. Most answers are a few flat sentences — stop once the question is answered. Only when genuinely multi-part:
|
|
13
13
|
|
|
14
14
|
```
|
|
15
15
|
### Summary
|
|
@@ -23,20 +23,21 @@ Use exactly these two headers — no other sections, no renaming.
|
|
|
23
23
|
|
|
24
24
|
**Counterweight.** Close with what could break the thesis — the key risk or the condition under which the narrative flips.
|
|
25
25
|
|
|
26
|
-
**Citations.** Every factual claim gets a source URL — no exceptions, including bullets and table cells: `…widened 12bp [[1]](https://marquee.gs.com/s/markets/…)`. Never surface refs
|
|
26
|
+
**Citations.** Every factual claim gets a source URL — no exceptions, including bullets and table cells: `…widened 12bp [[1]](https://marquee.gs.com/s/markets/…)`. Never surface refs in the final answer — they are internal plumbing.
|
|
27
|
+
|
|
28
|
+
**Charts.** For Mermaid `xychart-beta`, use unique x-axis labels. For time series spanning more than 12 months, include the year on every label (for example, `Nov24`, `Nov25`). Repeated categorical labels fold distinct points onto the same x position.
|
|
27
29
|
|
|
28
30
|
## Core loop
|
|
29
31
|
|
|
30
32
|
**Chain** refs — every command emits refs, the next consumes them.
|
|
31
33
|
|
|
32
34
|
```
|
|
33
|
-
marquee marketview search "query"
|
|
34
|
-
marquee
|
|
35
|
-
marquee
|
|
36
|
-
marquee expand @wN.data --tail 5 # peek at rows without code
|
|
35
|
+
marquee marketview search "query" # → @s1 with widget refs
|
|
36
|
+
marquee marketview widget view @s1.w1 # → @wN
|
|
37
|
+
marquee marketview widget view @wN --json data --jq '.data | map(select(…))' # extract rows
|
|
37
38
|
```
|
|
38
39
|
|
|
39
|
-
Asset-level: `marquee marketview dashboard TICKER` → `@dN`, then `
|
|
40
|
+
Asset-level: `marquee marketview dashboard view TICKER` → `@dN`, then `marquee marketview widget view @dN.w1`.
|
|
40
41
|
|
|
41
42
|
Go straight to the best command; search only when genuinely ambiguous.
|
|
42
43
|
|
|
@@ -44,20 +45,20 @@ Go straight to the best command; search only when genuinely ambiguous.
|
|
|
44
45
|
|
|
45
46
|
Use the exact ref from the latest output — never hardcode. The global registry accumulates across commands.
|
|
46
47
|
|
|
47
|
-
| Target | Shape
|
|
48
|
-
|
|
49
|
-
| `@wN
|
|
50
|
-
| `@
|
|
51
|
-
| `@s1` | search payload | filter/rank results before loading |
|
|
48
|
+
| Target | Shape | When |
|
|
49
|
+
| ------ | -------------- | ----------------------------------------------- |
|
|
50
|
+
| `@wN` | widget | display, change parameters, or inspect its rows |
|
|
51
|
+
| `@s1` | search payload | choose a result before retrieving it |
|
|
52
52
|
|
|
53
53
|
### Changing parameters
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
Widget output shows canonical `-p` keys. Re-get the widget with one or more overrides:
|
|
56
56
|
|
|
57
57
|
```
|
|
58
|
-
marquee
|
|
59
|
-
marquee
|
|
60
|
-
marquee
|
|
58
|
+
marquee marketview widget view @wN -p universe=Latam
|
|
59
|
+
marquee marketview widget view @wN -p pricingDate=2026-01-15
|
|
60
|
+
marquee marketview widget view @wN -p includeInternal=true
|
|
61
|
+
marquee marketview widget view @wN --json params # inspect the complete option space
|
|
61
62
|
```
|
|
62
63
|
|
|
63
64
|
## Content
|
|
@@ -65,26 +66,26 @@ marquee check @wN.includeInternal # boolean toggle
|
|
|
65
66
|
Research articles and market commentary:
|
|
66
67
|
|
|
67
68
|
```
|
|
68
|
-
marquee content search "query"
|
|
69
|
-
marquee content
|
|
70
|
-
marquee content
|
|
71
|
-
marquee content
|
|
72
|
-
marquee
|
|
69
|
+
marquee content search "query" # → @s1 with @s1.cN
|
|
70
|
+
marquee content search "query" --author hatz # fuzzy values resolve fail-loud
|
|
71
|
+
marquee content search "query" --source Research --published ">=2026-01-01"
|
|
72
|
+
marquee content view <uuid|url> # retrieves the document → @cN
|
|
73
|
+
marquee content view @s1.c1 # get the exact result ref printed
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
|
|
76
|
+
Narrow with repeatable `--source`, `--subsource`, `--type`, `--publication`, `--author`, `--region`, `--subject`, `--company`, `--industry`, `--action`, and `--focus` flags. Repeat one flag for OR; combine different flags for AND. Use the `Filter by:` footer for common values, resolution errors for candidates, and `--json` for the full facet list.
|
|
76
77
|
|
|
77
78
|
## Execution
|
|
78
79
|
|
|
79
|
-
Separate Bash tool calls run **sequentially**. All independent commands — searches,
|
|
80
|
+
Separate Bash tool calls run **sequentially**. All independent commands — searches, widget reads, projections — go in one Bash call with `&` + `wait`.
|
|
80
81
|
|
|
81
82
|
**Hedge searches**: the search engine is noisy — run 2-3 query variations in parallel (`&` + `wait`) to increase hit rate.
|
|
82
83
|
|
|
83
84
|
Search queries: precise, API-ready — include asset class (`EURUSD vol FX`), expand shorthand (`JPY` not `yen`), canonical terms (`risk reversal skew`).
|
|
84
85
|
|
|
85
|
-
## Browser
|
|
86
|
+
## Browser
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
To open any web page, or when structured commands can't get the data:
|
|
88
89
|
|
|
89
90
|
```
|
|
90
91
|
marquee browser open <url> # navigate
|
|
@@ -98,3 +99,5 @@ marquee browser network request <id> # request detail
|
|
|
98
99
|
```
|
|
99
100
|
|
|
100
101
|
Snapshot → interact → re-snapshot. Use `network requests` for API debugging.
|
|
102
|
+
The browser is signed in as the user: for a consequential action (submit, save, delete, share, send), stop and ask the user to Take over.
|
|
103
|
+
Parallel subagents pass a unique `--session <name>` on every browser command and avoid `close --all`, which closes every agent's browsers.
|