Upload Your First Run
Use this page when local checks already work and you want shared evidence in Glubean Cloud.
Upload does not change what you author. You still author contracts, workflows,
and raw test() checks in git. Cloud stores the derived run evidence under a
Target so the team can inspect history, failures, performance, documentation
links, and agent explanations from the same source.
If you want Cloud Specifications to update from the current source model
without waiting for a run, use glubean sync. Sync publishes
project-level projections; upload publishes target-level execution evidence.
Before you start
- A Glubean verification project exists
npx glubean runalready works locally- You have access to a Glubean Cloud project
1. Create a token
In Glubean Cloud, open Settings → Tokens and create a scoped token with
the runs:write scope. Every token starts with glb_. Copy the value now —
Glubean won’t show it again.
A glb_ token is bound to you within your org (not to a single project), so the
project and target you upload to are supplied separately (next step). For the
difference between scoped and personal tokens, see Tokens.
Device login (
npx glubean login) is the intended interactive flow but the server endpoints aren’t live yet, so create the token in the dashboard and provide it directly for now.
2. Store the token
Local development
Put the token in .env.secrets (must be gitignored), and the project + target
IDs in .env (committed):
# .env.secrets — NOT committed
GLUBEAN_TOKEN=glb_your_token# .env — committed; shared by every contributor
GLUBEAN_PROJECT_ID=prj_abc123
GLUBEAN_TARGET_ID=tgt_def456The project and target IDs aren’t sensitive and belong in the repo (.env).
The token is sensitive and goes in .env.secrets. Because they’re env vars,
every run mode — npx glubean run --upload, npx glubean ci run --upload, or a
filtered/tagged run — uploads to the same project/target. (If the project has a
single default target you can omit GLUBEAN_TARGET_ID.)
Working on multiple Glubean projects from one laptop? See Multi-workspace setup.
CI
Store the scoped (runs:write) token in your provider’s secret store and inject
it as the GLUBEAN_TOKEN env var. The CLI auto-picks it up. Do not run
npx glubean login in CI.
GitHub Actions example:
- name: Upload Glubean run
env:
GLUBEAN_TOKEN: ${{ secrets.GLUBEAN_TOKEN }}
run: npx glubean ci run --uploadThe project and target IDs are in .env, so no second secret is needed.
3. Upload a run
npm run doctor # verify token/project/scope/target without writing
npm run upload # generated script: local profile + uploadFor CI evidence, continue to use the CI profile explicitly:
npx glubean ci run --uploadYou can still target a file, folder, filter, or tag:
npx glubean run ./tests/auth.test.ts --upload
npx glubean run --filter "login" --upload
npx glubean run --tag smoke --upload4. Open the run
After upload, the CLI prints a Cloud URL. Open it to inspect:
- Run summary
- Test results
- Logs, traces, and metrics
- Contract and workflow evidence attached to the Target
- Agent explanations for failures or suspicious performance
Credential lookup order
The CLI resolves each upload field independently. The practical order is:
| Field | Resolution order |
|---|---|
| Token | --token → active run profile’s upload.tokenEnv → GLUBEAN_TOKEN env / .env.secrets → ~/.glubean/credentials.json |
| Project | --project → active run profile’s upload.projectId → GLUBEAN_PROJECT_ID env / .env → ~/.glubean/credentials.json |
| Target | --upload-target → active run profile’s upload.targetId → GLUBEAN_TARGET_ID env / .env → project default target |
| API URL | --api-url → GLUBEAN_API_URL / GLUBEAN_PLATFORM_API_URL env or env files → Glubean Cloud default |
The profile step applies to glubean run --profile <name>, glubean ci run,
and glubean load --profile <name> (CLI ≥ 0.10.1 — the profile’s envFile and
upload.projectId / upload.targetId / upload.tokenEnv are honored the same
way). An ad-hoc glubean load <file|dir> --upload without --profile skips the
profile step and uses CLI flags, env/env-file values, saved credentials, and the
project default target instead.
If a profile sets upload.tokenEnv, that env var is exclusive for that
profile after --token; the CLI does not silently fall back to
GLUBEAN_TOKEN. If --project overrides a profile’s project, the profile’s
upload.targetId is not reused with the new project; set --upload-target or
GLUBEAN_TARGET_ID when you need an explicit target.
This is what makes the recommended CI pattern work: one secret
(GLUBEAN_TOKEN) plus committed project/target IDs in .env. Keep token
values in .env.secrets or the CI secret store — a literal GLUBEAN_TOKEN in
the committed .env is read, so never commit one there.
GLUBEAN_API_URL normally needs no configuration — the CLI talks to Glubean Cloud by default. Set it only when pointing at a different Glubean-hosted environment (e.g. staging), using that environment’s https://api.<env>.glubean.com host — the CLI automatically derives the matching ingest host from it. See Tokens for details.
A glb_ token doesn’t encode the project or target; the upload posts to /v1/projects/{projectId}/targets/{targetId}/runs and Cloud checks the token’s org owns that project (and the project owns that target) plus the runs:write scope. A profile’s upload.projectId / upload.targetId in glubean.yaml is honored when you run that profile, and upload.tokenEnv (the name of the env var holding its token) lets different profiles upload to different destinations. See Tokens for the exact order and the full config reference at Configuration.