Skip to content

Security and privacy

June is a library that runs in your process. It has no server and sends nothing to June itself: data leaves your machine only when your code calls a model, a provider or a trainer, and June writes files only where you point a store or a trainer. This page collects what goes where.

Training data, chat sessions and corpora are often sensitive: a person's private writing, customer emails, internal docs. Treat everything below that holds them the same way.

Data flow at a glance

SurfaceMay send externallyMay persist
Workflows and stepsprompts, messages and tool data, to the models and tools you configuretraces, results and snapshots, wherever your code saves them
Chateach turn's instructions, context and input, to the responder's modelthe session journal, in the ChatStore you choose
Copycorpus text and requests, to the teacher, writer and judge modelsvoice manifests, and prepared samples, wherever your code saves them
Evalscase inputs, to the target and any model-based gradereval runs, wherever your code saves them
Local trainingnothing but downloads: base model weights and Python packagesa run directory under .june/trl with the training data and weights; uv and HF caches
Managed trainingthe training and validation datasets and the job config, to the providerstaging objects in your Cloud Storage bucket and the tuned model, at the provider

"Local" holds only as far as every model involved is local: a hosted teacher, judge, grader or eval target still receives the text you give it. Fingerprints and hashes identify data; they aren't a confidentiality mechanism. Each provider keeps what it receives under its own terms and retention, and that's between you and the provider.

The sections below give the detail.

What leaves your machine

What runsWhat leaves your machine
a <Step>the agent's instructions and tool definitions, the prompt, and the loop's messages and tool results, sent to the agent's model on each call
a toolwhatever your tool's code sends; <Bash /> can run commands that send anything the process can
useStep()whatever your function sends
a chat turnthe instructions, the context and the new input, sent to the model or workflow answering it
summaryContext()the turns it summarizes, sent to the summarizer model
dataset(), splits, fingerprintsnothing
evaluate()each case's input, sent to the target (and any model-based grader)
trl()nothing but downloads: the model weights and Python packages. Training data stays local
vertex()the training and validation datasets, uploaded to your Cloud Storage bucket, and the job
prepareVoice()each sample's text and metadata, sent to the teacher model you chose
voice.write()the request and exemplar texts, sent to the writing model; candidates, to the judge
june doctornothing: it checks whether keys are set, not whether they work

When the data can't leave, use local models for the teacher, judge, graders and eval target too, not only for training.

Managed training stores your data with the provider. Delete the staging objects and tuned models when you're done with them.

What June writes to disk

June's own code writes files in two places, and only when you use them:

  • fileStore(dir) writes one JSONL journal per chat session in dir. See Chat.
  • trl() writes a run directory under .june/trl (or its dir option) holding a copy of the training data, the config, the runner's log, and the trained weights. See Local training. uv and Hugging Face also cache the packages and base model weights they download in their own cache directories.

Everything else June produces it returns to you as values: run results and traces, snapshots, job refs, training and voice manifests, eval runs and datasets. Where they're saved, and who can read them, is up to your code.

Treat .june/ as sensitive and keep it out of version control.

Credentials

June doesn't take model API keys: AI SDK providers read them, usually from the environment. june doctor only checks whether they're set and never prints their values.

Pass other credentials only where an option asks for them, such as vertex({ getAccessToken }) or trl({ env: { HF_TOKEN } }). June sends tokens only in request headers and keeps them out of refs, manifests, errors and traces. Don't put secrets in providerOptions, metadata, dataset metadata or prompts: those are meant to be stored and passed around.

The TRL runner gets your process's environment, plus trl({ env }), so it can read the same variables your app can.

What June's records hold

  • Run snapshots hold each finished step's result and cache key, as plain JSON. A result is whatever the step produced, model text included.
  • Traces (onUpdate, the resolved tree, june run --json) hold each step's prompt, status, timing, model id, usage, tool calls with their inputs and outputs, streamed text and result. An <Agent>'s node holds its id, model id and tool names, not its instructions or model settings. A <FineTune>'s node holds its job id, state, progress and result, and an <Evaluate>'s its results, which include case inputs and outputs. Traces never hold the training request or provider options.
  • june run prints step progress and tool inputs to stderr, and results to stdout. It never prints --input itself, even in errors, though input your workflow puts in a prompt or a result appears wherever those do, including --json's tree.
  • Training manifests record the base model, trainer, method, hyperparameters, dataset sources, sizes and fingerprints, the job ref and the artifact. They don't hold examples or providerOptions.
  • Voice manifests record the voice's name, the corpus's source, size and fingerprint, the artifact and training manifest if it was trained, and its settings. They don't hold the corpus's text.
  • Job refs hold what a trainer needs to find its job: ids, resource names, a run directory.
  • Dataset fingerprints are SHA-256 hashes. They identify data; they don't hide it from someone who can guess it.

Tools that run commands

<Bash />, and bashTool() from june/tools under it, runs commands on your machine with your process's permissions and environment. It is not sandboxed, and approval is a prompt for an operator, not a boundary. Commands and their output appear in traces and go to the model. See Tools.

Chat

A chat session's journal holds inputs, replies, steering, feedback and small provenance, in plain text. It never holds API keys, auth headers, instructions, raw provider requests or responses, workflow traces, or tool inputs and outputs, except where a reply itself quotes them. fileStore() creates its directory as 0700 and each journal as 0600, where the platform supports it, but doesn't encrypt them; memoryStore() keeps sessions only for the life of the process; your own ChatStore owns its access control, encryption and retention. June stores what it's given and doesn't authenticate who reads a session. See Chat: privacy and security and sessions and stores.

Training on what people wrote

Chat sessions, feedback and corpora become training data only when your code converts them; june/train reads sessions and never writes to their journals. Before training, read what you're about to train on: feedback is written by people, edits can carry mistakes or private data, and a session's content already went to whatever model answered it. See Learning from chat.

A voice is a model of a real person's writing. Train one only with their consent, on writing that's theirs: authorship hygiene keeps other people's words out of a corpus.