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:

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 models
  • ui/ – Frontend components and state management
  • cli/ – Command implementations and configuration loading
  • packages/adapters/ – AI provider integrations
  • packages/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/shared is 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.ts eliminate 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:

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 →