This page is for people working on Plaid itself. If you only want to run Plaid, download plaid.jar from the releases page and follow the Quick Start instead. You do not need any of the tooling below.

1. Ports

Plaid listens on 8080 by default. Everything in the documentation assumes that port.

The one exception is the development server (clojure -X:dev), which listens on 8085 so that it does not collide with a release jar running on the same machine. That override lives in plaid-core/resources/config.dev.toml and is never written to data/config.toml.

To change the port a release jar uses, edit [server] port in data/config.toml (written automatically on first launch) and restart:

[server]
port = 9090

2. Repository Layout

Plaid is a monorepo:

plaid-core/

The Clojure server: REST API, data model, storage, audit log, query engine. Also holds this documentation under docs/.

plaid-ud/

The bundled Universal Dependencies editor (a Vite/React SPA), served from the jar at /ud/.

plaid-igt/

The bundled interlinear glossed text editor (a Vite SPA), served from the jar at /igt/.

plaid-dict/

The bundled dictionary reader (a Vite/React SPA), served from the jar at /dict/.

plaid-ui/

The component and helper package the three SPAs share. Not published: each app resolves it from the checkout.

plaid-agent/

The Python assistants for UD and IGT, one distribution named larc-plaid-agent. Installed from a checkout, not published.

plaid-client-js/

The official JavaScript client, published to npm as @larc-iu/plaid-client.

plaid-client-py/

The official Python client, published to PyPI as larc-plaid-client.

examples/

Small standalone demos built against the clients.

bb/, bb.edn

The babashka task runner that drives builds, tests, and releases.

3. Building From Source

Builds are driven by babashka tasks defined in bb.edn, which reproduce the release workflow (.github/workflows/release.yml) locally, everything except publishing. Run every task from the repository root.

3.1. Prerequisites

  • JDK 21 or later

  • Clojure CLI tools

  • babashka (bb)

  • Node.js 20 or later, for the two bundled SPAs. If you use nvm, activate it first (e.g. nvm use 24). The build fails fast with a hint if the active Node is too old.

  • Python 3, only if you want to build the Python client. Activate the environment you want it built into (e.g. mamba activate base) before running, since the build cannot activate one for you. Otherwise skip it with --skip-clients.

3.2. Build

bb build

This builds both SPAs, bundles them and the official services into plaid-core/resources/, compiles the uberjar, boot-smoke-tests it against /health on port 8080, and packs the npm tarball plus the Python sdist and wheel. Artifacts land in dist-artifacts/:

java -jar dist-artifacts/plaid-0.0.0-alpha.0.jar

The version defaults to 0.0.0-alpha.0 and may be given as an argument (bb build 0.2.0-alpha.1). In CI the git tag is the sole source of truth for the version. Locally it is just an argument.

Useful flags:

  • --skip-clients: build only the jar (skips npm and Python packaging, and their toolchain requirements).

  • --no-smoke: skip the jar boot test. Needed if something else already answers on port 8080.

Note
bb build leaves the built SPAs, services, and version.edn inside plaid-core/resources/ (all gitignored). Run bb clean to remove them before starting a plain development server, or the dev server will serve the stale bundled SPAs.

3.3. Other Tasks

bb test

Run the full plaid-core test suite, the same gate CI runs before building.

bb ci

bb test followed by bb build: the whole non-publishing release pipeline.

bb docs

Build this documentation site into _site/ for local preview. Requires gem install asciidoctor coderay.

bb clean

Remove all local build outputs.

bb release <version>

Tag and push a release, and CI does the rest. Requires a clean tree on master.

Run bb tasks for the full list.

4. Working on plaid-core

  • clojure -X:dev: start a REPL, then type (start) to bring up the development server. See localhost:8085

  • clojure -M:test: run the tests

  • clojure -M:test --jobs auto: run them on several JVMs at once (half the cores, at most 8), balanced by src/test-runner/test-timings.edn. --jobs N picks the count, --shard I/N runs one shard of that split, --record-timings rewrites the timings file, and --slowest K lists the slowest tests.

  • clojure -M:outdated: find outdated dependencies

  • clojure -X:uberjar: compile the jar alone (without the SPA bundling bb build does)

  • clojure -M:nrepl: start an nREPL server

  • clojure -M:format fix: apply cljfmt, the project’s formatter

Note
The client libraries are maintained separately in plaid-client-js/ and plaid-client-py/, each with its own tests.

4.1. OpenAPI Support

(On a release jar, substitute port 8080.)

5. Working on the SPAs

Each SPA is an ordinary Vite project. From plaid-ud/ or plaid-igt/:

npm install
npm run dev

The dev servers proxy API requests to the development server on port 8085. See each project’s vite.config.js. JavaScript, JSX, and CSS in the apps and plaid-ui are formatted by Prettier, and plaid-core’s Clojure by cljfmt, both applied to staged files by the tracked hook in .githooks/ (enable once per clone with git config core.hooksPath .githooks).

The tests and scripts that read real sample files (FieldWorks backups, .flextext exports) look for them in ~/.plaid_fixtures, or in the folder the PLAID_FIXTURES environment variable names, and skip with a note when a file is missing.

6. Database Access

Plaid stores everything in a single SQLite database at data/plaid.db (configurable via [database] path). You can inspect it with any SQLite client:

sqlite3 data/plaid.db

The database runs in WAL mode, so a plain file copy misses un-checkpointed writes in the -wal sidecar. For an ad-hoc backup of a running server, use the SQLite backup API:

sqlite3 data/plaid.db ".backup /path/to/backup-$(date +%F).db"

The server also takes automatic nightly snapshots. See the [backup] section of data/config.toml.