Bento CLI
This workspace composes the bento command: local agent work, terminal UI, and workspace/file/sync operations under one login. The npm identity remains @bentoai/cli.
Copyright (c) 2026 dzhng, LLC. Licensed under AGPL-3.0-only; bundled dependencies retain their licenses and notices.
External agents use the consumer skill to install and operate the released command from their own computer. Agent setup owns installation, skill install and sign-in; the lander publishes it at https://heybento.ai/agents.md.
The CLI embeds that consumer skill so an installed release can install it without
repository access. Build steps derive its text-import inventory from the skill
folder; the tree guard catches missing files and stale bytes. Successful CLI
upgrades use the newly installed launcher to refresh the skill for saved agents,
so the instructions match the executable. bento local skill --help owns the command
syntax; bento local skill list keeps its JSON discovery contract.
npm installs a Node launcher and the compiled executable for the host; users need
Node, not Bun. bento --help owns the command surface.
Harness runtime and protocol ownership belong to the private
agent workspace. The CLI consumes that owner directly;
it owns dispatch and user configuration. Operations over this computer’s stores
live under local; workspace operations come from the shared contract. A saved default selects remote operation targets
and model billing. A workspace flag never redirects a local store operation.
The HTML tool factory is a hosted composition boundary: it consumes gateway/session context and the contract's shared schema, while the gateway owns rendering and publication. It adds no terminal command.
Named API operations consume the shared customer bindings.
The command table owns matching, help and invocation checks across
bindings and hand-written commands. Its @bentoai/cli/command-table export lets documentation
consume the same grammar without loading the agent runtime. Examples live with the shared
customer operation inventory. Complete body input comes from a file or stdin; scalar body
and query flags override file fields, while declared header inputs stay separate. JSON results retain
API fields on stdout. File receipts and empty results retain HTTP metadata on stdout;
successful stderr stays quiet except for actionable recovery information. Failures
retain their status, headers and diagnostics on stderr.
Named binary writes stream a local file with --in, or stdin with --in -.
CLI JSON body files also accept the shared
binary request representations
for arbitrary bytes. Declared content type and conditional headers are retained.
Empty conditional/optional reads preserve HTTP metadata without replacing a
local destination. Binary reads use the existing src/file-transfers.ts streaming owner for stdout
or a local destination. With --json, failures retain the complete upstream body
inside apiError; a non-scope refusal keeps its own code. Local file handling and process exit codes remain CLI-owned.
Service calls use named vendor operations rather than an arbitrary Bento REST caller. The API retains route admission, vendor credentials, funding and accounting. Calls preserve repeated query/form values, complete JSON and raw bytes, following the same output and failure contract above. An output file can contain a vendor refusal, so callers must retain the exit status and metadata. Installed help owns the input flags.
Named model operations use the gateway's separate origin and existing billing
workspace. Their complete native bodies, protocol choices and headers are
advertised by command help; the gateway owns admission and exact model IDs.
Native streams require a protocol ending. Media bytes use ordinary local files,
and machine results retain surrounding native metadata. A delivery failure keeps
that result and any successfully saved files on stdout, and exits nonzero.
With --json, stderr includes indexed delivery errors. Generation is never
repeated for recovery.
Detached video receipts and raw status outcomes remain resumable without another
client job system.
The prompt convenience and native commands share SDK media and output owners.
Remote conversations use durable input outcomes from the shared
session contract. Submission writes its recovery request
identity to stderr before HTTP, then returns a terminal result or resumable handle.
A running result does not cancel work; result/wait only observe that input.
session create returns on acceptance; use --wait or --wait-ms to observe its reply.
For creation without waiting, exit 0 means accepted. Reply-waiting commands also
exit 0 while the turn is still running or asking; failed or cancelled turns exit
- Re-wait only on
status: "running". A terminalaskneeds an answer with a new input handle; other terminal outcomes, includingsleepandinterrupted, remain final for their handle. Transport closure cannot establish completion.
bento app credential manages external runtime keys for an already registered
app using the same saved human login or process-provided VM key. Workspace and
app selections are explicit. Creation returns the complete API response on stdout, including the one-time
plaintext key and deployment URLs. Capture the
key in memory and pass it through stdin to the host's server-side secret store.
The command never saves exported keys or retries an ambiguous mint. Inspect the
live inventory and revoke unwanted entries before explicitly creating another credential.
Rotation uses a second creation, host deployment and verification, then revocation
of the prior credential. bento app credential --help owns the command surface.
Laptop-local state has one selected root for login, memory, training, sync
identity, sessions, caches and logs. A fresh install creates ~/.bento; an
existing install with only ~/.duet continues reading and writing there. If
both directories exist, ~/.bento wins silently. Bento never migrates,
deletes, symlinks or merges the old directory. VM and project-local .duet
paths remain their own contracts.
The saved human login and default API/workspace live in config.json. Other provider keys remain in provider env files, and connected subscriptions keep their own store. Login approval identifies the person; access follows current workspace memberships. Mac mirroring has its own non-secret machine identity, so removing a Mac does not revoke the login.
The executable compiler owns isolated target-platform builds for public distributions, VM releases and benchmark/journey consumers. Public builds carry native tools beside the executable; VM builds preserve their release inventory and use the VM's installed tools. Native runtime locations belong to the agent runtime asset owner, so a compiled payload can move without keeping its source or dependency tree.
The public platform table owns supported hosts and npm package names. Platform assembly consumes the compiler's executable, sidecars and license notices; the public package builder builds only the Node launcher and pins the platform dependencies to its release version. The release workflow owns build inputs and publication order: platform payloads must exist before the launcher is published.
Contributors and VM tooling keep Bun. Repository JavaScript builds keep native
packages external through scripts/native-packages.ts; public executables embed
their module graph and load native data beside the binary. The root lockfile owns
dependencies and the root repository owns publication and VM release delivery.
Use the package scripts for builds, checks and disposable-container tests.
Mac sync keeps one computer identity across separate workspace transfer instances, with account removal independent of user login.
Public commands follow the contract naming rule.