Development

August 9, 2026 · View on GitHub

How to set up, build, run, and release the workspace. This doc is the practical "how do I work in this repo" companion; testing and production-validity gates get their own doc, Testing and validation.

Layout & toolchain

  • Monorepo: pnpm workspaces (pnpm-workspace.yaml) over apps/* and packages/*. Package manager pinned to pnpm@11.x; Node >=20.
  • ESM + TypeScript everywhere: every package is "type": "module" with dual type exports; internal links use workspace:*.
  • web/ uses Bun + Nuxt and is a separate toolchain - its commands run from web/ with bun, not pnpm. Only its data/catalog side is in scope here (see Catalogs).
  • Versioning: packages align around SDK v3 / manifestVersion 3. The workspace version is owned by the root package.json; do not duplicate a frozen version number in docs.

The authoritative structural map is the root codemap.md plus per-folder codemap.md files; read those before editing a subsystem.

Root command surface

All from the repo root unless noted (full list in root package.json):

CommandWhat it does
pnpm buildBuild every package (pnpm -r build)
pnpm typecheckType-check every package
pnpm checkPer-package check (typecheck + build + contract checks)
pnpm testBuild, then run each package's tests
pnpm dev:desktopRun the desktop app in dev
pnpm dev:desktop:control-centerDev with renderer/Control Center focus
pnpm dev:desktop:pluginsDev with official plugins hot-loaded
pnpm dev:desktop:third-partiesDev with direct plugin folders under third-parties hot-loaded
pnpm package:desktop / :dirBuild + package the desktop app (full / unpacked dir)
pnpm release:desktopmacOS-local build, automatic SignPath Windows signing, and verified GitHub publication
pnpm release:npmPublish npm packages
pnpm plugins:*Plugin test/validate/package/publish/deploy (see below)

Plugin DX commands

CommandPurpose
openpets plugin new <name> --template <t>Scaffold an SDK v3 plugin
openpets plugin validate <dir>Validate a plugin locally
pnpm plugins:testLocale checks + official-plugin harness tests
pnpm plugins:checkDry-run the catalog package plan
pnpm plugins:packageBuild catalog + ZIP staging (no upload)
pnpm plugins:validate-releasePre-ship release gate
pnpm plugins:publishUpload ZIPs to R2
pnpm plugins:validate-livePost-deploy live check
pnpm plugins:deployDeploy the web catalog

See Plugin platform for the authoring workflow and Testing and validation for what the validators catch.

Running the desktop app

  • pnpm dev:desktop launches Electron against the TypeScript source with the Vite renderer dev server.
  • Plugin authors using the installed app do not need this repo: open Plugins → Developer Mode → Load unpacked plugin folder to validate, snapshot, watch, and reload a standalone plugin folder.
  • For plugin work, pnpm dev:desktop:plugins points the local loader at both plugins/official and plugins/dev (via OPENPETS_DEV_PLUGIN_ROOTS) so official plugins and in-progress dev plugins hot-load when working on OpenPets itself.
  • pnpm dev:desktop:third-parties loads every direct child of third-parties that contains openpets.plugin.json through OPENPETS_DEV_PLUGIN_ROOTS, with the plugin catalog disabled. Non-plugin folders are ignored, and changes to a discovered plugin's manifest or entry file hot-reload it.
  • Logs land in userData/logs/openpets.log (path varies by OS). Route renderer diagnostics into the app log, not just DevTools (per AGENTS.md).

The CSP footgun

Any renderer-visible URL scheme, image source, dev endpoint, or internal protocol must be added to the CSP in both apps/desktop/vite.config.ts and apps/desktop/src/renderer/index.html. Symptom of forgetting: images fall back to the default pet even though install/render logic is correct. See Desktop app.

Logging-as-DX

When working on renderer/IPC/catalog/plugin/pet-window behavior, add targeted, scoped logs as part of the change (data shapes, selected ids, load/error states, boundary decisions). Avoid noisy permanent logs, secrets, full payload dumps, or logging inside animation/render loops. The logger (apps/desktop/src/logger.ts) provides scopes and redaction. This is an explicit repo convention (AGENTS.md), not optional polish.

Release flows

npm packages

pnpm release:npm (scripts/release-npm.mjs) orchestrates publishing the workspace packages. Packages must build and pass check/test first.

Desktop app

pnpm release:desktop -- --yes (apps/desktop/scripts/release-local.mjs) does a macOS-local build + packaging, creates and pushes the release tag, dispatches the production SignPath Windows workflow, waits for its signed artifact, and only then creates a draft GitHub release, verifies its complete asset set, and publishes it. The local Windows installer is disposable; macOS and Linux artifacts remain unsigned.

The release runs as checkpointed stages recorded in apps/desktop/.release-state/v<version>.json. If an attempt is interrupted, re-run the identical command: finished stages are skipped and the release resumes where it failed, including re-attaching to the SignPath run that was already dispatched. Inspect the plan with --status, force a redo with --from <stage>, and discard the checkpoint with --reset. Do not warm up with pnpm release:desktop -- --dry-run; it rebuilds the whole artifact set and throws it away, and the checkpoint already makes retries cheap. SignPath may pause for manual approval in its dashboard while the release script visibly waits. electron-builder handles cross-platform packaging; bundled mode unpacks the integration CLIs and bundles plugins/official as extra resources (verified by the packaging contract - see Testing and validation).

Web catalog

Pet and plugin catalog deploys run from web/ with Bun (bun run deploy, pnpm plugins:deploy). Catalog generation/verification is in Catalogs and the release gates are in Testing and validation and Release guide.

Cross-platform & Linux testing

  • An Ubuntu 24.04 ARM64 VMware/Vagrant VM exists for Linux GUI testing. Details and host-side commands are in AGENTS.md (VM dir /Volumes/external/vmware/ubuntu24; guest checkout /home/vagrant/src/openpets; helpers cdpets + openpets-dx). Use the isolated guest clone, never the mounted macOS checkout (platform-specific node_modules).
  • Use the VM to validate Linux/Wayland renderer, tray, pet-window drag, IPC, plugin, and packaging behavior.
  • WSL cross-platform IPC (WSL client → Windows host over private TCP) is part of the protocol - see IPC and remote control.

Code intelligence

This repo has a CodeGraph index (.codegraph/) and an MCP server (codegraph_* tools) - a tree-sitter knowledge graph of every symbol/edge/file. Prefer it for structural questions (who calls X, what breaks if I change Y, where is Z defined) over grep. Read-only dependency clones for inspecting Electron / KWin behavior live under .slim/clonedeps/repos/ (do not edit). Both are described in AGENTS.md.

Conventions checklist

  • Match surrounding code style; keep comment density and naming idiomatic.
  • Update the matching docs/*.md and codemap.md when behavior changes.
  • Honor forward-only direction: no legacy compat in current runtime paths.
  • Validate at boundaries; atomic writes; reject path traversal/symlinks.
  • For plugin/catalog/i18n changes, follow the explicit "update docs / run validators" rules in AGENTS.md.