Docs

ppm and Core Packages

Overview

Tranquil uses a forked version of ppm (Pulsar’s package manager) called tranquil-ppm, tracked as a git submodule at ppm/. Settings-view calls ppm ls --json to populate the Packages settings panel. The output has four sections: core, dev, user, git.

The _atomPackages problem

In a production Pulsar build, the bundler writes a _atomPackages field into the root package.json (inside the asar). This is a complete snapshot of every bundled package’s metadata, and ppm reads it to populate the core list.

In dev builds (running from source), no _atomPackages exists. The upstream ppm silently returns an empty core list when the field is missing.

Do not add _atomPackages to the root package.json manually. At startup, src/package-manager.js sets this.packagesCache directly from _atomPackages. A partial list (e.g. only our 5 owned packages) causes all other core packages — tree-view, status-bar, settings-view, etc. — to be invisible to the package manager, resulting in a blank screen.

The fix in tranquil-ppm

tranquil-ppm patches src/list.js to fall back to packageDependencies when _atomPackages is absent:

if (!atomPackages && packageJSON.packageDependencies) {
  packagesMeta = Object.keys(packageJSON.packageDependencies)
    .map(name => {
      try {
        return JSON.parse(fs.readFileSync(
          path.join(resourcePath, 'node_modules', name, 'package.json')
        ));
      } catch (_) { return null; }
    })
    .filter(Boolean)
    .filter(metadata => this.isPackageVisible(options, metadata));
}

packageDependencies in package.json lists every bundled package (Pulsar core packages plus our owned packages). Their metadata is read live from node_modules/, so owned packages (which are symlinked via link:../) always reflect the current source.

New-package corollary. This fallback reads node_modules/<name>/package.json for each packageDependencies entry. A newly added owned package that lacks its node_modules/<name> symlink is skipped by the try/catch (the read throws), so it is invisible in Settings — the same missing symlink also stops it from loading at all under yarn start. Creating the node_modules/<name> symlink fixes both. See Adding a New Owned Package.

ATOM_RESOURCE_PATH

ppm determines which package.json to read via ATOM_RESOURCE_PATH. Without it, ppm runs mdfind to locate the installed app bundle — which in development finds whatever Tranquil build is in /Applications, and reads its (potentially outdated) _atomPackages.

scripts/dev.js sets this env var explicitly before spawning Electron:

ATOM_RESOURCE_PATH: path.join(__dirname, '..'),

This points ppm at tranquil-client’s own package.json, where the fallback reads current metadata from node_modules/.

Note: ATOM_RESOURCE_PATH is only read by ppm. Electron’s main process determines its resource path via command-line arguments passed by the launcher; it does not read this env var.

settings-view patches (packages/settings-view/lib/package-card.js)

The upstream package-card has been patched to support Tranquil-owned packages:

  • Local logo: checks for resources/logo.png in the loaded package’s directory and uses it as the avatar instead of fetching from GitHub
  • Author display: uses package.json’s author.name field as the display name (falls back to GitHub username extracted from repository)
  • Author link: uses author.url for the click target (falls back to pulsar-edit.dev/users/...)

All owned packages (tranquil-automations, tranquil-browser, tranquil-config, tranquil-theme-dark, tranquil-theme-light) have author, repository, resources/logo.png, and resources/logo.svg set accordingly.

Production builds (TBD)

A production build will need to generate _atomPackages and write it into package.json before bundling into an asar. At that point, the tranquil-ppm fallback path will not be reached (production builds have _atomPackages), and ATOM_RESOURCE_PATH will not need to be set (the asar contains the correct resource path).

The generation step — iterating packageDependencies, reading each package’s metadata, and writing _atomPackages — needs to be added to the build pipeline. Owned package metadata should be taken from their repos at the pinned version used in the build.