agentful
v0.4.8
Published
Agentful in your terminal — local development with push-to-cloud previews
Maintainers
Readme
Agentful CLI
Develop locally, ship with one command. agentful gives you an AI coding
interface in your terminal and moves the project into your Agentful workspace
with a live preview URL — using the same models and credits as the web app.
npm i -g agentfulQuickstart
agentful login # once: confirm the code in your browser
agentful init # create or link the cloud project
agentful --model agentful/azure-gpt-5_4 --variant high
# start with an exact, visible model pin
agentful push # upload, cloud build, preview URL
agentful open # open the previewCommands
| Command | Purpose |
| --- | --- |
| login / logout / whoami | Browser-based sign-in; the token is kept in the macOS Keychain (on Linux: a 0600 file under ~/.config/agentful/) |
| init [--link <id>] [--title <t>] | Create a cloud project or link an existing one (.agentful/project.json) |
| push [--prebuilt [--dir <path>]] | Upload the source and build in the cloud; --prebuilt uploads a local build |
| open | Open the live preview |
| share [--private] | Make the preview public, or private again |
| publish <subdomain> | Publish at https://<subdomain>.agentful.dev |
| pull [--force] | Fetch the cloud state into this directory |
| models [--add-local] | Show available models, manage your own providers |
| upgrade | Update the CLI to the latest published version |
| licenses | Licences of the software shipped with this CLI |
| -s, --session <id> | Resume a previous coding session without changing its model |
| -m, --model <provider/model> [--variant <name>] | Pin an exact engine model and optional provider-specific variant (agentful and agentful tui) |
Inside the interface, / lists the Agentful commands (/setup, /push,
/preview, /publish, /share, /status) alongside the built-in ones.
push respects your .gitignore and always excludes .git, node_modules,
build output and every .env file. Uploads are capped at 6 MB.
What you can deploy
Agentful Cloud publishes static builds. Your app has no server process of its own — and server-side logic still has a place:
- A static build of a supported framework (Vite, Create React App, Next.js
with
output: 'export', Nuxt withssr: false, plain HTML/CSS/JS).agentful pushchecks this before it uploads. - Server Actions — functions we run for you. One file is one endpoint:
.server/actions/<name>.jsanswers at/api/p/{projectId}/actions/{name}, JSON in, JSON out. This is where API keys and logic the browser must not run belong (await ctx.secrets.get('server.<name>')). Plan for a 5 s budget per action (10 s hard limit), 256 MB memory, a 1 MB request body, 256 KB of source per action and 10 concurrent calls per project. The 5 s are a budget, not a guaranteed stop: an action still waiting on a network call at that point is answered with408, and calls it already started may still finish. Incoming webhooks: the platform checks the sender's signature for you —await ctx.webhooks.verifyStripe('server.<name>'),ctx.webhooks.verifyGitHub(…), orctx.verifyHmac({…})overctx.rawBody(the request body exactly as received) for other HMAC schemes. The signing secret stays on the platform; your action gets a verdict. - Your own API. Connect an HTTPS endpoint you run yourself in the Backend
tab;
/api/*on your app's domain is forwarded to it. The platform adds no secret and authorizes nobody on the way — that is your endpoint's job.
What does not work:
- A server process bundled into the app: Express, SSR, Next.js API routes,
middleware,
'use server'. The push preflight rejects these. - Inside Server Actions: no cron or background jobs (there is no scheduler —
an external scheduler can call an action with a token in a header), no npm
packages and no
require/import, nocrypto, no timers, no WebSockets or streaming, and no custom status codes, headers or HTML responses. Webhook signatures that are not an HMAC keyed with the stored secret as typed (asymmetric signatures, Svix-style secrets) are not covered — look the event up at the provider, or put a verifying receiver in front. - Build-time env vars or build secrets of your own.
.env*files never leave your machine. Every cloud build defines one fixed allowlist of public values and nothing else: the project ID (VITE_PROJECT_ID,PUBLIC_PROJECT_ID) and, while your own Supabase database is connected in the Backend tab, its URL and publishable key (VITE_/PUBLIC_/NEXT_PUBLIC_+SUPABASE_URL,SUPABASE_ANON_KEY). Reading one of those names while nothing defines it fails the build instead of compiling toundefined;agentful pushwarns about it before the upload. Keep public values of your own in an ordinary source constant.
Actions have no staging: they run from your project's source, so a push can change what the published app does immediately, while warm instances may serve the previous code for up to five minutes.
Actions run only while the managed server is switched on in the Backend tab
(agentful backend opens it). A push stores your action files either way, but
until the server is on every call answers 404 server_not_enabled. The CLI can
enable the database for you — not the server. Switching on takes effect on the
next call; switching off takes effect within 60 seconds.
The figures above are rendered into AGENTFUL_CLOUD.md from the machine-readable
contract at https://app.agentful.dev/cli/platform-contract.json
(server_side); the full picture for humans is at
https://www.agentful.dev/docs/managed-backend.
Platform support
macOS and Linux (arm64 and x64 each). The device-flow login works headless:
the CLI prints a URL plus a code, opening a browser is best-effort (xdg-open).
Windows is not supported natively yet — win32 engine artifacts are not mirrored
and the credential/spawn/extract assumptions are untested there; use WSL2
instead (it runs the proven linux builds).
Engine distribution
The TUI runs the Agentful engine, which the CLI downloads on first use from
app.agentful.dev/cli/engine/<version>/ (mirrored in R2) and verifies against
the checksum in app.agentful.dev/cli/engine-manifest.json.
That manifest is the release switch. Bump engine_version + artifacts
there and every CLI picks up the new engine on its next start — no npm release
required. Engine self-updates are disabled (autoupdate: false plus
OPENCODE_DISABLE_AUTOUPDATE), so nothing changes behind our back. To publish
a new engine version:
- Download the upstream release artifacts for all four platforms.
wrangler r2 object put mainmvp-distributions/cli/engine/<version>/<platform>.<ext> --file=… --jurisdiction eu --remote- Update
frontend/public/cli/engine-manifest.json(version + sha256) and deploy the frontend.
The engine is opencode under the MIT
license; agentful licenses shows the notice we are required to ship.
Models
agentful models lists what the account can use:
- Agentful models — the real per-account catalog from
/api/llm/available-models(the same source the web app uses), including server-side BYOK keys as explicitbyok/{provider}/{model}entries. Credits, AI region and org rules apply. - Local providers — providers with the user's own key in
~/.config/agentful/local-providers.json. This file belongs to the user: the CLI merges it into the engine config but never rewrites it. These requests go straight to the provider — no credits, no platform region guarantee, no usage record. - Direct TUI connections — provider connections created in the engine's
/modelsdialog. Their exact models come from the pinned engine's own catalog, so the CLI preflight and the dialog no longer maintain conflicting inventories. Requests go directly to that provider and use its billing and terms, outside Agentful credits and region controls.
The start resolver is deterministic: explicit CLI flag > resumed session >
optional project pin > platform default. A project pin lives at
.agentful/model.json:
{
"model": "zai-coding-plan/glm-5.2",
"variant": "high"
}Model IDs are canonical engine IDs and are matched exactly against
agentful-engine models <provider> after the final session config is written.
An unknown model or an unconnected direct provider fails before the TUI starts.
The CLI prints the chosen model, variant, source, billing path and data path.
For a resume without --model, the session's persisted provider/model/variant
wins; an unreadable session model is left to the engine and is never silently
replaced with the project or platform default.
Stream liveness and safe recovery
Each TUI starts its engine API on a random 127.0.0.1 port and observes
/global/event. Provider/status, token/reasoning, tool, question and idle
events are classified separately. A running tool or pending user question
suspends the silence timer.
- after 60 seconds without a real progress event, the TUI shows a warning;
- after 120 seconds it tells the user how to stop and offers recovery after exit;
- no timeout changes the model, sends a prompt or starts a retry;
- recovery requires an explicit
yand only reopens the same session. It does not continue automatically, so completed tool calls are not replayed by the CLI.
Local providers are governed by the organization's BYOK policy (/api/org/me):
disabled blocks them, provider_allowlist permits only the listed provider ids,
allow (and private accounts without an org) permits any. The check is done by
the CLI, so it is a cooperative control, not a cryptographic one — the config
lives on the user's machine.
Known limitation: the engine's exit banner
When the TUI closes, the engine writes its own splash (its logo plus a
opencode -s <id> hint) straight into the scrollback. v1.18.x offers no flag,
env var or config to suppress it, and patching the binary would break its
macOS signature. We therefore let it stand and print our own last line with
the command that actually works here — agentful -s <id>; the engine's hint
cannot work, because that binary is not on the user's PATH and its data lives
in a different directory.
Branding
Everything user-visible lives in src/branding/: branding.ts (palette,
wordmark, product name), agentful-theme.json (TUI colors, with a remote
override at app.agentful.dev/cli/theme.json), logo.txt (home-screen mark,
plain half-blocks so it takes the theme color), plugin.ts (the TUI plugin
that fills the home_logo / home_footer slots) and commands.ts (the /
palette entries).
Development
npm install
npm run typecheck
npm run build # dist/index.cjs (self-contained, shebang included)
node dist/index.cjs --helpAll endpoints default to production pb.agentful.dev (workspace routes are
PB-hook proxies; api.agentful.dev only serves the end-user OAuth broker) and
can be overridden with AGENTFUL_PB_URL / AGENTFUL_API_URL / AGENTFUL_APP_URL.
Design tokens (colors, banner, symbols) live in src/branding.ts — change the
look there, nowhere else.
