Skip to content

CLI

The june command runs the workflow or chat a file default exports, and june doctor checks your setup. Bun imports .tsx and .ts files directly, so there's no build step, and a file's models, providers and stores are whatever its code builds: there are no provider or model flags.

NeedCommand
Run a workflowjune run review.tsx
Open an interactive conversationjune chat chat.ts
Ask once, or script a chatjune ask chat.ts "…"
Check Bun and provider keysjune doctor

The CLI comes with the package as node_modules/.bin/june and requires Bun 1.2 or later. Run it as bunx june if it isn't on your PATH; Install covers setup.

june run

june run review.tsx

Renders the component the file default exports and runs it to completion. The Quickstart walks through a first run, and Running workflows covers what a run does. With options:

june run triage.tsx --input '{"repo":"johno/june","issues":[12,15]}'
june run triage.tsx --input-file ./triage.json
june run review.tsx --json > review.json
june run review.tsx --timeout 60000
  • The file must default export a workflow component. june: cannot find <file> if it doesn't exist, and june: <file> must default export a workflow component if its default export isn't a function.
  • Progress goes to stderr for each <Step>, <FineTune> and <Evaluate> as it starts (▸ id), calls a tool (↳ tool {input}), streams text, and finishes (✓ id) or fails (✗ id: message). A useStep or <Write> prints no progress, only its result.
  • Results go to stdout once every step has finished: each step's result under ── id, in the order the steps finished. A failed run prints no results, only the error on stderr.
  • Tools. The CLI doesn't add tools to a workflow: it runs the tools the workflow's own <Agent> declares, including <Bash />.
  • Approvals. When a step asks to run a tool that needs approval, june run asks on stderr, ? Allow <tool> {input} (step <id>)? [y/N], and reads the answer from stdin. y or yes approves; anything else, or the end of stdin, denies.

Options

  • --input <json> passes a JSON object to the component as its props, as run(<Workflow {...input} />) would. It must be an object: june: --input must be a JSON object of the workflow's props for anything else, and june: --input is not valid JSON when it doesn't parse. June never prints the input itself, even in errors; input your workflow puts in a prompt or a result shows up wherever those do, including --json's tree.
  • --input-file <path> reads the props from a JSON file, relative to the current directory. Use one of --input and --input-file, not both. Without either, the props are {}.
  • --json prints the whole result to stdout as one JSON object once the run succeeds (a failed run prints nothing to stdout): steps (each result, by step id), usage (the tokens the run used, when steps reported any) and tree (the run's trace). Progress stays on stderr, so stdout parses. Use it for anything that reads the output: the plain text format may change, the JSON follows the compatibility rules.
  • --timeout <ms> aborts the run after that many milliseconds, a positive number. A run that times out fails with june: The operation timed out.

Exit status

  • 0 when every step finished.
  • 1 when a step failed, the run timed out, or the file or options were wrong. The message is on stderr, after june: .
  • 130 when you pressed Ctrl-C. The first Ctrl-C aborts the run; a second exits at once.

june chat

june chat chat.ts

An interactive chat in your terminal with the chat a file default exports, such as one made with createChat() from june/chat. Chat covers what a chat is and how sessions work.

import { openai } from "june/sdk/openai";
import { createChat, fileStore } from "june/chat";

export default createChat({
  model: openai("gpt-5-mini"),
  instructions: "You are helping build June.",
  store: fileStore(".june/chat"),
});
$ june chat chat.ts
session 4f9c…e1
/new starts a session, /session prints its id, /feedback up|down rates the last reply, /quit exits

> What is June?
June is a declarative runtime for AI workflows…

> Say that in five words.
Declarative AI workflows, in React.

>

A chat in the terminal's normal scrollback, not a full-screen app. Replies stream to stdout; the > prompt, the session id and status go to stderr. A blank line separates turns.

  • --session <id> reopens a saved session: june chat chat.ts --session <id>. It needs a persistent store, such as fileStore(".june/chat"). With the default memoryStore(), a session ends with its process, and --session fails with no chat session.
  • Commands. /new starts a new session, /session prints the current id, /feedback up or /feedback down rates the last reply, and /quit or Ctrl-D exits.
  • Ctrl-C while a reply streams cancels that turn (it's recorded as canceled and left out of later context) and returns to the prompt. Ctrl-C at the prompt exits with status 130.
  • Errors. A failed turn prints its error and returns to the prompt.
  • Approvals. When a workflow chat's step asks to run a tool that needs approval, it asks on stderr, like june run: y approves, anything else denies.

Sessions and stores covers what a session stores and how it reopens.

june ask

june ask chat.ts "Explain this package"

One turn with the same chat, for scripts. The prompt is the remaining arguments, or stdin when there are none:

june ask chat.ts --session <id> "And its tests?"
git diff | june ask chat.ts
june ask chat.ts --json "Explain this package" > reply.json
june ask chat.ts -- "-h means help?"

The reply streams to stdout, followed by a newline, and session <id> goes to stderr, so --session can continue the conversation later. With --json, the id is the object's sessionId instead.

  • --session <id> continues a saved session.
  • --json prints exactly one JSON object to stdout once the turn completes, and nothing else.
  • -- ends the options, so a prompt can start with -.
  • Approvals are asked on stderr and answered on stdin, so a prompt piped on stdin leaves nothing to answer with and the call is denied.
{
  "sessionId": "4f9c…e1",
  "turnId": "b2d1…07",
  "text": "June is a declarative runtime for AI workflows…",
  "metadata": {
    "responder": { "kind": "model" },
    "model": { "provider": "openai.responses", "modelId": "gpt-5-mini" },
    "usage": { "inputTokens": 24, "outputTokens": 31, "totalTokens": 55 },
    "finishReason": "stop"
  }
}

metadata is the turn's provenance. A failed turn exits 1 with the error on stderr, and Ctrl-C cancels it and exits 130.

june doctor

june doctor
june doctor review.tsx

Checks that Bun is 1.2 or later and which provider API keys are set, without calling a model.

  • With a file, it finds the providers the file and its local imports use: each june/sdk/<provider> or @ai-sdk/<provider> import, and a gateway model string such as "anthropic/claude-sonnet-5-5". It reports the key each needs and exits 1 if one is missing.
  • Without a file, it lists every key it knows and exits 1 only if none is set.
ProviderKey
@ai-sdk/openaiOPENAI_API_KEY
@ai-sdk/anthropicANTHROPIC_API_KEY
@ai-sdk/googleGOOGLE_GENERATIVE_AI_API_KEY
@ai-sdk/groqGROQ_API_KEY
@ai-sdk/mistralMISTRAL_API_KEY
@ai-sdk/xaiXAI_API_KEY
AI GatewayAI_GATEWAY_API_KEY

It doesn't check that a key is valid, or that the model a file names exists. Those show up when you run.

Help and version

  • --help, -h, june help or june alone prints the usage, options and examples.
  • --version, -v prints the installed version.
  • An unknown command exits 1 with june: unknown command <name>, run 'june --help' for usage.