zframes

Skill file

Preview skill file
---
name: zframes
description: Build or update the user's personal zframes market dashboard. Use when the user says "/zframes", "build me a dashboard", "set up my terminal", "make me a market terminal", "add X to my dashboard", or wants a personalized live market dashboard (crypto + stocks). Writes a validated dashboard.json and serves it live with the CLI — the agent never writes React.
---

# zframes — your dashboard, generated

You set up the user's dashboard by driving the **zframes CLI** and writing a
`dashboard.json` spec. The CLI *is* the runtime: it serves a prebuilt dashboard
app pointed at that one file, editable in the browser. You only ever write JSON.
Never create or edit `.tsx` files for this task.

## 0. The CLI

The runtime ships as the `zframes` CLI on npm. Always invoke it with
**`npx --yes zframes@latest <cmd>`** — npx fetches the published CLI (which bundles the
dashboard runtime) per run, so there's nothing to clone, install, or keep
current. The commands you'll use below are `init`, `catalogue`, `lint`, and
`serve` (written `zframes <cmd>` for brevity — always run them through `npx`).

## 1. Pick where the dashboard lives — and scaffold it

The only artifact is a single `dashboard.json`. There is **no app to scaffold** —
the runtime comes from the CLI.

- **Updating an existing dashboard?** Find the `dashboard.json` the user is
  serving (or one in the current directory), read it first, and go to step 2 to
  change only what they asked for. Don't re-init — you'd wipe their frames.
- **New dashboard?** Pick a directory for it — the current directory, or a fresh
  one the user names (e.g. `~/zframes`) — then **scaffold the file with `init`
  instead of hand-writing the envelope**:

  ```bash
  npx --yes zframes@latest init <dir> --title "<dashboard title>" --author "<name>"
  ```

  This writes a bare, already-valid `<dir>/dashboard.json` — the fixed envelope,
  modelled on package.json: `version` (semver string), `title`, `author` (pass
  `--author` if the user gave a name, else it's left blank), then the 12-column
  `grid` (geometry — columns/rowHeight/`gap`), the unicorn `background`, the
  `theme` colours (`accentHue`/`accentSat` for the accent + `baseHue`/`baseSat`
  for the dark card-surface tint + `upColor`/`downColor` for gain/loss), the `typography` (`fontFamily`
  sans/mono/serif + `numericStyle` proportional/tabular + `scale` global text
  size), and the card-surface
  `appearance` (`radius`/`borderStrength`/`surfaceOpacity`/`density`/`elevation`) — with an
  **empty `frames` array**. You never author that boilerplate or its
  geometry by hand; you only fill in `frames` (step 4). The
  spec is `<dir>/dashboard.json`; that single file is everything the user owns.
  Any sibling files it references (a `daily-analysis.json` brief, a local image)
  live next to it in `<dir>`. `init` refuses to clobber an existing file unless
  you pass `--force`.

## 2. Read the catalogue — always, before generating

```bash
npx --yes zframes@latest catalogue > /tmp/zframes-catalogue.json
```

Then **read `/tmp/zframes-catalogue.json`** with your file reader (it's ~25 KB of
JSON Schema). Redirect to a file and read the file rather than reading the
command's piped stdout — that guarantees the *complete* catalogue even if the
shell truncates large piped output. Frame names, config fields, and enum values
come from here — never from memory. The catalogue grows; your memory doesn't.

## 3. Interview the user (first run = onboarding)

The interview has **one job: choose which tickers fill the dashboard.** It never
decides *which frames* — every dashboard ships the full market frame set (step
4); the funnel only picks the *symbols* that populate them. Keep it to a short
three-step funnel, each step narrowing from the one before:

1. **Stocks, crypto, or both?** The asset class. This is the only answer that
   changes the frame set — it gates the asset-specific frames (US-stock frames
   like `short-volume` for stocks; `bitcoin-dominance` / `tvl-treemap` for
   crypto; *both* → all of them). If they're vague, default to **stocks**.
2. **Which categories?** Built from their step-1 answer, so they pick from groups
   instead of recalling tickers cold. Offer a short multi-select menu:
   - **Stocks** → sectors: *Big Tech, Semiconductors, EV & Auto, Banks &
     Finance, Energy, Healthcare, Consumer & Retail*.
   - **Crypto** → themes: *Majors (BTC/ETH), Layer-1s, DeFi, Layer-2s, AI,
     Memecoins*.
   - **Both** → offer both groupings.
3. **Any in particular?** Within the chosen categories, ask them to name **3–5
   specific tickers** (free text — "NVDA, TSLA, AAPL"). Show and accept **plain
   tickers only**; the `xyz:` HIP-3 dex prefix is a framework internal you add
   silently when writing the spec ("TSLA" → `xyz:TSLA`; crypto stays bare). If
   they don't have specific names, **you pick representative liquid tickers** from
   their chosen categories — don't send them off to research. Note which 1–2 are
   the **main focus**; those drive the hero chart. If unsaid, take the first two.

That's the whole interview. Everything else — the full frame set, zones,
headings, the background, default config — is your call from the step-4 defaults;
never ask about it, and never read back frame or widget names as options.

This maps cleanly onto `AskUserQuestion`: step 1 is one question; step 2's options
are built from step-1's answer (a second round, not the same call); step 3 is the
free-text "Other" field. Label every option by **asset / category / ticker**,
never by frame name.

For "update my dashboard" requests, skip the funnel — read the existing
`dashboard.json` first and change only what they asked for.

## 4. Fill in the frames

Edit the file `init` scaffolded (or the existing one for updates): add objects to
the `frames` array. **Leave the envelope alone** — `version`, `grid`,
`background`, `theme`, `typography`, and `appearance` are already set; only
touch them if the user explicitly asks (e.g. "more spacing" → bump `grid.gap`,
"square corners" → `appearance.radius: 0`, "muted accent" → lower
`theme.accentSat`, "warmer/blacker cards" → shift `theme.baseHue` / lower
`theme.baseSat`, "terminal look" → `typography.fontFamily: "mono"`, "stop the
numbers jumping" → `typography.numericStyle: "tabular"`, "bigger/smaller text" →
`typography.scale`, "colourblind / custom gain-loss colours" →
`theme.upColor`/`theme.downColor`, "glassy cards" → lower
`appearance.surfaceOpacity`, "no animation" → `background.type: "gradient"`).

**Show the full frame set — every dashboard gets all the market frames.** You
don't cherry-pick frames by interest; build the whole comprehensive set and
populate the symbol-bearing frames with the user's tickers from the interview.
The only thing that varies the set is the **asset class** (step 1): the US-stock
frames for a stocks desk, the crypto frames for a crypto desk, all of them for
*both*. The pure-content frames (`note`, `image`, `dino-game`) stay opt-in — add
them only if the user asks; `heading`s are structure (added per the zone rules
below). Start from this spine (with the interview's symbols), then add the rest
of the catalogue's market frames around it:

- **`price-liveline` hero** — the user's 2–8 main symbols streaming together in
  one live race. Keep `normalize: true` so stocks and crypto share an axis.
  Place it big and up top: `w: 8–12, h: 3`.
- **Four `price-chart` cards on one row** — each `w: 3, h: 3` (3 × 4 = 12
  columns, so all four sit side by side on the same row), all
  `"interval": "5m"` (intraday), `title` = the ticker, and **color-coded** (a
  distinct `color` hex per card). Split the rendering two and two: two
  `"mode": "candle"`, two `"mode": "line"`. Default stocks picks when the user
  named fewer than four — **NVDA & TSLA as candles, AAPL & AMD as lines**
  (e.g. NVDA `#76b900`, TSLA `#e82127`, AAPL `#0a84ff`, AMD `#f5a623`). On a
  crypto desk, use the user's coins instead (e.g. BTC & ETH as candles, SOL & a
  fourth as lines).
- **`short-volume`** *(stocks desks only — FINRA reports US-equity short
  volume)* for the stock tickers (`"sort": "shortPct"`): `w: 5, h: 4`.
- **The macro trio — always include all three.** Keyless official-data context
  every dashboard should carry; group them in a row under a "Macro" heading
  (4 + 4 + 4 = 12 columns). None need config — schema defaults are sensible:
  - **`rates-board`** — NY Fed SOFR / effective fed funds / repo rates +
    Treasury average rates. `w: 4, h: 4`.
  - **`yield-curve`** — the US Treasury par yield curve + the 2s10s spread.
    `w: 4, h: 3`.
  - **`inflation-pulse`** — BLS CPI, month-over-month / year-over-year + trend.
    `w: 4, h: 3`.
- **`clock` + `market-hours` — always include both.** A `clock` set to the
  market's timezone (`"timezone": "America/New_York"`, `"label": "New York"`),
  `w: 3, h: 2`; and `market-hours` for exchange open / closed status with next
  open/close countdowns (`"exchanges": ["NYSE","NASDAQ"]` for a US-stocks desk,
  or leave it empty for the world set), `w: 4, h: 4`.
- **The rest of the catalogue's market frames — include them too**, so the
  dashboard reads as complete rather than sparse. From the catalogue you read in
  step 2, add the remaining market frames that fit the asset class:
  `top-movers`, `price-ticker`, and a normalized `price-compare` of the user's
  tickers on any desk; **`fear-greed`** for market mood; and when crypto is in
  scope, `bitcoin-dominance`, `tvl-treemap`, `funding-rate-chart`, and
  `funding-heatmap`. Symbol-bearing frames take the user's tickers; context
  frames need no config (schema defaults are sensible).

Layout rules for the frames:

- The grid is 12 columns, `rowHeight: 96` (set by `init`). Place each frame with
  an explicit `position: { x, y, w, h }` in grid units.
- **Group into zones.** Put a `heading` frame (full-width `w: 12, h: 1`) above
  each group of related frames — e.g. "Markets", "On-chain", "Desk". Headings
  render as bare section dividers (no card); they're what make a dashboard read
  as designed instead of a widget dump. A good dashboard has 2–3 zones.
- **Title each card.** Set a per-instance `"title"` (sibling of `frame`/`position`)
  to label the card; it overrides the default, which is just the frame-type name.
  Required on every `price-chart` — use the ticker (`"title": "TSLA"`, not
  `"PRICE CHART"`) so a wall of charts is readable. Useful on any frame whose
  type name is ambiguous; skip it for `heading` (bare, no card chrome).
- Big charts: `w: 6–12, h: 3`. Lists/tickers: `w: 3–4, h: 3`. Small cards
  (fear-greed, bitcoin-dominance): `w: 2–3, h: 3`.
- No overlaps; no frame past column 12; every `id` unique and human-readable.
- Only set config fields the user cares about — schema defaults cover the
  rest, except required fields (the catalogue's `required` list).

## 5. Lint — the feedback loop

```bash
npx --yes zframes@latest lint <dir>/dashboard.json
```

If it reports issues, fix the JSON and re-lint until clean. The error
messages name the frame instance and the exact field. Unknown frame names
come back with the list of valid ones — use it.

Renderer-level failures (a frame whose capability no provider covers) show
up as error cards in the running dashboard; treat those the same way.

## 6. Hand off — serve it

Serve the dashboard and open it for the user:

```bash
npx --yes zframes@latest serve <dir>/dashboard.json   # live at http://127.0.0.1:37263
```

`serve` hosts the prebuilt runtime pointed at that file, streaming live keyless
data. The user can drag, resize, add, and configure frames **in the browser** —
Save writes the changes straight back to `dashboard.json`. Edits to the file
(yours or theirs) show on reload, so further "add X to my dashboard" requests are
just another edit + the page reloads. Pass `--port <n>` if 37263 is taken.

## Hard rules

- **The interview only picks tickers, never frames.** Every dashboard ships the
  full market frame set (step 4); the onboarding funnel — asset class →
  categories → specific tickers — exists only to choose which symbols fill them.
  Never ask which frames or widgets to include, never show or read back frame
  names as options, and never make the user assemble the dashboard.
- dashboard.json is the only artifact. No React, no CSS, no new frames.
  If the user wants a frame that doesn't exist, say so and list what does.
- Free data only: Hyperliquid (crypto + HIP-3 stock perps), DeFiLlama,
  alternative.me, CoinGecko. There are no API keys to configure — never ask for one.
- Re-read the catalogue every session; never trust remembered frame names.

Source

Creator's repository · zentryhq/zframes

View on GitHub

Security

Security checks in progress
Results will appear here once audits complete
Checked by 3 independent security firms
Does it try to trick the AI?Not yet checkedPending · Gen Agent Trust Hub
Does it sneak in hidden code?Not yet checkedPending · Socket
Does it have known bugs?Not yet checkedPending · Snyk