Freebuff Monorepo Workspace Structure: Complete Technical Guide

Freebuff uses a TypeScript monorepo with npm/Bun workspaces where the root package.json declares 10 distinct workspaces including agents, cli, sdk, and specialized packages under packages/*, enabling isolated development with cross-workspace dependencies via the workspace:* protocol.

The Freebuff monorepo workspace structure powers CodebuffAI's AI-assisted coding platform. Built on Bun and organized into logical, independently buildable units, this architecture lets teams develop the CLI, desktop app, SDK, and core agent runtime as separate packages while sharing types and utilities through a unified source tree.

How Freebuff Defines Workspaces in package.json

In CodebuffAI/freebuff, workspace membership is declared explicitly. The root package.json lists all workspace directories in a top-level workspaces array (lines 7-17), which Bun interprets to establish the monorepo boundary.

// package.json (root)
{
  "name": "@codebuff/root",
  "private": true,
  "packageManager": "bun@1.3.14",
  "workspaces": [
    "agents",
    "cli",
    "common",
    "evals",
    "freebuff",
    "packages/*",
    "sdk",
    "scripts/*"
  ]
}

This declaration pattern—supported by npm, Yarn, and PNPM—lets Bun hoist dependencies and resolve local package names to their source folders automatically.

Complete Freebuff Workspace Inventory

Workspace Path Purpose Published?
agents agents/ Core AI agents (CodeReviewers, Thinkers, Editors) Private
cli cli/ Terminal UI client (codebuff-tui binary) Private
common common/ Shared utilities, types, constants, helpers Private
evals evals/ Benchmarking and agent performance evaluation Private
freebuff freebuff/ Electron-based desktop application Private
agent-runtime packages/agent-runtime/ Orchestrates and executes agents Private
code-map packages/code-map/ Source parsing and codebase mapping Private
llm-providers packages/llm-providers/ LLM backend adapters (OpenAI, Anthropic, Gemini) Private
tmux scripts scripts/tmux/ CI/e2e automation helpers Private
sdk sdk/ Public TypeScript SDK (@codebuff/sdk) Published

The packages/* and scripts/* globs demonstrate how Freebuff groups related workspaces without listing each individually.

Cross-Workspace Dependencies with workspace:*

Freebuff leverages the workspace:* protocol to link internal packages. This ensures consuming workspaces always use the local source version, not a registry copy.

In cli/package.json, the SDK and runtime are declared as workspace dependencies:

{
  "name": "@codebuff/cli",
  "dependencies": {
    "@codebuff/sdk": "workspace:*",
    "@codebuff/agent-runtime": "workspace:*",
    "@codebuff/common": "workspace:*"
  }
}

At installation, Bun resolves @codebuff/sdk to sdk/ locally. The * accepts any version stored in that workspace's package.json.

Shared Configuration Architecture

TypeScript Base Configuration

Each workspace extends tsconfig.base.json from the root for consistent compiler settings:

// packages/agent-runtime/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src/**/*"]
}

This pattern centralizes strictness rules, target versions, and path mappings while allowing per-workspace customization.

Bun-Specific Build Settings

The root bunfig.toml applies shared build configuration:

[install]
cache = true
exact = true

[run]
bun = true

Practical Workspace Operations

Installing Dependencies Across All Workspaces


# From repository root

bun install

# Installs root + all workspace dependencies with hoisting

Running Commands in Specific Workspaces


# Build only the SDK

cd sdk && bun run build

# Or use Bun's --filter flag from root

bun run --filter @codebuff/sdk build

Creating a New Workspace Step-by-Step


# 1. Create directory

mkdir packages/new-integration

# 2. Initialize package.json

cat > packages/new-integration/package.json <<'EOF'
{
  "name": "@codebuff/new-integration",
  "version": "0.0.0",
  "private": true,
  "type": "module",
  "main": "./src/index.ts",
  "exports": {
    ".": "./src/index.ts"
  }
}
EOF

# 3. Add to root workspaces (already covered by packages/* glob)

# No root package.json edit needed for packages/* paths

After bun install, import from other workspaces immediately:

// packages/new-integration/src/client.ts
import { askUserBridge } from "@codebuff/common";
import type { LlmProvider } from "@codebuff/llm-providers";

export async function createClient(provider: LlmProvider) {
  const config = await askUserBridge.loadConfig();
  // ...
}

Workspace Isolation and Dependency Boundaries

Freebuff enforces clean boundaries through its structure. The common workspace at common/package.json serves as the only universally shared dependency, preventing circular references between functional domains:

// Permitted: cli → sdk → common
// Permitted: agents → agent-runtime → llm-providers → common
// Avoided: agents direct import from cli (would create coupling)

The evals workspace demonstrates intentional isolation—it benchmarks agents without being imported by production code, ensuring evaluation utilities don't bloat releases.

Summary

  • Freebuff's monorepo structure uses Bun workspaces declared in the root package.json with 10 defined workspaces across agents/, cli/, common/, evals/, freebuff/, packages/*, sdk/, and scripts/*.
  • Cross-workspace linking relies on the workspace:* protocol in dependency declarations, resolved by Bun to local source folders.
  • Shared infrastructure comes from root-level tsconfig.base.json and bunfig.toml, extended or referenced by each workspace.
  • Published vs. private packages: only @codebuff/sdk is published; remaining workspaces stay internal with "private": true.
  • Adding workspaces in packages/ or scripts/ requires no root configuration changes due to glob patterns; other locations need explicit addition to the workspaces array.

Frequently Asked Questions

What package manager does Freebuff use for its monorepo?

Freebuff uses Bun as its primary package manager. The root package.json specifies "packageManager": "bun@1.3.14", and all workspace resolution, installation, and script running happens through Bun's native workspace support, which maintains compatibility with the npm workspaces specification.

How does Freebuff prevent workspace dependency conflicts?

Freebuff minimizes conflicts through hoisting (Bun deduplicates compatible versions at root) and strict workspace boundaries. The common workspace centralizes shared types and utilities, reducing duplication. Each workspace maintains its own package.json with explicit dependency versions, and workspace:* protocol usage ensures local resolution takes precedence over registry versions.

Can I run a single workspace's tests without building everything?

Yes. Each workspace contains independent scripts in its package.json. Navigate to any workspace folder and run bun test or bun run typecheck to validate only that package. For CI efficiency, Bun's --filter flag from root targets specific workspaces without processing unaffected ones.

Why does Freebuff separate agent-runtime from agents?

The packages/agent-runtime/ workspace provides the execution engine that loads and orchestrates agents, while agents/ contains the agent implementations themselves (behaviors, prompts, logic). This separation lets the runtime evolve independently from agent logic and enables third-party agents to run on the same runtime without residing in the main repository.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →