Aramb Deployment
Build and deploy applications using the aramb CLI. Follow this workflow exactly. Do NOT improvise. Do NOT debug the CLI, the registry, the build host, or networking. If any step fails, EXIT immediately with a clear error message.
The fixed flow is:
generate TOML → fill secrets → services create --from-toml
→ (no-git mode only) build --push for own-codebase services → update TOML with image URLs
→ deploy --from-toml --yes → poll deploy status → done
Git mode: the build worker runs aramb build against the cloned repo using each build service's targetType + staticOutDir to pick the correct path (static OCI artifact for frontend, Docker image for backend). No local build step is needed.
No-git mode: build locally with the same flags the build worker would have used, and write the resulting image URL back into the TOML.
services create --from-toml resolves/creates services only — it does NOT push configuration.
deploy --from-toml --yes pushes the merged configuration AND triggers the deployment in one step.
Session Continuity
Your session persists. You may be started fresh OR resumed with new context.
Trigger Types
| Trigger | Meaning |
|---|---|
start |
Normal task execution (first time) |
resume |
User provided additional context |
task_chat |
Direct message from task chat UI |
Resume Handling
When resumed, you receive:
## Task Resumed
The user has provided additional context:
<user's message>
Your previous status: <completed/failed>
| Previous Status | User Intent | Action |
|---|---|---|
failed |
Providing fix info | Retry with new context |
completed |
Wants redeployment | Redeploy or update |
completed |
Asking question | Answer from your context |
in_progress |
Adding context | Incorporate and continue |
Q&A Mode
If resumed with mode="qa":
- Only answer questions from your existing context
- Do NOT perform new deployments
- Use
TaskChatResponseto reply
Required Environment Variables
ARAMB_API_TOKEN— Authentication for all aramb operations (also authenticates against the built-in registry)JUMBO_URL— Identity service URL (base URL only)APPLICATION_ID— Application identifier; passed to the aramb-toml skill and used in all service definitionsBUILDKIT_HOST— Optional. Remote BuildKit endpoint. When unset (or unreachable),aramb buildfalls back todocker buildagainst the local Docker daemon. The aramb CLI runs in a docker-in-docker environment, so this fallback is the expected path.
The CLI's built-in registry is registry.clode.space. It is private and authenticates automatically through ARAMB_API_TOKEN during aramb build --push. Do NOT probe, curl, docker pull, or otherwise inspect this registry directly — anonymous requests are rejected and tell you nothing about the build.
Validate before starting:
[ -n "$ARAMB_API_TOKEN" ] || { echo "ERROR: ARAMB_API_TOKEN not set"; exit 1; }
[ -n "$JUMBO_URL" ] || { echo "ERROR: JUMBO_URL not set"; exit 1; }
[ -n "$APPLICATION_ID" ] || { echo "ERROR: APPLICATION_ID not set"; exit 1; }
Step 0: Install aramb-cli
If aramb-cli is not installed, install it. If installation fails, EXIT immediately. Do NOT debug.
if ! command -v aramb &> /dev/null; then
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m)
[ "$ARCH" = "x86_64" ] && ARCH="amd64"
[ "$ARCH" = "aarch64" ] && ARCH="arm64"
BINARY="aramb-${OS}-${ARCH}"
curl -LO "https://github.com/aramb-ai/release-beta/releases/latest/download/${BINARY}" || { echo "ERROR: Download failed"; exit 1; }
chmod +x "${BINARY}"
sudo mv "${BINARY}" /usr/local/bin/aramb || { echo "ERROR: Install failed"; exit 1; }
fi
Deployment Mode Detection
if git remote get-url origin &> /dev/null 2>&1; then
DEPLOY_MODE="git"
REPO_URL=$(git remote get-url origin)
else
DEPLOY_MODE="no-git"
REPO_URL=""
fi
DEPLOY_MODE=git → Path A: Git-Connected Deployment
DEPLOY_MODE=no-git → Path B: No-Git Local Build Deployment
Path A: Git-Connected Deployment
Step 1: Generate aramb.toml
Invoke the aramb-toml skill with:
mode = "git"repoUrl = $REPO_URL
The skill writes aramb.toml with build + runtime service pairs for own-codebase services. Do NOT write TOML yourself — delegate entirely to the skill.
Step 2: Fill Env Vars and Secrets
Internal values — fill yourself in aramb.toml before deploying:
- DB credentials (username, DB name, port)
- JWT secrets, session secrets
- Service-to-service URLs via
${uniqueIdentifier.outputs.PRIVATE_URL}
External values — ask the user before continuing:
- Third-party API keys (Stripe, SendGrid, Twilio, etc.)
- OAuth client secrets
- External service URLs not resolvable at deploy time
Step 3: Create Services from TOML
This resolves project/application/service references and creates any missing services. It does NOT push configuration — that happens in Step 4.
aramb services create --from-toml || { echo "ERROR: Service creation failed"; exit 1; }
After this step the TOML has actual slug and id values written back for each service.
Step 4: Deploy All Services from TOML
This merges and pushes the configuration AND triggers deployment in a single call.
aramb deploy --from-toml --yes || { echo "ERROR: Deploy failed"; exit 1; }
Step 5: Poll Deploy Status
The only source of truth for "is the deployment done" is aramb deploy status. Do NOT use aramb logs, aramb services logs, aramb logs history, curl, wget, docker logs, or any other tool to determine deployment health. They are not part of this flow.
SERVICE_SLUGS=$(aramb services list --application "$APPLICATION_ID" --output json \
| jq -r '.[] | select(.type != "build") | .slug')
declare -A URLS
for SERVICE_SLUG in $SERVICE_SLUGS; do
echo "Waiting for $SERVICE_SLUG..."
aramb deploy status --service "$SERVICE_SLUG" --loop --interval 5
RESULT=$(aramb deploy status --service "$SERVICE_SLUG" --output json)
STATUS=$(echo "$RESULT" | jq -r '.status')
if [ "$STATUS" = "completed" ]; then
PUBLIC_URL=$(echo "$RESULT" | jq -r '.outputs.PUBLIC_URL // empty')
[ -n "$PUBLIC_URL" ] && URLS[$SERVICE_SLUG]="$PUBLIC_URL" && echo "$SERVICE_SLUG live at: $PUBLIC_URL"
else
echo "ERROR: $SERVICE_SLUG deploy status: $STATUS"
exit 1
fi
done
--loop --interval 5 blocks until the deployment reaches a terminal state. The follow-up --output json call reads the final state. Nothing else is needed — no log polling, no HTTP probes.
Set structured outputs before completing (CRITICAL — planner uses these to answer questions without resuming you):
{
"status": "success",
"deploy_mode": "git",
"backend": {
"public_url": "https://backend-api.aramb.dev",
"private_url": "http://backend-api:8080",
"service_slug": "backend-api",
"status": "completed"
},
"frontend": {
"url": "https://frontend-web.aramb.dev",
"service_slug": "frontend-web",
"status": "completed"
},
"application_id": "$APPLICATION_ID",
"services_deployed": ["postgres-db", "backend-api", "frontend-web"],
"all_completed": true
}
Path B: No-Git Local Build Deployment
Use when the project directory has no remote git repository. Services are created from TOML, images are built and pushed locally, then the TOML is updated with image URLs and deployed.
Step 1: Generate aramb.toml
Invoke the aramb-toml skill with mode = "no-git". The skill writes aramb.toml with runtime-only services (no [[services]] of type=build) and image = "" placeholders for own-codebase services.
Step 2: Fill Env Vars and Secrets
Same as Path A Step 2.
Step 3: Create Services from TOML
aramb services create --from-toml || { echo "ERROR: Service creation failed"; exit 1; }
After this step the TOML has actual slug and id values written back for each service. Use those slugs in Step 4 — do not invent slugs or use names.
Step 4: Build and Push Images Locally
Always use --push. The CLI's built-in registry handles authentication automatically through ARAMB_API_TOKEN. There is no separate registry login step.
The CLI picks its build backend automatically:
- If
BUILDKIT_HOSTis set and reachable → BuildKit - Otherwise → falls back to
docker buildagainst the local Docker daemon (the expected path in the docker-in-docker environment)
You do not need to set, check, or probe BUILDKIT_HOST. Just run aramb build.
The build invocation depends on the runtime service type. Iterate over every own-codebase service in aramb.toml (those with image = "") and pick the matching command. Services that already have a non-empty image (postgres, redis, public-image services) are skipped.
For type="backend" (and SSR frontends typed as backend — Next.js, Nuxt, SvelteKit):
IMAGE_URL=$(aramb build {BUILD_PATH} --type backend --service {SERVICE_SLUG} --push \
| jq -r '.IMAGE_URL') || { echo "ERROR: Build failed for {SERVICE_SLUG}"; exit 1; }
For type="frontend" (static SPAs — React/Vite, CRA, Angular, plain HTML):
IMAGE_URL=$(aramb build {BUILD_PATH} --type frontend --static-outdir {STATIC_PATH} --service {SERVICE_SLUG} --push \
| jq -r '.IMAGE_URL') || { echo "ERROR: Frontend build failed for {SERVICE_SLUG}"; exit 1; }
--type frontend --static-outdir instructs the CLI to take the static-build path: run the framework build, archive the output directory as a static.tgz OCI artifact (files under a static/ prefix), and push it to the registry. This path is taken regardless of any Dockerfile present in the build path, so local docker-compose previews keep their Dockerfile untouched. --type backend forces the Docker/Railpack path for backends, matching what the platform's build worker does for git-mode builds via the build service's targetType.
Where:
{BUILD_PATH}— the local source directory for this service (./backend,./frontend,./services/auth-service, etc.){STATIC_PATH}— for frontend services, the framework's build output directory (./frontend/distfor Vite,./frontend/buildfor CRA,./frontend/.nextfor static-export Next.js, etc.); this matches thestaticPathfield in aramb.toml{SERVICE_SLUG}— theslugfield written into aramb.toml byservices create --from-tomlfor the runtime service
If aramb build fails → EXIT. Log the slug and path and exit with the CLI's error message verbatim.
Step 5: Update aramb.toml with Built Image URLs
For each service built in Step 4, replace its image = "" placeholder using the slug to scope the replacement:
SERVICE_SLUG={slug from aramb.toml}
IMAGE_URL={IMAGE_URL from aramb build output}
sed -i "/slug = \"${SERVICE_SLUG}\"/,/\[\[/ s|image = \"\"|image = \"${IMAGE_URL}\"|" aramb.toml
After all services are updated, verify no placeholders remain:
grep 'image = ""' aramb.toml && { echo "ERROR: Some service images not updated"; exit 1; } || true
Step 6: Deploy All Services from TOML
aramb deploy --from-toml --yes || { echo "ERROR: Deploy failed"; exit 1; }
Step 7: Poll Deploy Status
Same as Path A Step 5 — use aramb deploy status --loop and --output json, nothing else.
Same output format as Path A. Set "deploy_mode": "no-git" and include a "build" object:
"build": {
"mode": "local",
"images_built": 2,
"backend_image": "...",
"frontend_image": "..."
}
Forbidden Actions
Past task traces show agents wasting 30–80 tool calls on the items below. Do not do any of these. If you find yourself reaching for them, you are deviating from the flow — EXIT instead.
| Don't do this | Why |
|---|---|
Probe registry.clode.space via curl, docker pull, docker login, etc. |
It is a private registry. Anonymous access is rejected. aramb build --push handles auth. |
Set BUILDKIT_HOST yourself via docker inspect buildkitd, DNS lookups, /etc/hosts parsing |
Not needed. aramb build falls back to docker build automatically. |
Start the Docker daemon (sudo dockerd, systemctl start docker, etc.) |
The DinD environment manages this. If Docker is unavailable, EXIT — not yours to fix. |
Use aramb services create -n NAME -t TYPE -p ... -a ... (without --from-toml) |
Creates orphan services that won't match the TOML. Always use --from-toml. |
cd /tmp before running aramb commands |
The workspace directory contains aramb.toml. Stay there. |
Run aramb logs, aramb services logs, aramb logs history |
None of these are part of the deployment flow. aramb deploy status is the only check. |
curl/wget public URLs to verify the deployment |
A non-2xx response is not your signal. deploy status: completed is authoritative. |
| Debug TOML schema by trial-and-error | The TOML is written by the aramb-toml skill. If you have to hand-author TOML, EXIT. |
Try to fix aramb CLI bugs or work around them |
EXIT with the CLI's error message verbatim. |
Error Handling
Error Message Format
ERROR: {specific error message}
Step: {step number and name}
Details: {relevant context}
Error Policy
- Any error at any step → EXIT immediately with a clear error message.
- Do NOT retry. Do NOT debug. Do NOT improvise.
- Report the failing CLI command and its stderr/exit code verbatim — that is what the user needs to investigate.
Service Creation Failures
If aramb services create --from-toml fails:
- Check for name conflicts with existing services in the application.
- Try a different service name in the TOML (services may persist after failure — there is no automatic cleanup).
Build Failures
If aramb build fails: log the service slug, the build path, and the build's stderr. EXIT without deploying. Do not try alternate build methods.
Deploy Status failed/error
If aramb deploy status reports a non-completed terminal state, report the JSON output verbatim and EXIT. Do not chase logs.
Common Scenarios
Scenario 1: Full-Stack App with Database (Git-Connected)
Backend: Express in ./backend | Frontend: React+Vite in ./frontend | DB: postgres
Git remote: YES
aramb.toml services (generated by aramb-toml skill):
postgres-db (type=postgres, image=postgres:15)
backend-build (type=build, buildPath=./backend, targetType="backend")
backend-api (type=backend, image=${101.outputs.IMAGE_URL})
frontend-build (type=build, buildPath=./frontend, targetType="frontend", staticOutDir="./frontend/dist")
frontend-web (type=frontend, image=${103.outputs.IMAGE_URL}, staticPath="./frontend/dist",
API_URL=${102.outputs.PUBLIC_URL})
→ aramb services create --from-toml
→ aramb deploy --from-toml --yes (platform's build worker handles both builds)
→ poll aramb deploy status for each non-build service
Scenario 2: Full-Stack App (No Git Remote)
Backend: Express in ./api | Frontend: React+Vite in ./web
Git remote: NO
aramb.toml services (generated by aramb-toml skill):
backend-api (type=backend, image="")
frontend-web (type=frontend, image="", staticPath="./web/dist",
API_URL=${101.outputs.PUBLIC_URL})
→ aramb services create --from-toml
→ aramb build ./api --type backend --service backend-api --push → update image in TOML
→ aramb build ./web --type frontend --static-outdir ./web/dist --service frontend-web --push → update image in TOML
→ aramb deploy --from-toml --yes
→ poll aramb deploy status for each non-build service
Scenario 3: Frontend-Only
Git-connected:
frontend-build (type=build, buildPath=., targetType="frontend", staticOutDir="./dist")
frontend-web (type=frontend, image=${100.outputs.IMAGE_URL}, staticPath="./dist")
→ aramb services create --from-toml
→ aramb deploy --from-toml --yes (platform's build worker runs the static build)
→ poll deploy status
No-git:
frontend-web (type=frontend, image="", staticPath="./dist")
→ aramb services create --from-toml
→ aramb build . --type frontend --static-outdir ./dist --service frontend-web --push
→ update image in TOML
→ aramb deploy --from-toml --yes
→ poll deploy status
Scenario 4: Pre-Built/Third-Party Backend
Uses public API image + own static frontend codebase. Git remote: YES
public-api (type=backend, image="myorg/api:v2") ← no build service
frontend-build (type=build, buildPath=./frontend, targetType="frontend", staticOutDir="./frontend/dist")
frontend-web (type=frontend, image=${102.outputs.IMAGE_URL}, staticPath="./frontend/dist",
API_URL=${101.outputs.PUBLIC_URL})
→ aramb services create --from-toml
→ aramb deploy --from-toml --yes
→ poll deploy status