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.jsonwith 10 defined workspaces acrossagents/,cli/,common/,evals/,freebuff/,packages/*,sdk/, andscripts/*. - 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.jsonandbunfig.toml, extended or referenced by each workspace. - Published vs. private packages: only
@codebuff/sdkis published; remaining workspaces stay internal with"private": true. - Adding workspaces in
packages/orscripts/requires no root configuration changes due to glob patterns; other locations need explicit addition to theworkspacesarray.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →