What Is the `packages/shared` Directory in Paperclip? A Complete Guide to Shared Types, Constants, and Validators
The packages/shared directory in Paperclip serves as the single source of truth for all cross-boundary contracts between the backend server, CLI, UI, and external adapters, containing shared TypeScript types, constants, Zod validators, and telemetry definitions.
Paperclip is a control-plane platform that enforces strict company-scoped boundaries across its entire ecosystem. To maintain type safety and prevent interface drift, the project centralizes every cross-cutting contract in packages/shared. This article examines its architecture, key files, and practical usage patterns drawn directly from the Paperclip source code.
Core Responsibilities of packages/shared
The packages/shared package eliminates duplication and guarantees consistency across the monorepo. According to AGENTS.md, this directory holds shared types, constants, validators, and API path constants that the server, UI, and adapters all depend on.
Domain Types in src/types/index.ts
The type system hub lives at src/types/index.ts, which re-exports dozens of domain types as a master barrel file. This includes Issue, Project, Agent, ToolConnection, PluginManifest, and other core entities.
// Import a shared type in a server route
import { Issue } from "@paperclipai/paperclip/packages/shared/src/types/issue.js";
export async function getIssue(id: string): Promise<Issue> {
return db.selectFrom("issues").where("id", "=", id).executeTakeFirstOrThrow();
}
Centralizing types here ensures the server, UI, and adapters speak identical ShapeScript/TypeScript interfaces. When the Issue type changes, every consuming package receives the update through a single dependency.
Canonical Constants in src/constants.ts
src/constants.ts defines canonical enums including AGENT_STATUSES, ISSUE_STATUSES, DEPLOYMENT_MODES, and PLUGIN_CAPABILITIES. These hard-coded strings propagate throughout the system without risk of mismatched literals.
// Use a shared constant in the UI
import { ISSUE_STATUSES } from "@paperclipai/paperclip/packages/shared/src/constants.js";
const statusOptions = ISSUE_STATUSES.map(s => ({
value: s,
label: s.replace(/_/g, " ").toUpperCase(),
}));
Centralizing enums makes refactors safe. Changing ISSUE_STATUSES in one place automatically updates validation logic, database constraints, and UI dropdowns.
Runtime Validation with Zod Schemas
The validators/ directory translates TypeScript types into runtime Zod validation rules. Files like validators/company.ts and validators/issue.ts guarantee that incoming API payloads match the exact definitions used elsewhere.
// Validate incoming payloads with a shared Zod schema
import { createCompanySchema } from "@paperclipai/paperclip/packages/shared/src/validators/company.js";
export async function handleCreateCompany(req: Request) {
const payload = await req.json();
const data = createCompanySchema.parse(payload); // throws if invalid
// proceed with creation...
}
This pattern unifies compile-time and runtime type safety. The same schema validates CLI inputs, API requests, and test fixtures.
Configuration Schema in src/config-schema.ts
src/config-schema.ts describes the shape of the .paperclip configuration file that both the CLI and server consume. This provides a single validation point and enables schema reuse in documentation and tests.
// Example: config validation shared between CLI and server
import { configSchema } from "@paperclipai/paperclip/packages/shared/src/config-schema.js";
const validated = configSchema.parse(rawConfig);
Telemetry Contract in src/telemetry/
The telemetry/ directory contains README.md and generated event definitions (telemetry/generated/paperclip-telemetry.ts). Any package can emit events conforming to this shared contract, ensuring consistent analytics across the platform.
// Emit a telemetry event from any package
import { client } from "@paperclipai/paperclip/packages/shared/src/telemetry/telemetry.js";
client.track("company.created", { companyId: "c_1234" });
Plugin and Adapter Contracts
packages/shared defines the interoperability layer for Paperclip's extensibility system:
src/types/plugin.ts–PluginManifestV1,ToolAccess, andPluginCapabilitytypessrc/adapter-types.ts–AdapterTypeand related contracts consumed bypackages/adapters/
These definitions enable third-party plugins and AI adapters to integrate without duplicating type declarations.
Key Files Reference
| File | Purpose |
|---|---|
src/types/index.ts |
Master barrel export of all domain types |
src/constants.ts |
Canonical enums and primitive constants |
src/config-schema.ts |
CLI/server configuration validation |
src/validators/*.ts |
Zod runtime validators |
src/telemetry/README.md |
Telemetry data contract documentation |
src/types/plugin.ts |
Plugin manifest and capability types |
src/adapter-types.ts |
Adapter interoperability contracts |
Who Imports packages/shared
The packages/shared directory is imported throughout the monorepo:
server/– API route handlers and database modelsui/– Frontend components and state managementcli/– Command implementations and configuration loadingpackages/adapters/– AI provider integrationspackages/plugins/– Third-party extension system
As noted in doc/SPEC-implementation.md at line 91, this package is listed as a core architectural component.
Summary
packages/sharedis the single source of truth for types, constants, and validation rules across the entire Paperclip ecosystem- Centralized contracts prevent interface drift between the server, CLI, UI, and adapters
- Zod validators in
validators/unify compile-time and runtime type safety - Constants in
constants.tseliminate hard-coded string duplication - Telemetry and plugin contracts enable consistent extensibility
Frequently Asked Questions
What types are defined in packages/shared/src/types/index.ts?
The master barrel file exports domain types including Issue, Project, Agent, ToolConnection, PluginManifest, Company, and related entities. These types are imported by the server, UI, CLI, and adapter packages to ensure identical data shapes across all layers.
How does packages/shared prevent bugs in Paperclip?
By centralizing constants and types, the package eliminates mismatched string literals and interface drift. When AGENT_STATUSES or the Issue type changes, all consumers receive the update through their shared dependency rather than requiring manual coordination across packages.
What's the relationship between TypeScript types and Zod validators in packages/shared?
TypeScript types provide compile-time safety while Zod validators in validators/ provide runtime validation. Both derive from the same source of truth, ensuring that API payloads, CLI inputs, and database records all conform to identical constraints.
Can external plugins use packages/shared?
Yes. The PluginManifestV1 type and related contracts in src/types/plugin.ts are specifically designed for third-party plugins and adapters. The packages/adapters/ directory imports src/adapter-types.ts to implement AI provider integrations without duplicating type definitions.
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 →