Extensions overview

Extensions are manifest-driven fence-block renderers. They add new rendered output to Sigla without modifying the app itself — a directory with a sigla.json manifest plus, optionally, some assets and a process binary spec.

This page explains what’s already there, how user extensions get loaded, and what to expect when you install one. For authoring your own, see Extensions — authoring.

Bundled extensions

Three extensions ship inside the signed Sigla.app:

ExtensionFence labelsRender kindNeeds external binary?
PlantUMLplantumlprocessYes — brew install plantuml
Graphvizdot, graphvizprocessYes — brew install graphviz
GherkingherkintemplateNo

Each appears in Settings (⌘,) → Renderers with a bundled (blue) badge. They load even when you have no ~/.config/sigla/extensions/ directory.

When a process-backed extension’s binary isn’t installed, the fence renders a placeholder telling you the brew install command. The source stays visible — nothing disappears.

Two render kinds

  • template — pure HTML substitution. The manifest declares an HTML template with {{SOURCE_ATTR}} and {{SOURCE_BODY}} placeholders, which Sigla fills with attribute-escaped and body-escaped versions of the fence contents. Gherkin works this way.
  • process — Sigla spawns a configured binary, pipes the fence body to its stdin, and renders the binary’s stdout as SVG, HTML, or plain text. PlantUML and Graphviz work this way.

User extensions

Drop a directory into ~/.config/sigla/extensions/<id>/ with a sigla.json manifest inside, then press ⌘⇧R (View → Reload Extensions). The extension shows up in Settings → Renderers with a user (green) badge.

[!NOTE] Sigla respects $XDG_CONFIG_HOME if set. If you’ve moved your XDG config root, extensions live at $XDG_CONFIG_HOME/sigla/extensions/.

Quick install path

For an extension shared as a directory (zip, git clone, copy-paste from /Applications/Sigla.app/Contents/Resources/Extensions/):

# 1. Drop the directory into place.
cp -R ~/Downloads/my-extension ~/.config/sigla/extensions/my-extension

# 2. Tell Sigla to rescan.
# In Sigla: press ⌘⇧R (or View → Reload Extensions).

# 3. Verify it loaded.
# Settings → Renderers should list it with a green `user` badge.

The directory name must match the id field in sigla.json exactly — they’re cross-checked at load.

Override warning

If you install a user extension with the same id as a bundled one, the user copy wins (that’s the whole point of being able to override). Sigla:

  1. Surfaces an amber override chip in Settings → Renderers.
  2. Prompts once, on first appearance, asking you to confirm the replacement.

[!WARNING] A user-installed extension can declare a different binary, different assets, and different HTML. Id-shadowing is the highest-value attack surface for extensions, so the override is deliberately friction-y. Accept only if you actively chose to override the bundled version.

The kill switch

Settings (⌘,) → Renderers → Enable extensions turns off all extensions, bundled and user alike. Built-in renderers (Mermaid, Vega-Lite, CSV/TSV) stay on. Useful for:

  • Confirming a rendering bug isn’t extension-induced.
  • Temporarily disabling everything while debugging a broken user extension.
  • Running Sigla in a known-minimum-surface mode.

Per-extension toggles let you disable a single extension without affecting the others.

Security model (high level)

User-installed extensions go through extra guarding that bundled extensions don’t need:

  • HTML strings (render.html, missing.html, error.html) pass through an allowlist sanitizer. No <script>, no on* handlers, no javascript: URLs, no unknown tags.
  • Process spawns are constrained: absolute binary paths only (no PATH lookup), literal args (no source-body templating into args), stdin-only input, enforced timeouts, environment-variable allowlist.
  • Manifest hard limits: 64 KB manifest, 32 assets per extension, 2 MB per asset file, 50 MB per directory, 16 KB per HTML slot. Violations are reported in the Diagnostics section.

Bundled extensions bypass HTML sanitization — trust derives from the app’s code signature, and the bundled sigla.json files are SHA-256-verified at load.

For the full schema and limits reference, see Extensions — authoring.

Reload semantics

⌘⇧R (View → Reload Extensions) re-scans both directories and:

  • Picks up new extensions you’ve just dropped in.
  • Picks up edits to existing manifests and assets.
  • Re-runs validation. An extension that broke between reloads moves into Diagnostics; one that was fixed moves back into Installed.
  • Re-resolves process binaries — useful after brew upgrade plantuml mid-session.

The currently open document re-renders automatically after a reload.

Where extensions come from

  • Personal: write your own, drop it in ~/.config/sigla/extensions/.
  • Shared: open a PR to github.com/slantedt/sigla/extensions/. Curated extensions will surface in an in-app catalog in a follow-up phase, once a few entries exist.
  • Bundled: contribute upstream via the main repo if your extension belongs in the default install.

Cross-references