Divine

dv show

View as Markdown

dv show constructs a capturable render URL for a page, a block, or a side-by-side comparison of theme targets. It never takes a screenshot. The command prints a URL, and an agent or browser tool opens that URL to capture what it renders. Keeping capture out of the CLI means dv show has no browser dependency and stays fast, while the agent that already drives a browser does the part it is good at.

The URL it prints is short-lived and signed. Every render runs through a server-issued preview token, so the link renders the selected theme target and nothing else, then expires. This is the same preview-token model the rest of Divine uses, scoped down to one render.

This page covers the three subcommands, the flags that shape the output, and the three resolution layers that let the command work against a real local WordPress install rather than only inside a wired-up test harness.

The Three Subcommands

dv show has one job split across three target shapes. A page renders a worktree or app page as a standalone document. A block renders a single block. A compare renders several targets together so a human or agent can see them next to each other.

Subcommand What it renders
dv show page <slug> One page from the app or a worktree.
dv show block <name> One block from the app or a worktree.
dv show compare <targets...> A labeled grid of two or more targets.

You run the command from inside the theme directory, so the current directory tells Divine which app you are working in. The slug or block name is the only required positional argument for page and block.

To get a capturable URL for the home page of the current theme:

dv show page home

To get one for a block named hero:

dv show block hero

Compare Targets

dv show compare takes two or more target specifiers rather than a bare slug. Each specifier names a kind and an id, and may pin the target to the app or to a specific worktree with an @ suffix. The suffix is how you compare the same page across variants in one URL.

Target form Meaning
page:<slug> A page from the default app target.
block:<name> A block from the default app target.
page:<slug>@app A page explicitly from the app theme.
page:<slug>@<worktree> A page from the named worktree.
block:<name>@<worktree> A block from the named worktree.

A specifier without an @ suffix, or with @app, resolves to the app theme. Any other suffix is treated as a worktree id. Compare always renders the virtual document of each target, so --live and --worktree are rejected here; you express the worktree per target through the suffix instead.

To compare the app’s home page against the same page in a redesign worktree:

dv show compare page:home@app page:home@redesign

Each tile in the compare grid is labeled. A label is the variant, the kind, and the id joined together, where the variant is the worktree id or the word app. The two targets above are labeled app page home and redesign page home.

Render Modes

A page or block normally renders as a virtual document. Divine renders the snapshot of the selected theme target into a standalone HTML document and serves it from a signed Divine REST route. This is the default because it isolates the target: it shows the theme files as they stand, independent of the live site’s posts and options.

A page can also render in live mode with --live. Instead of the virtual document, this issues a signed preview URL onto the real site URL for that page, so the capture shows the page rendered against live site data with the selected theme active for that request. Live mode is page-only by design. Blocks have no live site URL of their own, so dv show block --live is rejected, and compare URLs are always virtual.

Mode Subcommands What it shows
virtual page, block, compare The theme target rendered as an isolated document.
live page only, with --live The page on the real site URL with the theme active for that request.

Flags

The flags shape which target is resolved, how wide it renders, how long the URL lives, and how the result is returned. None of them are required; the defaults match the most common capture.

Flag Effect
--worktree <id> Render the target from a worktree theme instead of the app theme.
--live Page only. Issue the live signed site URL instead of the virtual render.
--width <px> Set the render width passed into the URL. Defaults to 1440, and is clamped to a sane range.
--site <slug|id> On multisite, select the target subsite by network-site slug or numeric blog id.
--url <url> On multisite, select the target subsite by its site URL.
--ttl <seconds> Set the token lifetime in seconds. Defaults to 3600, clamped between 60 and one day.
--json Emit the URL plus metadata as JSON instead of a bare URL.
--output <path> Also write the isolated HTML document to a file at the given path.

A few combinations are rejected on purpose. --live is only valid for pages, never for blocks or compare. --worktree is not valid for compare, because compare targets carry their own @ suffix. --site and --url are mutually exclusive; pass one or the other. --output cannot be combined with --live, because there is no isolated document to write when the URL points at the live site.

Default Output

By default the command prints a single line containing the URL, which is all an agent needs to hand to a browser tool:

dv show page home
https://example.test/wp-json/divine/v1/apps/acme/show/page/home?divine-show-token=...&width=1440

JSON Output

With --json, the command prints a structured payload instead. The payload carries the url, the render mode, the token expires_at as a Unix timestamp, and a targets array describing each resolved target. This is the form to prefer when the caller needs the label, the resolved app slug, or the expiry rather than just the link.

dv show page home --json
{
  "url": "https://example.test/wp-json/divine/v1/apps/acme/show/page/home?divine-show-token=...&width=1440",
  "mode": "virtual",
  "expires_at": 1750000000,
  "targets": [
    {
      "kind": "page",
      "id": "home",
      "app_slug": "acme",
      "worktree_id": null,
      "label": "app page home",
      "mode": "virtual"
    }
  ]
}

Writing The Document To A File

--output writes the isolated HTML document to a file in addition to printing the URL. For a page or block this is the single rendered document; for compare it is the full labeled grid. Missing parent directories are created, and relative paths are resolved against the current directory.

dv show compare page:home@app page:home@redesign --output ./build/compare.html

The file is the same HTML the virtual URL would serve, so --output is useful when you want the artifact on disk without an HTTP round trip. It cannot be combined with --live, which has no isolated document.

Resolving A DB-Connected WordPress

dv show reads themes, tokens, and site state from a live WordPress, so before it resolves anything it has to reach a WordPress that is connected to the database. It does not assume it is already running inside WordPress. Instead it walks an ordered set of strategies and uses the first one that reaches a DB-connected runtime.

The command tries these in order:

  1. If WordPress is already loaded in the current process, it uses that. This is the case when dv show runs inside an existing bootstrap, such as a wp-env or test context.
  2. If DIVINE_WORDPRESS_BOOTSTRAP points at a readable file, it requires that file. Set this to a wp-load.php you know reaches the database when the other strategies cannot find one.
  3. It tries to delegate the whole command to wp-cli. It first probes with wp option get siteurl; if that succeeds, it re-runs dv show inside a wp eval-file so the command executes in WP-CLI’s already-connected runtime.
  4. It walks up from the current directory looking for wp-load.php, up to eight levels, and requires the first one it finds.

If none of those reach a DB-connected runtime, the command fails with exit code 2 and prints the strategies it probed, so you can see exactly where resolution stopped.

The wp-cli delegation matters most on local installs. On stacks like Local by Flywheel the database is reachable through a socket that WP-CLI is configured for but a raw require 'wp-load.php' from a plain CLI PHP process is not. By probing and then handing the command to WP-CLI, dv show reaches the database the same way wp does, instead of failing to connect. The delegated process is marked so it does not try to delegate again, which keeps the handoff from recursing.

Resolving The Right Stylesheet

A Divine theme directory does not have to be named the same as the stylesheet WordPress has installed. A symlinked theme, or a worktree directory, can sit at a path whose basename differs from the registered stylesheet. dv show resolves the stylesheet from WordPress rather than trusting the directory name.

It compares the real, canonical path of the current directory against the stylesheet directories that WordPress reports. It checks the active stylesheet and template first when a site is explicitly selected, then falls back to scanning every theme from wp_get_themes() and matching by real path. The match is on resolved paths, so a symlinked theme whose directory name differs from its installed stylesheet still resolves to the correct stylesheet. If you pass --app explicitly, that wins and no path matching is needed.

Resolving The Right Subsite

On a single-site install there is one site, and dv show targets it without any extra input. On multisite, the command has to target the subsite whose active theme is the one you are building.

When exactly one network site runs the theme, dv show resolves that subsite automatically from the app slug. When you need to be explicit, or when more than one site could match, you select the subsite directly:

Selector Resolves by
--site <slug> The network-site slug.
--site <id> The numeric blog id.
--url <url> The site URL, matched by host and path.

If a selector matches no site, the command reports that the site was not found rather than guessing. When several sites could match an ambiguous selector, it surfaces the candidates so you can pick one precisely. --site and --url are mutually exclusive, and both require a multisite install; passing --site on a single-site install is an error.

Exit Codes

dv show follows the same exit-code convention as the rest of the dv CLI. A successful run prints the URL or JSON and exits 0. A usage error, a failed WordPress resolution, or an internal error exits 2 with a message on standard error. There is no findings-style exit 1 here, because dv show resolves a URL rather than validating a theme.

Exit code Meaning
0 A URL or JSON payload was produced.
2 Usage error, WordPress could not be resolved, or an internal error occurred.