Skip to content

Quickstart

In five minutes you'll write a component, run it from the terminal, and see how nesting becomes a dependency and <Parallel> becomes independent work. Start after Installation.

Check your setup

With OPENAI_API_KEY set, run:

june doctor
✓ bun 1.3.0
· ANTHROPIC_API_KEY is not set (anthropic)
…
✓ OPENAI_API_KEY is set (openai)
· XAI_API_KEY is not set (xai)

If OPENAI_API_KEY shows not set, set it before going on.

Write a workflow

A workflow is a React component that a file default exports. Save this as brief.tsx:

import { openai } from "june/sdk/openai";
import { Agent, Parallel, Step } from "june";

export default function Brief({ topic }: { topic: string }) {
  return (
    <Agent
      model={openai("gpt-5-mini")}
      instructions="You write short, plain technical briefs."
    >
      <Step id="outline" prompt={`Outline a one-page brief on ${topic}.`}>
        {(outline) => (
          <Parallel>
            <Step
              id="brief"
              prompt={`Write the brief from this outline:\n${outline}`}
            />
            <Step
              id="questions"
              prompt={`List three questions a reader will ask about:\n${outline}`}
            />
          </Parallel>
        )}
      </Step>
    </Agent>
  );
}

Read it as a tree. outline must finish before its children can render, because they're a function of its result. brief and questions are independent inside <Parallel>, so they start together. There's no separate graph to define.

  • <Agent> sets the model and instructions for every step inside it. The model is an AI SDK model, passed straight through.
  • Each <Step> is one call to the agent, named by its id: a single model call here, or a whole tool loop when the agent has tools.
  • topic is an ordinary component prop. A workflow's props are its input.

Run it

june run brief.tsx --input '{"topic":"React Suspense"}'

june run prints progress to stderr as steps start (▸) and finish (✓):

▸ outline
✓ outline
▸ brief
▸ questions
✓ questions
✓ brief

Then it prints each step's result to stdout, under its id, in the order the steps finished:

── outline
…
── questions
…
── brief
…

outline ran first, then brief and questions ran at the same time. Which of those two finishes first depends on the model.

Use the output

The plain text is for people. To hand the run to a script, add --json:

june run brief.tsx --input '{"topic":"React Suspense"}' --json > brief.result.json

stdout is then one JSON object: steps (each step's result, by id), usage (the tokens the run used), and tree (the run's trace). Progress still goes to stderr, so stdout stays clean to parse or pipe into the next program.

Pass input from a file

--input takes the workflow's props as a JSON object. For anything longer, put them in a file and pass --input-file:

{ "topic": "React Suspense" }
june run brief.tsx --input-file brief.json

June doesn't echo the input, even in errors, and refuses anything that isn't a JSON object. Input your workflow puts in a prompt or a result still shows up in its output.

If it doesn't run

  • OpenAI API key is missing: the step fails with a ✗ and june run exits 1. Set OPENAI_API_KEY, or put it in a .env file where you run june.
  • june: command not found: run it as bunx june.
  • A model error from the provider: openai(...) takes OpenAI model ids. For another provider, install its package and use its model function.

Installation and the CLI reference cover the rest.

Next

Read React as the workflow next: branches, fan-out, recovery, approvals and resuming, with the same components. The CLI is the reference for every command and option.