How the Osmosis Agent Toolkit Monorepo Build Process Works: A Turbo Repo Deep Dive

The Osmosis Agent Toolkit leverages Turbo Repo to orchestrate TypeScript compilation across three interdependent packages, automatically respecting the dependency graph through the caret (^) directive in turbo.json to ensure correct build order and aggressive caching.

The jonator/osmosis-agent-toolkit repository is organized as a Yarn-compatible monorepo containing the core, ai-sdk, and mcp packages. Understanding the Osmosis Agent Toolkit monorepo build process requires examining how Turbo Repo wires together individual package scripts while optimizing for performance through intelligent task scheduling and remote caching.

How Turbo Repo Orchestrates the Build Pipeline

The build entry point resides in the root package.json, which delegates execution to Turbo Repo rather than running build commands directly.

// Root package.json
{
  "scripts": {
    "build": "turbo run build"
  }
}

When you invoke bun run build from the repository root, Turbo Repo reads the task graph defined in turbo.json at the repository root. The configuration specifies that the build task depends on upstream builds completing first:

// turbo.json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "tsconfig.tsbuildinfo"]
    }
  }
}

The caret (^) in "^build" instructs Turbo to execute a package's dependencies' build scripts before its own. This topological sorting ensures that if ai-sdk depends on core, the core package compiles first.

Dependency Graph Resolution

The monorepo structure creates a clear hierarchy that Turbo automatically detects:

  • packages/core acts as the foundational library with no internal dependencies
  • packages/ai-sdk lists @osmosis-agent-toolkit/core as a regular dependency
  • packages/mcp also depends on @osmosis-agent-toolkit/core

Turbo constructs a directed acyclic graph (DAG) from these relationships, guaranteeing core builds completely before either consumer package begins compilation. This prevents type errors and missing module resolutions during the build process.

Package-Level Build Configuration

Each package defines its own build logic within its respective package.json, allowing for specialized compilation strategies based on the package's distribution requirements.

Core Package: Dual Module Support

The core package generates both ESM and CommonJS artifacts to maximize compatibility. In packages/core/package.json, the build script chains two TypeScript compiler invocations:

{
  "scripts": {
    "build": "tsc; tsc -p tsconfig.cjs.json"
  }
}

The first tsc compiles the standard tsconfig.json (ESM output), while the second invocation targets tsconfig.cjs.json to produce the CommonJS bundle. This dual-output approach ensures consumers can import the library regardless of their module system.

AI SDK and MCP Packages

Both ai-sdk and mcp follow a simpler single-step compilation. In packages/ai-sdk/package.json and packages/mcp/package.json, the build script runs a standard TypeScript compilation:

{
  "scripts": {
    "build": "tsc"
  }
}

The mcp package additionally defines a prepublishOnly script at line 24 that re-runs bun run build, ensuring the distributed binary at dist/index.js is always current before npm publication.

Running Builds: Commands and Workflows

The monorepo supports both holistic and targeted build operations. Execute these commands from the repository root:

  • bun run build – Triggers the full Turbo pipeline, building core, then ai-sdk and mcp in parallel once dependencies resolve
  • bun run dev – Starts Turbo in watch mode ("persistent": true), rebuilding packages incrementally as source files change
  • bun run clean – Removes compiled artifacts from dist/ directories and clears Turbo's local cache

For rapid iteration on a single package, navigate to the package directory:

cd packages/core
bun run build

This bypasses the Turbo orchestration and runs only that package's build script, useful when you haven't modified upstream dependencies.

Build Outputs and Caching Strategy

Turbo's performance relies on declarative output definitions. The turbo.json configuration explicitly declares:

{
  "outputs": ["dist/**", "tsconfig.tsbuildinfo"]
}

These paths tell Turbo which files to cache after a successful build. The dist/** glob captures all compiled JavaScript and type definitions, while tsconfig.tsbuildinfo enables TypeScript's incremental compilation. When you run a subsequent build, Turbo computes content hashes for source files and restores cached outputs for unchanged packages, often reducing build times to milliseconds.

Each package's prepublishOnly script provides a safety mechanism by forcing a fresh build before npm publication, preventing stale artifacts from reaching the registry.

Summary

  • The root package.json delegates to turbo run build, which reads the task graph from turbo.json
  • The ^build dependency directive ensures topological ordering, compiling core before dependent packages
  • core produces dual ESM/CJS outputs via sequential tsc invocations, while ai-sdk and mcp use standard single-step compilation
  • Turbo caches dist/** and tsconfig.tsbuildinfo, enabling incremental builds that skip unchanged packages
  • Individual packages can be built in isolation by running bun run build within their respective directories

Frequently Asked Questions

What build tool does the Osmosis Agent Toolkit monorepo use?

The repository uses Turbo Repo for build orchestration and Bun as the package manager and runtime. While the monorepo structure is Yarn-compatible (using workspaces), the actual build commands leverage Turbo's task scheduling and caching capabilities defined in turbo.json.

How does the monorepo handle the core package dependency?

Turbo automatically detects the dependency relationships through package.json files. Because both ai-sdk and mcp list @osmosis-agent-toolkit/core as a dependency, Turbo's ^build directive ensures the core package finishes compiling before any consumer package begins its build step.

Why does the core package have two TypeScript compilation steps?

The core package targets both ECMAScript Modules (ESM) and CommonJS (CJS) consumers. The build script tsc; tsc -p tsconfig.cjs.json first compiles the standard TypeScript configuration for ESM output, then uses a specialized tsconfig.cjs.json to generate CommonJS-compatible JavaScript, maximizing interoperability across different consuming projects.

How do I build only a single package during development?

Navigate to the specific package directory (e.g., cd packages/mcp) and run bun run build. This executes the package's local build script directly, bypassing Turbo's orchestration. This approach is optimal when you haven't modified the core package and want faster feedback loops during iterative development.

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 →