Skip to content

Latest commit

 

History

History
109 lines (74 loc) · 7.03 KB

CONTRIBUTING.md

File metadata and controls

109 lines (74 loc) · 7.03 KB

Contributing to Berth

Thanks for helping. The most useful things you can do are build a resident app and tell us where the berth init → berth dev workflow got in your way. ROADMAP.md lists what works today and what's next.

Berth has one maintainer, so reviews can take a few days. If you hear nothing for a while, a friendly ping on the PR or issue is welcome.

Set up

You need Node.js 22.19+, pnpm (through corepack) and Docker.

git clone https://github.com/Ash20pk/BerthOS && cd BerthOS
corepack enable
pnpm install
pnpm build
node packages/cli/bin/berth.js doctor --fix   # can this machine's kernel enforce anything?

The commands below write berth for node packages/cli/bin/berth.js. Enforcement needs a Linux 6.7+ kernel with Landlock. Docker Desktop doesn't have it; on a Mac, berth doctor --fix sets up a Colima VM that does.

Run the tests

pnpm test                          # everything, through Turborepo
pnpm --filter <package> test       # one package, e.g. pnpm --filter @berthos/sdk test
pnpm lint                          # type-check every package

The Docker-backed integration tests live in packages/docker-orchestrator/test/*.mjs and run against a real container. Run the one that covers what you changed, for example:

node packages/docker-orchestrator/test/context-bus-milestone.mjs

A passing capability-enforcement.mjs run only proves enforcement on a kernel that has Landlock. Check with berth doctor, or cat /sys/kernel/security/lsm.

Build a resident app

This is the quickest route from a clone to a merged PR, and needs no changes under packages/.

berth init my-app     # scaffolds berth.yml and SDK boilerplate from a template
cd my-app
berth dev             # boots it in the sandbox, reloads on save
berth test            # builds the production image and checks every export

Edit src/index.ts and berth.yml. Resident apps explains the manifest, exports and capabilities, and the SDK reference covers the full API. Run berth test before you open the PR.

Resident apps we'd love to see

Each of these is self-contained and makes a good first contribution:

  • Slack: post messages, read channel history, react to events.
  • Postgres / SQL: query and change a database, scoped to specific tables.
  • Email: read, send and search, scoped by label or folder.
  • Linear or Jira: read and create issues, scoped like apps/github-assistant.
  • Stripe: read-only reporting first. Write scopes such as refunds need a design discussion.
  • Playwright QA: a step up from apps/browser-native that runs a test suite instead of free-form browsing.
  • Calendar: read availability, create events.

Have a different idea, or not sure it fits the capability model? Open a resident app proposal, ideally before you write code.

Open a good PR

  • Open it against main, one change per PR.
  • Say what it changes and how you checked it. For anything touching enforcement, say which kernel you ran it on.
  • Run pnpm build, pnpm lint and the tests for the packages you touched.
  • For a new or changed app, berth test passes.
  • Code style: TypeScript in strict mode (tsconfig.base.json). No default exports, except where a package's public API is a single factory, such as a resident app's export default defineApp(...).

Write a doc

Every page in docs/ and docs/design/ follows the C4 model, so a reader knows where to look on any page. After the title and a short opening paragraph come four sections, always in this order:

  1. ## Context: where the subject sits in Berth, and who or what uses it.
  2. ## Containers: the separately running pieces involved (the CLI, a daemon, the sandbox, berth-vmm, an external service) and how they talk.
  3. ## Components: the parts inside the main piece, and how it works.
  4. ## Code: what a developer types or reads: berth.yml, API calls, commands, environment variables, reference tables, links to the source.

Limits, open problems, troubleshooting and the like come after Code. If a level has nothing to say for a page, keep the heading with one line saying so. Add a diagram only when a level has three or more moving parts: each one is a file in scripts/c4/diagrams/, and node scripts/c4-diagrams.mjs renders them all to docs/images/c4/. docs/egress-broker-reference.md is a good page to copy.

Report an issue

Use the issue templates:

  • Bug report: what broke, what you expected, your berth.yml, logs, and berth doctor output.
  • Workflow feedback: what confused you, how long init → dev took, where you got stuck.
  • Resident app proposal: an app you want to build or want to exist.

Security issues go through SECURITY.md, not a public issue.

The agents packages are frozen

Berth is a sandbox, not an agent framework. The agent framework in experimental/ (@berthos/agents, and berthos-agents for Python) exists to show the sandbox works from an agent loop. It is not published and is used from a clone.

Its API is frozen: we don't accept new Crew shapes, new providers or framework-parity features. Bug fixes and security fixes are welcome. To build a richer agent loop on Berth, use the sandbox's own interfaces: berth mcp, toAiSdkTools / toLangChainTools, the HTTP RPC bridge, or the SDK directly.

Working on Berth's internals

If you're changing packages/ rather than building an app, keep these rules:

  • packages/manifest-schema depends on nothing else in the repo. Start there if you're changing the berth.yml format.
  • packages/sdk runs inside the sandbox. It must never import Docker, the CLI or host-only Node APIs.
  • packages/cli never imports the E2B or Daytona SDKs directly. Deploy adapters sit behind the DeployAdapter interface in packages/adapters/adapter-core.
  • packages/context-bus-daemon/proto/context_bus.proto is the wire schema. Keep packages/sdk/proto/context_bus.proto in sync with it by hand.
  • After changing context-bus-daemon, the SDK's context-bus client, apps/filesystem or apps/code-editor, run node packages/docker-orchestrator/test/context-bus-milestone.mjs.
  • packages/context-bus-daemon and packages/agent-init are Rust. You don't need a Rust toolchain to build apps, because berth dev, test and deploy compile them inside the Docker image. To iterate on the daemon locally you need cargo and protoc (brew install protobuf or apk add protobuf).
  • packages/agent-init applies the Landlock policy, so it only enforces on a kernel with Landlock in its LSM stack. In a privileged container, mount securityfs first (mount -t securityfs securityfs /sys/kernel/security) and then check /sys/kernel/security/lsm.