› tarjan

Configuration

The tarjan.yaml schema — repos, tools, services.

name: myproduct
version: dev                           # named, reusable workspace (omit for a fresh one per run)
workspaceRoot: ~/tarjan/myproduct      # workspaces are materialised under here

requires:                              # tools that must exist before starting
  - name: git                          # no `services:` → baseline, always checked
  - name: docker
    optional: true                     # warn instead of fail if missing
    services: [postgres]               # checked only when postgres is in the selection
  - name: node
    minVersion: "20"
    mise: node@20                      # versioned runtime via mise (with --install)
    services: [api]

repos:                                 # cloned into the workspace
  - name: api
    url: https://github.com/your-org/api.git
    branch: main

services:                              # started in dependency order
  - name: postgres
    docker: { image: postgres:16, ports: ["5432:5432"], env: { POSTGRES_PASSWORD: dev } }
    health: { tcp: "localhost:5432" }

  - name: api
    workdir: api
    setup: ["npm install"]             # one-shot, runs once per workspace
    setupCheck: "test -d node_modules" # setup counts as done only if this passes
    command: "npm run dev"
    env: { DATABASE_URL: "postgres://postgres:dev@localhost:5432/postgres" }
    dependsOn: [postgres]
    health: { http: "http://localhost:8080/health" }
    restart: on-failure
    watch: { paths: ["src"] }

workspace: { vscode: true }

Workspaces & versions

With no version:, each tarjan up materialises a fresh, timestamped workspace under workspaceRoot (e.g. ~/tarjan/myproduct/20260628-150405/) — every run starts from a clean slate and old runs stay around for reference.

Set a top-level version: (or pass tarjan up --version <label>, which overrides it per run) to use a named, reusable workspace at <workspaceRoot>/<name>-<version> instead. Repeated up runs of the same version reuse the directory: already-cloned repos and finished setup steps are skipped, so it comes back fast. tarjan pull <version> updates that workspace's checkouts in place, and --workspace <dir> still overrides everything with an explicit path.

Different versions give you parallel environments side by side — e.g. --version feat-a and --version feat-b are independent checkouts you can keep on different branches. They coexist on disk, but only one can run at a time: services publish fixed host ports shared by every workspace, so a second running environment collides with the first ("address already in use"). Stop one (Ctrl+C or tarjan down) before starting the other — reuse makes the switch quick.

Required tools

Each requires entry declares a tool: name (looked up on PATH), minVersion, versionCommand, installHint, optional, and an install provider — mise (versioned runtimes), package (OS package managers), or a bespoke install command — run only with --install.

A tool may also list the services that need it. A tool with no services is a baseline, checked on every run; one that names services is checked only when at least one of them is in the run's selection — so a partial tarjan up web skips toolchains it won't use, and tarjan doctor <service> reports just what that service needs.

Service fields

FieldMeaning
nameUnique service name.
kindservice (default) or job (run-to-completion).
workdirWorking directory inside the workspace (usually a cloned repo).
setupOne-shot commands run once per workspace before first start.
setupCheckCommand that verifies setup succeeded; setup is recorded as done only when it exits 0, and a later run re-checks and re-runs setup if it now fails. Guards against a setup command that exits 0 without producing what it should (e.g. npm install printing "up to date" while a downloaded binary is missing).
commandLong-running command (ignored when docker is set).
dockerRun as a container: image, ports, env, volumes, args.
externalA cloud/remote dependency tarjan only health-probes.
env / envFileInline variables / .env files (files load before inline).
dependsOnServices that must be healthy (or, for jobs, complete) first.
healthReadiness probe: tcp, http, or command (+ timeout, interval).
restartCrash policy: no (default), on-failure, or always.
maxRestartsCap on automatic restarts (default 5; 0 = unlimited).
watchLive-restart on file change: paths + debounce.
optionalFailure → warning instead of aborting the whole up.
profilesGate the service to specific --profile groups.
remoteRun on a named SSH target from remotes: — see Remote targets.

Profiles & selective start

A service or repo with no profiles is always included; one with profiles is included only when a matching profile is active (--profile), it's named in --only, or it's pulled in as a dependency.

tarjan up                     # always-on services only
tarjan up --profile frontend  # + the frontend profile
tarjan up --only web          # web + its dependencies

Env files & secrets

A global envFile applies to every service; a per-service envFile applies to one. Precedence, lowest to highest: process env, global env files, service env files, inline env. Commit a .env.example and git-ignore the real .env*.

On this page