flaminis/dalaran/dalaran-blueprint

Claude Code and agent skill by flaminis/dalaran

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Design a Dalaran blueprint from the data, then iterate on it from headless screenshots. Read this when laying out a recording or dataset in the viewer, designing a default blueprint, or deciding which views show which entities. Covers archetype-to-view mapping, layout reasoning, the rrb construction API, the contents grammar, and the screenshot loop.

Install

npx vskill@latest install flaminis/dalaran/dalaran-blueprint

SKILL.md

Dalaran blueprint

A blueprint decides how a recording is shown; the recording decides what exists. Read the data, design a first layout, then iterate from screenshots until it reads at a glance. The constructors are discoverable (dir(rrb), help(rrb.Spatial3DView)); this skill covers what you can't guess. Import as import dalaran.blueprint as rrb.

1. Read the data

Enumerate every (entity_path, archetype) pair first — the archetype picks the view, the entity path scopes it. For a dataset (see dalaran-catalog-queries):

python
for c in dataset.schema().component_columns():
print(c.entity_path, c.archetype, c.component_name)

For a local recording, stream it with RrdReader and read entity_path and the archetype off each chunk (see dalaran-chunk-processing).

2. Map archetype to view

Archetype familyView
Points2D, Image, EncodedImage, Boxes2D, LineStrips2D, Pinhole projectionsSpatial2DView
Points3D, Mesh3D, Boxes3D, LineStrips3D, Transform3D, Asset3DSpatial3DView
Scalars, SeriesLines, SeriesPointsTimeSeriesView
TextLog / TextDocument / BarChartTextLogView / TextDocumentView / BarChartView
Tensor, DepthImage (heatmap)TensorView
GeoPoints, GeoLineStringsMapView
GraphNodes, GraphEdgesGraphView
tabular / catalog dataDataframeView

3. Group entities into views

This step is just deciding which entities share a view. Sizing and placement are mechanics you tune by eye in the screenshot loop, not rules to settle up front.

  • Group by shared path prefix. Entities under a common prefix usually belong

in one view. Don't give every entity its own pane: dozens of raw message entities go in one DataframeView, or get left out, rather than a pane each.

  • One spatial frame per spatial view. A whole Transform3D tree goes in one

Spatial3DView at the common ancestor; a Pinhole camera gets its own Spatial2DView rooted at the camera so images inherit the projection.

  • Collapse scalars. Many Scalars under a prefix → one TimeSeriesView over

the prefix, not one each. Split only when value ranges clash.

  • `column_shares`/`row_shares` are relative weights on a container's

children, equal by default. Tune them from the screenshots.

4. Construct it

Containers (Grid, Horizontal, Vertical, Tabs) hold views. Default a flat set to Grid; use the others for a deliberate split, Tabs for alternatives competing for one slot (left/right/depth cameras). Always set an explicit `origin` and `name` — origin defaults to /, which dumps the whole tree into one view (the usual cause of an unreadable blob).

python
blueprint = rrb.Blueprint(
rrb.Horizontal(
rrb.Spatial3DView(origin="/world", name="Scene"),
rrb.Vertical(
rrb.Spatial2DView(origin="/world/camera", name="Camera"),
rrb.TimeSeriesView(origin="/sensors", name="Sensors"),
),
column_shares=[3, 2],
),
rrb.TextLogView(origin="/logs", name="Logs"),
collapse_panels=True,
)

contents defaults to "$origin/**". Scope a view with include/exclude rules, e.g. contents=["+ $origin/**", "- $origin/internal/**"]. A bare line is an include; /** is the only wildcard (matches a subtree). Most-specific rule wins, ties go to the last, unmatched paths are excluded.

Coordinate frames. A spatial view only renders entities it can place relative to its target frame. Transform3D/Pinhole logged on entities compose down the tree, so origin is enough. But named frames (CoordinateFrame(frame=...), common in ROS/MCAP) live in a separate frame graph — point the view at a frame the data occupies via spatial_information=rrb.SpatialInformation(target_frame="<frame>"). The tell is an empty 3D view with "No transform path from <frame>…" errors: origin="/" targets the root tf#/, which connects to nothing if the tf tree was never materialized. Read the CoordinateFrame:frame values, target the one the main 3D content sits in, and exclude entities in unconnected frames.

5. Iterate from screenshots

Spawn the viewer and load the recording once, then re-send blueprints into the same viewer; each send + screenshot is one cheap iteration. Render, look, revise.

The blueprint binds to the data by store identity, both application id and recording id. A loaded .dlr keeps its own identity, so build the stream from the dlr's values (set both; recording_id otherwise defaults to a random one). Mismatch either and the viewer keeps blueprint and data as separate recordings and never applies the blueprint.

python
import time
import dalaran as rr
import dalaran.blueprint as rrb
from dalaran.experimental import ViewerClient, RrdReader
store = RrdReader("segment.dlr").recordings()[0] # the dlr's application id + recording id
with ViewerClient.spawn(headless=True, port=9879) as viewer:
rec = rr.RecordingStream(store.application_id, recording_id=store.recording_id)
rec.connect_grpc(url=viewer.url)
rec.log_file_from_path("segment.dlr")
def shot(blueprint, path):
rec.send_blueprint(blueprint, make_active=True, make_default=True)
time.sleep(2) # let the import finish and a frame render; bump if a view is blank
viewer.save_screenshot(path) # view_id=view.id for a single view
shot(blueprint_v1, "bp_v1.png")
# Read bp_v1.png, revise, send the next one into the same viewer.
shot(blueprint_v2, "bp_v2.png")

To bake a finished blueprint in instead, pass default_blueprint= to rr.init / spawn / connect_grpc / save, or blueprint= to notebook_show.

Gotchas

  • A DataframeView shows "Unknown timeline" without a query:

query=rrb.archetypes.DataframeQuery(timeline="<timeline>", apply_latest_at=True).

  • A view back blank? The importer may not have finished (bump the settle) or the

cursor sits before the data (add rrb.TimePanel(play_state=rrb.components.PlayState.Following)).

  • rrb views and ViewerClient (dalaran.experimental) are unstable. Check

help() if a constructor argument is rejected.

See also

  • dalaran-data-model — entities, archetypes, timelines.
  • dalaran-catalog-queries — enumerate entities in a dataset.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
738
Repository forks
32
7-day trend score
33

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/flaminis/dalaran/dalaran-blueprint/badge)](https://verified-skill.com/skills/flaminis/dalaran/dalaran-blueprint)

Something wrong with this skill or its page? Tell us.