balda

module
v0.3.2-0...-939d930 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 3, 2026 License: MIT

README

balda

test lint

Self-hosted engineering agent for team chat

Balda is a self-hosted engineering agent that lives in your team chat and works inside your project.

You can give it a task in chat, open a focused topic for a piece of work, run a longer goal loop, or wire external events into the same workflow. Balda keeps context, uses your configured tools, and returns something reviewable: a summary, changed files, validation output, a commit, or a concrete next step.

What Balda is good for

  • chat-native engineering help in Telegram, Zulip, or Slack Agent DMs/channel threads
  • focused task threads instead of one shared bot conversation
  • long-running goal execution with progress updates and final results
  • wedge style operation: put the agent in the middle of your team workflow so chat, tools, schedules, and external events all feed the same execution path
  • self-hosted deployment close to your repo, config, and credentials

Quickstart

You need:

  • one chat surface: Telegram, Zulip, or Slack
  • one supported provider CLI installed on the host or in Docker: codex, opencode, copilot, gemini, or claude
  • Node.js/npm, unless you run the Docker Compose path

Install:

npm install -g -y @baldaworks/balda

Initialize in your project:

balda init

Start:

balda start

balda init creates .config/balda/config.yaml, initializes .config/balda/state.db, detects available provider CLIs, and prints the next step for your selected chat provider.

First run

For Telegram, authenticate the owner with the command printed by balda init:

/start owner=<owner_token>

Then send a normal direct message to the bot, or open an isolated topic:

/topic release

From there you can:

  • ask for ordinary help in chat
  • start a goal loop with /goalkeeper <objective>
  • stop the current turn with /cancel
  • reset the current session with /reset

Main workflows

1. Ordinary chat work

Send a message in the session where you want work to happen. Balda keeps that conversation as the execution context.

2. Focused topic work

Use /topic <name> to create a separate session for a task, incident, release, or stream of work.

3. Goal-driven execution

Use /goalkeeper <objective> when you want Balda to keep working until there is a result to review.

Balda will:

  • work in repeated passes
  • post progress updates
  • ask follow-up questions when critical input is missing
  • return a terminal result with outcome details

See docs/goal-workflow.md for the detailed goal contract.

4. Wedge mode

Balda can act as a wedge between team chat and the rest of your engineering system:

  • chat messages start work
  • scheduled jobs wake work up
  • inbound webhooks turn external events into session work
  • the same session can continue through follow-up questions and delayed work

This is useful when you want one operational path for human requests, automation, and agent execution instead of separate bots and scripts.

Supported chat providers

  • Telegram
  • Zulip
  • Slack Agent DMs and mentioned channel threads

Balda maps each conversation scope to its own session:

  • Telegram direct chat or personal/group topic
  • Zulip stream + topic
  • Slack Agent DM or mentioned channel thread

In Slack channels, every turn requires an explicit @Balda mention. A mention inside an existing thread can use its preceding accessible discussion as bounded context; ordinary channel messages never activate Balda.

Docker Compose

Balda ships a root Dockerfile and compose.yaml for local Docker Compose deployment.

The current directory is mounted as /workspace, so Balda sees your checkout, config, git metadata, and local state.

docker compose build balda
docker compose run --rm balda init
docker compose up -d balda

Polling mode is the default, so Telegram does not require publishing a port. Webhook deployment details live in docs/balda.md.

Published container image

Balda publishes a release image at ghcr.io/baldaworks/balda:latest.

That image contains the balda binary only. It does not bundle provider CLIs. Use it as a source stage in your own image and add the provider runtime you want.

Example with Codex:

FROM node:24-bookworm-slim AS cli-builder
RUN npm install -g @openai/codex

FROM ghcr.io/baldaworks/balda:latest AS balda

FROM node:24-bookworm-slim
RUN apt-get update \
 && apt-get install -y --no-install-recommends \
      ca-certificates \
      git \
      openssh-client \
      ripgrep \
 && rm -rf /var/lib/apt/lists/*

COPY --from=cli-builder /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=cli-builder /usr/local/bin/codex /usr/local/bin/codex
COPY --from=balda /usr/local/bin/balda /usr/local/bin/balda

WORKDIR /workspace
ENTRYPOINT ["balda"]

Core commands

  • /start owner=<owner_token> — owner bootstrap in direct messages
  • /start invite=<invite_token> — collaborator onboarding
  • /topic <name> — open a focused session
  • /goalkeeper <objective> — run a longer goal loop
  • /goalkeeper clear — stop active goal work in the current session
  • /cancel — stop the current turn
  • /reset or /restart — clear the current session and start fresh
  • /locator — show the current session locator for scheduler/webhook routing

Full command behavior is documented in docs/balda.md.

Configuration

Balda loads .config/balda/config.yaml and then applies BALDA_* environment overrides. If a local .env exists, Balda loads it before resolving config.

Minimal shape:

runtime:
  providers:
    codex:
      type: codex_acp
      codex_acp: {}
  mcp_servers: {}

balda:
  provider: codex
  telegram:
    token: ""

Common settings:

  • balda.provider — which configured provider runtime to use
  • balda.telegram.token — Telegram bot token
  • balda.telegram.formatting_mode — Telegram output mode: rich_markdown (default), rich_html, or none for literal plain text
  • balda.zulip.* — Zulip outgoing webhook bot credentials and receiver config
  • balda.slack.* — Slack Agent credentials plus agent.* HTTP/streaming config
  • balda.webhooks.* — optional inbound webhook routes
  • balda.scheduler.jobs — recurring scheduled jobs
  • balda.workspace.* — workspace/worktree behavior for goal execution
  • balda.permissions.mode — agent permission policy: allow_all, ask, or deny_all
  • balda.permissions.timeout — maximum wait for an interactive permission decision (default 2m)
  • balda.memory.enabled — enable the global explicit-fact memory store and its bundled MCP tools (default true)
  • balda.mcp_servers — MCP servers injected into Balda-started sessions
Explicit fact memory

The bundled balda.memory.remember tool stores explicit facts globally for the Balda instance. Each update records a latest-memory timestamp. On a subsequent session turn, Balda compares that timestamp with the turn's memory cursor. When they differ, Balda adds the complete current fact-memory snapshot to that same provider user prompt in a delimited application-memory block. Unchanged, empty, or disabled memory adds nothing to the prompt. Global fact memory is expected to remain small; it is separate from optional durable session memory.

Knowl sidecar

Run Knowl separately, then register its MCP endpoint through Balda's existing generic configuration:

runtime:
  mcp_servers:
    knowl:
      type: http
      url: http://127.0.0.1:8080/mcp

balda:
  mcp_servers:
    - knowl

This exposes knowl_retrieve, knowl_ingest, and knowl_operation to Balda-started sessions. Balda does not start Knowl, initialize its workspace, own its provider/storage configuration, or automatically ingest conversation turns.

allow_all preserves historical behavior and should be used only where every agent tool call is trusted. Production chat deployments should normally set BALDA_PERMISSIONS_MODE=ask; unsupported channels, missing requester context, cancellation, and timeout fail closed.

Set BALDA_TELEGRAM_FORMATTING_MODE to override the Telegram mode. Existing markdownv2 configurations must move to rich_markdown (or none), and existing html configurations must move to rich_html (or none). Balda does not accept compatibility aliases: an unsupported value fails startup before ingress begins accepting messages. See the Telegram formatting guide for rollout and fallback details.

For complete configuration, examples, and provider-specific details, see docs/balda.md.

Troubleshooting

  • telegram token is required — run balda init or set BALDA_TELEGRAM_TOKEN
  • no supported agent CLI detected — install or expose one of codex, opencode, copilot, gemini, or claude
  • balda.provider is required — rerun balda init or set a configured provider id manually
  • webhook or Slack/Zulip startup issues — verify the matching balda.* integration settings in config
  • workspace import/export issues — check balda.workspace.mode, balda.workspace.base_branch, and the git checkout Balda is running in

Docs

Release

npm releases are published from Git tags through the Omnidist workflow. The workflow uses npm trusted publishing with GitHub Actions OIDC; it does not use a long-lived npm publish token. Each @baldaworks/balda* package trusts the baldaworks/balda repository and the omnidist-release.yml workflow.

Directories

Path Synopsis
cmd
balda command
internal
apps/balda/actorcmd
Package actorcmd defines Balda's stable actor command and event wire taxonomy.
Package actorcmd defines Balda's stable actor command and event wire taxonomy.
apps/balda/actors
Package actors owns Balda product actor behavior and feature-owned orchestration.
Package actors owns Balda product actor behavior and feature-owned orchestration.
apps/balda/actors/goalkeeper
Package goalkeeper owns the goalkeeper feature actor.
Package goalkeeper owns the goalkeeper feature actor.
apps/balda/channel
Package channel contains transport-neutral balda channel contracts.
Package channel contains transport-neutral balda channel contracts.
apps/balda/controlapp
Package controlapp owns application-level control services for Balda jobs and sessions.
Package controlapp owns application-level control services for Balda jobs and sessions.
apps/balda/deliveryfmt
Package deliveryfmt defines transport-neutral delivery presentation options.
Package deliveryfmt defines transport-neutral delivery presentation options.
apps/balda/deliveryfx
Package deliveryfx wires shared delivery adapters, messenger, and router composition used by ingress and delivery workflows.
Package deliveryfx wires shared delivery adapters, messenger, and router composition used by ingress and delivery workflows.
apps/balda/envelopetarget
Package envelopetarget resolves configured envelope targets such as owner aliases and explicit locator references into concrete session delivery addresses.
Package envelopetarget resolves configured envelope targets such as owner aliases and explicit locator references into concrete session delivery addresses.
apps/balda/eventbus
Package eventbus contains Balda's internal event bus configuration model.
Package eventbus contains Balda's internal event bus configuration model.
apps/balda/execution
Package execution owns Balda runtime policy.
Package execution owns Balda runtime policy.
apps/balda/handlers
Package handlers owns Balda ingress behavior.
Package handlers owns Balda ingress behavior.
apps/balda/handlersfx
Package handlersfx owns composition adapters between ingress handlers and concrete runtimes.
Package handlersfx owns composition adapters between ingress handlers and concrete runtimes.
apps/balda/ingressapp
Package ingressapp owns provider-neutral conversational intake settlement.
Package ingressapp owns provider-neutral conversational intake settlement.
apps/balda/jobs
Package jobs owns durable job state and projection-oriented job services.
Package jobs owns durable job state and projection-oriented job services.
apps/balda/permissioncmd
Package permissioncmd defines transport-neutral contracts for permission review.
Package permissioncmd defines transport-neutral contracts for permission review.
apps/balda/permissionfmt
Package permissionfmt renders structured permission requests for concrete delivery channels without inspecting opaque provider input.
Package permissionfmt renders structured permission requests for concrete delivery channels without inspecting opaque provider input.
apps/balda/permissions
Package permissions implements Balda's generic agent permission review policy.
Package permissions implements Balda's generic agent permission review policy.
apps/balda/progressfmt
Package progressfmt renders structured progress updates for concrete delivery channels without relying on model-authored formatting.
Package progressfmt renders structured progress updates for concrete delivery channels without relying on model-authored formatting.
apps/balda/questioncmd
Package questioncmd defines transport-neutral contracts for interactive question flows that may be initiated by any Balda product actor with a valid session-scoped interaction context.
Package questioncmd defines transport-neutral contracts for interactive question flows that may be initiated by any Balda product actor with a valid session-scoped interaction context.
apps/balda/questionfmt
Package questionfmt renders structured question requests for concrete delivery channels without relying on model-authored formatting.
Package questionfmt renders structured question requests for concrete delivery channels without relying on model-authored formatting.
apps/balda/questions
Package questions owns pending-question lifecycle, durable reply settlement, and actor continuation targeting for interactive user questions.
Package questions owns pending-question lifecycle, durable reply settlement, and actor continuation targeting for interactive user questions.
apps/balda/redaction
Package redaction removes credential-shaped values from user-visible text and logs.
Package redaction removes credential-shaped values from user-visible text and logs.
apps/balda/scheduledjobs
Package scheduledjobs owns startup-managed recurring job reconciliation and scheduled job dispatch into Balda turn commands.
Package scheduledjobs owns startup-managed recurring job reconciliation and scheduled job dispatch into Balda turn commands.
apps/balda/sessionapp
Package sessionapp wires Balda session management dependencies and bridges runtime/agent infrastructure into session-owned application ports.
Package sessionapp wires Balda session management dependencies and bridges runtime/agent infrastructure into session-owned application ports.
apps/balda/sessionmemoryapp
Package sessionmemoryapp owns the Balda session-memory processing lifecycle.
Package sessionmemoryapp owns the Balda session-memory processing lifecycle.
apps/balda/sessionmemorycmd
Package sessionmemorycmd defines transport-neutral session-memory export envelopes.
Package sessionmemorycmd defines transport-neutral session-memory export envelopes.
apps/balda/sessionmemorymcp
Package sessionmemorymcp exposes the Balda-owned authentication bridge for the neutral session-memory MCP adapter.
Package sessionmemorymcp exposes the Balda-owned authentication bridge for the neutral session-memory MCP adapter.
apps/balda/sessionmemorytest
Package sessionmemorytest supplies in-process typed ingest capability fakes.
Package sessionmemorytest supplies in-process typed ingest capability fakes.
apps/balda/sessionturn
Package sessionturn owns restoration and execution orchestration for queued session turns.
Package sessionturn owns restoration and execution orchestration for queued session turns.
apps/balda/sessionturnapp
Package sessionturnapp owns queued session-turn application wiring and provider-turn execution helpers above the sessionturn use-case package.
Package sessionturnapp owns queued session-turn application wiring and provider-turn execution helpers above the sessionturn use-case package.
apps/balda/shutdown
Package shutdown classifies errors produced during graceful balda shutdown.
Package shutdown classifies errors produced during graceful balda shutdown.
apps/balda/telegramref
Package telegramref owns Telegram locator and transport identifier helpers that are shared across ingress, application services, and Telegram delivery adapters.
Package telegramref owns Telegram locator and transport identifier helpers that are shared across ingress, application services, and Telegram delivery adapters.
git
logging
Package logging provides application-wide logging configuration.
Package logging provides application-wide logging configuration.
throttle
Package throttle provides small, in-process function throttling.
Package throttle provides small, in-process function throttling.
Package sessionmemory defines portable raw and derived contracts for durable, locator-scoped session memory.
Package sessionmemory defines portable raw and derived contracts for durable, locator-scoped session memory.
app
Package app owns the portable session-memory application use cases.
Package app owns the portable session-memory application use cases.
mcp
Package mcp exposes the transport-neutral session-memory MCP surface.
Package mcp exposes the transport-neutral session-memory MCP surface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL