5.6.8 Skyscope — Skyframe Visualizer
extraSkyscope turns one retained Skyframe graph into an interactive browser view. It
is useful when a label-level query is too coarse and the text from bazel dump --skyframe is too large or opaque to inspect directly. The boundary
is that it visualizes a snapshot of internal dependency state. It is not a
supported query API, an execution timeline, or a history of invalidations.1
The project remains available and its GitHub repository is not archived, but the latest published release is v0.4.3 from July 2024 and the repository's last code activity was also in 2024. Treat it as a specialist diagnostic aid with version-sensitive compatibility, not as a maintained part of Bazel's toolset. In particular, verify an import against the exact Bazel version that produced the graph before relying on it in an investigation.2
Install the tool outside the workspace
Current upstream instructions require Graphviz's dot executable. They offer a
prebuilt, statically linked Skyscope binary for Linux. MacOS users are directed
to build the backend from source with Nix. Put the resulting skyscope binary
on PATH and run it below the Bazel workspace whose server you want to inspect.
The older http_archive plus @skyscope//:import installation shown in the
2023 announcement describes v0.2.7 and is no longer the current workflow.1,2
Before collecting a real diagnostic capture, check these operational details:
- Skyscope starts a local HTTP server, using port 28581 by default, and stores
imports under
$HOME/.skyscopeunlessSKYSCOPE_DATAoverrides it. - Importing shells out to the
bazelfound onPATH.SKYSCOPE_BAZEL_BINcan select a different binary. - The imported graph and its optional enrichment can contain labels, paths, command lines, and other workspace details. Treat the database as diagnostic data, especially on a shared machine.
Capture the smallest graph that answers the question
Skyframe belongs to the long-lived Bazel server and changes as commands run. Populate that server deliberately, then import it:
bazel shutdown
bazel build //app:release
skyscope import --query='//app/...' --aquery='//app/...'
bazel shutdown is appropriate here only when a deliberately cold, bounded
snapshot answers the question. It discards the very incremental state you might
otherwise be trying to diagnose. If the symptom exists only in a warm server,
reproduce it first and import that server without clearing it. Record the Bazel
version, startup options, output base, workload, and import options just as you
would for a raw dump. 5.6.7 bazel dump — Internal State Inspection explains why that provenance matters.
Skyscope obtains topology from bazel dump --skyframe. By default it also runs
aquery 'deps(//...)' and query 'deps(//...)' --output build to decorate
otherwise terse nodes with action and target context. Those enrichment commands
can be slow, can fail when unrelated targets are broken, and can themselves
change the server graph. Narrow them with --query and --aquery, or use
--no-query --no-aquery when preserving the captured topology matters more than
friendly labels. A failed enrichment does not necessarily abort the topology
import. It leaves some context absent.2
The importer loads a snapshot into SQLite and the server presents a link in the
browser. Previously imported graphs are listed at http://localhost:28581 and
can be deleted there.2
Read nodes as SkyKeys, not BUILD targets
Search matches the key text printed by bazel dump --skyframe. % is a
wildcard. ConfiguredTarget, FileState, and ActionExecution are useful
examples, not an exhaustive support list. Skyscope imports the dependency graph
generically and displays the SkyFunction-derived node type plus raw key data.
Consequently, the node vocabulary and formatting follow Bazel internals and can
change between versions.3,2
This graph crosses several abstractions:
- A
ConfiguredTargetis configuration-specific. Similar labels may therefore denote different internal nodes. - A
FileStatenode represents filesystem state used by Skyframe's incremental evaluation, not a declared BUILD dependency by itself. - An
ActionExecutionkey identifies an action associated with a configured target and an action index. Optionalaquerycontext can recover a mnemonic, inputs, and outputs that the dump key alone does not explain.2
Edges mean that evaluation of one Skyframe value depends on another. They do
not establish wall-clock action order. Use 5.2.3 bazel aquery — Action Graph for the analyzed
action plan and execution profiles or the BEP for what actually ran. Likewise,
a snapshot may expose nodes associated with configurations and transitions, but
Skyscope does not replace 5.2.2 bazel cquery — Configured Graph for explaining a transition or
comparing configured target options.
Explore without rendering the whole graph
A fresh import initially hides every node. Search for one or two precise keys, make them visible, and expand outward:
- A collapsed node shows only edges to other visible nodes.
- Clicking it expands the node, exposing edges to hidden neighbors as small circles. Double-clicking reveals all neighbors.
- A dotted connection between visible components says that a dependency path
exists. Choose Open to reveal one such path, much like
somepath(). - Shift-select and crop to keep only the useful subgraph. Browser back and forward undo and redo exploration states.
This progressive reveal is the tool's main advantage over rendering an entire DOT graph. It is also where restraint matters: expanding a high-fanout internal node can still produce thousands of edges and slow Graphviz. Skyscope lets you interrupt a render and return to its last completed checkpoint.3,2
Use the picture to choose the next supported probe
Skyscope is strongest as a hypothesis generator:
- Reveal a path between an internal file node and a configured target, then use
cqueryto verify the configured target relationship. - Reveal an
ActionExecutionneighborhood, then use focusedaqueryoutput to inspect the action's declared inputs, outputs, owner, and command. - Notice unexpected internal fan-in or retained node families, then capture a filtered raw dump or compare controlled cold and warm experiments.
Do not conclude from a single picture that an edge caused a rebuild, that one action ran before another, or that a transition invalidated the analysis cache. The import contains the current dependency graph, not the before/after dirtying events needed to prove those claims. It can suggest where to instrument next. The producing command, profile, log, BEP, or controlled mutation supplies the causal evidence.
Import cost is another practical limit. The 2023 prototype could take minutes on large graphs and could exhaust memory because it first loaded the whole graph before writing SQLite. Upstream later implemented streaming import, so the old 10 GB Envoy anecdote is not a current architectural description. Large imports and high-fanout renders can nevertheless remain expensive, and neither the dump format nor Skyscope's parsing of it is a stable Bazel compatibility contract.1,2
Use Skyscope when you need an interactive, selectively revealed view of one
Bazel server's internal Skyframe dependencies. Install the standalone tool,
populate or preserve the server state deliberately, and narrow or disable its
default query/aquery enrichment according to the investigation.
Interpret nodes as version-sensitive SkyKeys and edges as evaluation
dependencies. Skyscope can reveal internal paths and neighborhoods, but it
cannot by itself prove execution order, rebuild causality, configuration
transition behavior, or why a cache was invalidated. Turn each visual clue into
a focused query, cquery, aquery, dump, profile, or BEP check.
Check your understanding · 4 questions
1.A Skyscope snapshot shows an unexpected path from a FileState node to a ConfiguredTarget. Which conclusions or next steps are justified?
Select all that apply
2.A team wants to try the current Skyscope release on Linux. Which setup follows the article's guidance?
Select one answer
3.How should you interpret nodes in an imported Skyframe graph?
Choose True or False for each sentence
4.A slow build appears only after several commands have reused the same Bazel server. What is the most useful Skyscope capture strategy?
Select one answer
Footnotes
-
Announcing Skyscope — motivation, snapshot workflow, path and action examples, and original performance limitations ↩1 ↩2 ↩3
-
Skyscope upstream repository — current installation, import and enrichment behavior, storage, supported graph interaction, release history, and project status (verified 18 July 2026) ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8
-
Visualizing Build Graphs with Skyscope — node semantics, progressive reveal, path opening, cropping, history, and render interruption ↩1 ↩2