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/coreacts as the foundational library with no internal dependenciespackages/ai-sdklists@osmosis-agent-toolkit/coreas a regular dependencypackages/mcpalso 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, buildingcore, thenai-sdkandmcpin parallel once dependencies resolvebun run dev– Starts Turbo in watch mode ("persistent": true), rebuilding packages incrementally as source files changebun run clean– Removes compiled artifacts fromdist/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.jsondelegates toturbo run build, which reads the task graph fromturbo.json - The
^builddependency directive ensures topological ordering, compilingcorebefore dependent packages coreproduces dual ESM/CJS outputs via sequentialtscinvocations, whileai-sdkandmcpuse standard single-step compilation- Turbo caches
dist/**andtsconfig.tsbuildinfo, enabling incremental builds that skip unchanged packages - Individual packages can be built in isolation by running
bun run buildwithin 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →