Commands
Full reference for every harumi CLI command, flag, and the Python library.
Every command accepts --api-url, --git-url, and --org to override the
resolved configuration for a single invocation. Commands
that act on a project take --project, -p; if you omit it, the CLI uses the
.harumi binding written by harumi new/import/clone/link (searched
upward from the current directory).
Authentication
harumi login # existing account: email + one-time code
harumi login --signup # create the account first, then send the code
harumi whoami # show the current user: email, id, name, environment, organization
harumi logout # clear the local sessionProp
Type
Discover kernels
Kernel specs determine the compute size and image your code runs on. List the
ones available to you before passing --kernel to run:
harumi specsPrints a table of name, display_name, cpu, memory, and whether the
spec requires a subscription. Use the name value (e.g. or_python_small,
gurobi_python_medium) as the --kernel argument.
Examples
List the example projects: finished Harumi projects you can start a copy of.
harumi examplesPrints a table of slug, name and description; --json prints the same
three fields. Pass an example's slug to
harumi new --example. They were called blueprints
before 0.12.0: harumi blueprints and new --blueprint still work, hidden and
with a deprecation notice, until 0.13.0.
Starting a project
There are three ways to get a project onto your machine, one per journey in
Starting a project — this section covers all
three, plus link and new --no-clone.
harumi start # asks which journey, then runs one of the below
harumi new "Demand Planning" # nothing yet: create + clone a scaffold
harumi new "Demand Planning" --example <slug> # start from a copy of an example instead of the default scaffold
harumi new "Demand Planning" --dir ./somewhere-else
harumi new "Demand Planning" --personal # create in your personal workspace
harumi new "Demand Planning" --no-clone # only create it: no clone, no bind (for scripts)
harumi import # existing folder: create a project from the current directory
harumi import ./my-project --project-name "New Name"
harumi import ./my-project --from-git https://github.com/org/repo.git
harumi import ./my-project --personal
harumi clone <PROJECT_ID> # existing Harumi project: clone + bind
harumi clone <PROJECT_ID> --dir ./somewhere-else
harumi link --project <PROJECT_ID> # already checked out: just bindProp
Type
New projects are created in your configured organization (see
Configuration), and new prints which workspace the
project landed in. new --no-clone provisions the project's Gitea repo
server-side but doesn't touch your local directory or git.
new and clone refuse to clone into a destination that already exists and
isn't empty — pass --dir to pick somewhere else. All three of new,
import, and clone finish by writing .harumi/config.json and configuring
the harumi git remote for HTTPS + token pushes, the same binding step
link performs on its own for a directory that's already checked out.
import creates a new project, and force-pushes your folder
import always creates a new project; it is not how you send edits to
a project that already exists (that's git push harumi <branch> from a
clone — see Repository). The project it creates only has a
scaffold commit — there's no shared history with your local folder for a
normal push to merge against, so import force-pushes instead. If the
folder has no harumi.toml, a minimal one (python main.py on
or_python_small) is written for you first, so harumi run doesn't fail
with a missing manifest immediately afterward.
Projects
List and manage the projects you can see. (Creating one is
harumi new.)
harumi projects list # list your projects
harumi projects get <PROJECT_ID> # details for one project
harumi projects rename <PROJECT_ID> <NEW_NAME> # rename a project
harumi projects rm <PROJECT_ID> # delete (confirms first)Prop
Type
projects rm asks you to type the project name to confirm unless you pass
--yes.
Repository
A project's repo is an ordinary git repository. harumi new, import and
clone leave a remote named harumi in your checkout with your token already
in its URL, so plain git works with no further setup — there is no harumi repo command.
| To… | Run, inside the clone |
|---|---|
| List files | git ls-files |
| Read a file | cat <path> |
| Read it on another branch | git fetch harumi && git show harumi/<branch>:<path> |
| Create or change files | edit them, then git add -A && git commit -m "msg" && git push harumi <branch> |
| Delete or move | git rm -r <path> / git mv <from> <to>, then commit and push |
| Zip the repo or a folder | git archive --format=zip -o repo.zip harumi/main [<path>] |
| See history | git log --oneline [-- <path>] |
| List branches | git fetch harumi && git branch -r |
| Create a branch | git switch -c <name> harumi/main && git push -u harumi <name> |
| Delete a branch | git push harumi --delete <name> |
| Promote a branch into live | git switch main && git merge --no-ff harumi/<name> && git push harumi main |
| Label a version with a tag | harumi tags set <name> [--to <branch-or-sha>] |
The harumi remote's URL embeds your Gitea token. Git keeps it in
.git/config and git remote -v prints it, so don't paste either into chat,
logs or issues.
One commit and one push cover any number of edited files. You don't need to
commit to try something: harumi run pushes uncommitted work to a scratch
branch for you.
Check the schedules before deleting a branch
A schedule can pin a branch. Deleting that branch with git won't warn you,
so look at harumi schedules list first.
Check readiness
harumi check # everything blocking this project from running
harumi check --ref <branch> # the same, for another branch or commitProp
Type
check reports what would stop harumi run — the repo exists, harumi.toml
is present and valid, and the kernel is one the project may use — before you
run it.
Files
Upload, list, download, and delete files in the project's non-git storage —
distinct from the project's git repo (git-tracked, lands in a commit): uploads land in
a shared bucket under the project's own prefix and appear at inputs/ inside
every run's sandbox.
harumi files ls # every file uploaded to this project
harumi files put ./data.csv # uploads as "data.csv"
harumi files put ./data.csv raw/data.csv # uploads to a specific path
harumi files get raw/data.csv --output ./data.csv
harumi files rm raw/data.csv --yes
harumi files rm raw/data.csv --yes --missing-ok # exit 0 if it is already goneProp
Type
Upload cap
files put refuses an upload that would push the project past 500 files or
500 MB total — the same limit a run enforces when it syncs these files into
inputs/ — so a bad upload fails immediately instead of breaking every
run afterward.
Run
harumi run
harumi run --branch <b> --commit <sha> --command <c> --kernel <k> --watch
harumi run --tag prod --watchProp
Type
See The run model for how scratch branches
work. When a --watched run succeeds, the CLI prints the
harumi runs download command for its output.
Tags
A tag is a movable label on one version, such as prod. Run one with
harumi run --tag, or follow it from a schedule with --git-tag. See
Tags for how they behave.
harumi tags list
harumi tags set prod # the branch you are on
harumi tags set prod --to release-2 # another branch
harumi tags set prod --to 3f2a9c1e # a commit
harumi tags rm prod --yesProp
Type
tags set creates the tag, or moves it if it exists. Without --to it
labels the branch you are on and refuses if that branch has commits the server
doesn't have yet, because the tag would label older code than you see; push
first, or pass --to. A tag can't share a name with a branch.
tags rm is refused while a schedule follows the tag. The commits aren't
affected.
Runs
Inspect, cancel and download past and in-flight runs.
harumi runs list # recent runs, newest first
harumi runs get <RUN_ID> # details + captured stdout/stderr/error
harumi runs cancel <RUN_ID> # cancel an in-flight run
harumi runs download # the latest run's output, as a zip in this folder
harumi runs download <RUN_ID> --output-dir ./out # a specific run's outputProp
Type
Compare runs
Put 2–4 runs side by side: the project's declared KPIs, the winner, and whether the runs used the same inputs.
harumi compare <RUN_ID> <RUN_ID> # the first run is the baseline
harumi compare <RUN_ID> <RUN_ID> <RUN_ID> --json # the raw comparison, for scriptsProp
Type
KPIs are the project's [[output.kpi]] declarations in harumi.toml. The
winner is the run with the best value of the primary KPI; when there is none
the output says why. "Inputs" reports same, differs (with the files that
differ) or unknown when a run has no record of its inputs.
Data sources
Project-scoped database connections. These hit real, live endpoints today. Credentials are always prompted interactively (hidden input) — never passed as a flag — and the server never returns them.
harumi datasources list
harumi datasources get <name>
harumi datasources add <name> --type postgresql --host <host> --port 5432 --database <db> --username <user>
harumi datasources update <name> --host <new-host> --set-credentials
harumi datasources query <name> --sql "SELECT * FROM orders LIMIT 10" --csv ./out.csv
harumi datasources test --type postgresql --host <host> --port 5432 --database <db> --username <user>
harumi datasources rm <name> --yesProp
Type
Read-only queries
datasources query only allows SELECT/WITH; anything else is rejected
with an explicit error naming the forbidden keyword, and results are capped
server-side. Use it to validate SQL before wiring it into solver code.
Dashboard
Reference and validate the project's dashboard.toml widgets before
committing it — the platform silently drops a widget it can't render instead
of erroring, so validating locally is the only way to catch a typo up front.
See Widgets for the same reference with fuller examples.
harumi dashboard widgets # every widget type + its keys
harumi dashboard widgets --type table # just one type
harumi dashboard validate # check ./dashboard.toml
harumi dashboard validate --against ./output/output.json
harumi dashboard validate --run <RUN_ID> # check against a run's output
harumi dashboard validate --latest # check against the most recent run
harumi dashboard validate --ref <branch> # validate the repo's copy instead of a local fileProp
Type
dashboard validate reports every widget the platform would drop (unknown
type, missing required key) and, when given --against/--run/--latest,
flags dot-paths that won't resolve against that output.json.
Share
Manage a project's public, unauthenticated dashboard links. A project can
have several links, each independently revocable, each with its own
permissions and optional password. Every permission defaults to off on
add, so creating a link never silently grants more than a bare read-only,
latest-run-only dashboard view. run-control capabilities additionally
require the viewer to be signed in. rotate and changing the password invalidate
previously issued viewer sessions for that link only.
harumi share list # every link on this project
harumi share get <LINK_ID> # one link's full URL and permissions
harumi share add # create a link (every permission off)
harumi share add --label "Client" --chat --run-history
harumi share add --label "Client" --run-history --comparisons # --comparisons needs --run-history
harumi share update <LINK_ID> --run-control # only the flags passed are changed
harumi share update <LINK_ID> --disable # turn a link off without touching its permissions
harumi share rm <LINK_ID> --yes # permanently delete
harumi share rotate <LINK_ID> # invalidate the current token, mint a new one
harumi share rotate <LINK_ID> --yes # skip the confirmation prompt
harumi share update <LINK_ID> --password # prompts twice for a password (hidden, min 8 chars)
harumi share update <LINK_ID> --no-password # make the link freely viewable againProp
Type
Schedules
Project-scoped cron schedules. Cron is a raw 5-field expression interpreted in UTC and validated server-side. There is no pause/enable flag — delete the schedule to stop it firing.
harumi schedules list
harumi schedules get <SCHEDULE_ID>
harumi schedules add --cron "0 9 * * *" --git-branch main --kernel or_python_small --email-to everyone
harumi schedules add --cron "0 9 * * *" --git-tag prod
harumi schedules update <SCHEDULE_ID> --cron "0 6 * * 1-5"
harumi schedules rm <SCHEDULE_ID> --yesProp
Type
Secrets
Project-scoped environment variables, injected into your kernels at run time. Values are stored securely and never printed back. Setting an existing name overwrites it.
harumi secrets list # names only (values never shown)
harumi secrets set <NAME> # prompts for the value (hidden input)
harumi secrets rm <NAME> --yesProp
Type
Memories
Short notes the project's assistant remembers, visible to everyone with
access to the project. always memories are loaded into every chat turn;
on_demand ones (the default) are only retrieved when they're relevant.
harumi memories list # includes memories inherited from the organization or your workspace
harumi memories list --query units --mode always
harumi memories add "Report every monetary figure in USD" --mode always
harumi memories edit <MEMORY_ID> --content "Use metric units"
harumi memories rm <MEMORY_ID> --yesProp
Type
Memories inherited from the organization or your personal workspace are listed but can't be edited or removed from a project.
Skills
A skill is a saved, reusable instruction file the project's assistant loads
only when it's relevant. A project's skills are plain files in its repo at
skills/<slug>/SKILL.md: create, edit and delete them in your clone with your
editor and git (see Repository). The CLI adds the one thing a
file edit can't do — installing a preset from Harumi's skill library.
harumi skills library # the preset skills you can install
harumi skills library --category modeling --query roster
harumi skills add scheduling-modeling # write skills/scheduling-modeling/SKILL.md into your clone
git add skills/scheduling-modeling && git commit -m "Install scheduling-modeling skill" && git push harumi mainProp
Type
skills add must run inside a clone. It writes the file only — commit and
push it so the assistant can load it from the live branch — and records
source: harumi/<slug> and the preset's version in its frontmatter. It
refuses to overwrite an existing skills/<slug>/SKILL.md unless you pass
--force.
To install the Harumi CLI's own skills into a coding agent instead, see Agent skills.
Organizations
Manage the organizations you belong to and their members.
harumi org list
harumi org create "<BUSINESS_NAME>"
harumi org rename <ORG_ID> "<NEW_NAME>"
harumi org rm <ORG_ID> --yes
harumi org members <ORG_ID>
harumi org invite <ORG_ID> --email person@example.com --role member
harumi org role <ORG_ID> <USER_ID> --role admin
harumi org rm-member <ORG_ID> <USER_ID> --yes
harumi org use <ORG_ID> # persist the org sent as X-OrganizationProp
Type
Profile
harumi whoami # shows your profile, environment and active organization
harumi profile set --first-name Ana --last-name Silva --bio "Optimization engineer"Prop
Type
Usage
Your (or --org's) current credit allowance — see
Pricing & Limits for what a credit is and what
each plan includes.
harumi usage # your personal allowance
harumi usage --org <ORG_ID> # an organization's pooled allowancePrints the plan code, balance, included credits, and when the period resets. If overage is enabled it also shows the spend cap; otherwise it warns that the next chat turn or run past a zero balance is a hard stop (HTTP 402).
Platform status
The live status of each part of the Harumi platform, read from the public status page. No login needed.
harumi statusPrints a table of services (group, service, status) and exits non-zero if
any service is down, so it also works in scripts. It follows the active
environment (see Environments). When a command fails because
Harumi can't be reached, or answers with a 5xx error, the CLI's error message
points here.
What's new
harumi whats-new # release notes for the version you have installed
harumi whats-new --all # every release, newest firstThe notes ship inside the package, so this works offline. The same notes are on the Changelog page.
harumi also tells you when a newer version is out: after a command, in an
interactive terminal, it prints a one-line notice with the upgrade command for
how you installed it. It checks at most once a day and repeats the same notice
at most once a day. Nothing is printed when output is piped, under CI, or
for harumi --version; set HARUMI_NO_UPDATE_CHECK=1 to turn it off.
Environments
The CLI targets a backend environment — production is the default and the
only one visible to regular users.
harumi env list # selectable environments and their endpoints (the active one is flagged)
harumi env list --all # include internal (VPN-only) environments
harumi env use <name> # persist a different default environment
harumi --env <name> run # override the environment for a single commandEach environment keeps its own login session, so switching with env use
doesn't log you out of the other — you still need harumi login at least
once per environment. Harumi staff have additional internal environments
available; they stay hidden from env list unless you pass --all.
Configuration
Every setting resolves in this order: CLI flag > environment variable >
~/.harumi config > default.
| Setting | Env var | Default |
|---|---|---|
| API base URL | HARUMI_API_URL | https://api.harumi.io/api |
| Gitea URL | HARUMI_GIT_URL | https://git.harumi.io |
| Organization | HARUMI_ORG | none (resolved at login) |
| Update notice | HARUMI_NO_UPDATE_CHECK | on (set to 1 to turn off) |
harumi org use <ORG_ID> # persist the org sent as X-OrganizationThe organization scopes which projects projects list returns, and is the
workspace new and import create new projects in. Pass --personal to
either of them to create a project in your personal workspace instead.
Set HARUMI_HOME to relocate the whole config directory (credentials, config,
and tokens all live under it).
Agent skills
Install the bundled harumi-cli and harumi-cli-setup agent skills onto this
machine (not to be confused with a project's own skills) — see Agent skill for what they do and the other
install methods (npx skills, the Claude Code/Cursor plugin marketplace).
harumi agent-skills install # auto-detects installed agents, global scope
harumi agent-skills install --project # writes to ./.agents/skills instead
harumi agent-skills install --agent claude-code --dry-run # print each source -> destination, write nothingProp
Type
Renamed in 0.11
The old names keep working in 0.11.x — hidden from --help, and each prints a
deprecated: line naming its replacement — and are removed in 0.12.0.
| Old | Use instead |
|---|---|
push | harumi import |
projects create | harumi new <NAME> --no-clone |
outputs, run --output-dir | harumi runs download |
config set-org | harumi org use |
profile show | harumi whoami |
env current | harumi env list |
skill install, skill path | harumi agent-skills install (--dry-run instead of path) |
repo readiness | harumi check |
every other repo command | plain git in your clone (see Repository) |
share set-password, share rm-password | harumi share update --password / --no-password |
projects delete, org delete | projects rm, org rm |
share remove, datasources remove, schedules remove | share rm, datasources rm, schedules rm |
org remove | harumi org rm-member |
Files the CLI uses
~/.harumi/environments/production/credentials.json— session tokens and the Gitea token (mode0600).~/.harumi/environments/production/config.json— resolvedorg_id(and any localapi_url/git_urloverrides).<project>/.harumi/config.json— per-directory project binding (project_id+ repo), searched upward from the current directory.
Python library
The same functionality is available as a library — useful in notebooks or your own automation.
from harumi import Client
from harumi.config import ProjectBinding
binding = ProjectBinding.load() # reads .harumi/config.json
client = Client() # reads your stored session
response = client.execute_project(
binding.project_id,
branch="feature/solver-v2",
command="python main.py",
)
from harumi.execution import wait_for_run, download_run_output
result = wait_for_run(client.api, binding.project_id, response.project_run_id)
print(result.status, result.succeeded)
download_run_output(client.api, binding.project_id, result, "./out")