Your first workflow

This tutorial walks you through writing and running your first Jaiph workflow. By the end of it you will have written a single .jh file, run it with the jaiph CLI, watched the live progress tree, and looked at the run artifacts the runtime writes under .jaiph/runs/.

This tutorial uses only script steps, so you do not need an agent backend, API keys, or Docker. The follow-up tutorial Your first agent + sandboxed run adds a prompt step and the Docker sandbox on top of what you build here.

What you will build

You will write a workflow with one script step that prints a greeting, and a return step that passes the script’s output back as the workflow’s return value. The whole file is five lines.

Prerequisites

Node, Docker, and API keys are not required for this tutorial. Runs use jaiph run --unsafe so the workflow runs on the host (Docker is on by default for jaiph run).

1. Install the CLI

Install the standalone binary:

curl -fsSL https://jaiph.org/install | bash

The installer downloads a per-platform binary, verifies its signature and checksum, and writes it to ~/.local/bin/jaiph. See Install and switch versions for other options, such as npm, JAIPH_BIN_DIR, and version switching.

Confirm the install:

jaiph --version

If the command is not found, prepend the install directory to PATH:

export PATH="$HOME/.local/bin:$PATH"

2. Write the workflow

Create a fresh directory and write a file named hello.jh:

script greet = `echo "Hello, ${1:-world}!"`

workflow default(who) {
  return run greet(who)
}

Here is what each line does:

3. Run it

jaiph run --unsafe ./hello.jh "Adam"

--unsafe sets JAIPH_UNSAFE=true for this run only and skips the Docker sandbox.

Because Docker is on by default, disabling the sandbox with --unsafe requires confirmation. The CLI prints a warning and waits for you to answer y:

⚠️ You are going to run the Jaiph workflow in the unsafe mode with no sandboxing. It has full access to your machine.

Continue? [y/N] y

Type y and press Enter. In a non-interactive context such as CI, add --yes or set JAIPH_INPLACE_YES=1 to skip this prompt.

Before any step runs, the CLI prepares the workflow in two steps:

After you confirm, you should see this (timings will differ):

Jaiph: Running hello.jh (Docker sandbox, unsafe)

  ⚠ You are running the Jaiph workflow in the unsafe mode with no sandboxing. It has full access to your machine.
workflow default (who="Adam")
  ▸ script greet (1="Adam")
  ✓ script greet (0s)

✓ PASS workflow default (0.2s)

Hello, Adam!

The first line is the sandbox banner. The workflow default row and the indented and rows are the live progress tree. A marks a step that has started, a marks a step that has finished, and (0s) is the elapsed time for that step. The root workflow row is static, and only nested steps print and lines. The blank line and Hello, Adam! after PASS are the workflow return value, which jaiph run prints on stdout after a successful run.

The (Docker sandbox, unsafe) banner reflects --unsafe. The workflow runs on the host with no container, and the runtime prints a warning that the workflow has full access to your machine. If you omit --unsafe, jaiph run uses the Docker sandbox by default, and the banner then reads (Docker sandbox, snapshot). If Docker is enabled but the daemon is unavailable, the CLI exits with E_DOCKER_NOT_FOUND instead of falling back to the host.

4. Inspect the run artifacts

Every run writes durable files under .jaiph/runs/<YYYY-MM-DD>/<HH-MM-SS>-<entry>/ in UTC. List the most recent run:

ls -la .jaiph/runs/*/*/

The layout you should see:

Read the captured script output and the return value:

cat .jaiph/runs/*/*/000002-script__greet.out
cat .jaiph/runs/*/*/return_value.txt

Both should match the line printed after PASS. The full artifact layout is documented in the durable artifact layout section of the architecture page. The event types in run_summary.jsonl are documented in the run artifacts section of the CLI reference.

Replace the script body with one that exits non-zero:

script greet = `echo "Hello, ${1:-world}!" && exit 7`

workflow default(who) {
  return run greet(who)
}

Re-run with the same arguments (confirm the --unsafe prompt again with y):

jaiph run --unsafe ./hello.jh "Adam"

The CLI prints a ✗ FAIL line on stderr, then a block with Logs:, Summary:, out:, and err: lines that point to the run directory, followed by an Output of failed step: excerpt. The process exits non-zero. return_value.txt is not written on failure, only on success.

Where to go next

Revert the failing script body so the workflow passes again, then pick a direction: