How to Export and Import Company Configurations in Paperclip: Complete Guide
Paperclip lets you move an entire company's configuration—branding, agents, org chart, projects, tasks, and skills—as a portable markdown-first package using REST APIs or the CLI.
Exporting and importing company configurations in Paperclip enables portability across environments, version control of organizational data, and disaster recovery. The system treats company data as a markdown-first package: a zipped archive containing human-readable files plus a .paperclip.yaml side-car for runtime-specific metadata. This guide covers the full workflow using the Paperclip API and paperclipai CLI, with implementation details from the paperclipai/paperclip source code.
Export Workflow: Creating a Portable Company Package
Paperclip exports follow a three-stage pattern: select components, preview the output, then generate the archive.
Selecting Export Components
The include parameter controls which entities ship in the package. Valid flags are company, agents, projects, issues, and skills. The CLI defaults to company plus agents.
In server/src/routes/companies.ts, the export endpoint validates requests using companyPortabilityExportSchema:
router.post("/:companyId/export", async (req, res) => {
const companyId = req.params.companyId as string;
await assertSameCompanyCeoAgentOrBoard(req, companyId, "company exports");
const body = companyPortabilityExportSchema.parse(req.body);
const result = await portability.exportBundle(companyId, body);
res.json(result);
});
Source: companies.ts – export endpoint
Required permission: CEO or Board member of the source company.
Previewing Before Export
Call POST /api/companies/:companyId/exports/preview or use --dry-run to see the exact file list and any environment-input prompts without creating a bundle.
Running the Export
The export produces a .zip with this internal structure:
COMPANY.md— company branding, settings, org chartagents/— agent definitions (one file per agent)skills/— skill configurationsprojects/— project definitions (if included)tasks/orissues/— task/issue data (if included).paperclip.yaml— runtime metadata (adapter configs, budgets, secret references)
CLI command:
paperclipai company export 123e4567-89ab-cdef-0123-456789abcdef \
--out ./my-company \
--include company,agents,projects,issues,skills
Import Workflow: Restoring or Migrating Company Data
Imports support two targets: new company (create) or existing company (update/merge).
Import Targets and Collision Strategies
| Target | Endpoint | Use Case |
|---|---|---|
| New company | POST /api/companies/import |
Fresh migration, sandbox creation |
| Existing company | POST /api/companies/:companyId/imports/apply |
Update agents, sync configurations |
Collision strategies (rename, skip, replace) determine behavior when entities already exist.
Previewing the Import Plan
The preview endpoint parses and validates the package, returning a plan showing which entities will be created, updated, or skipped. In server/src/routes/companies.ts:
router.post("/import/preview", async (req, res) => {
assertBoard(req);
const body = companyPortabilityPreviewSchema.parse(await resolveImportPayload(req, res));
assertImportTargetAccess(req, body.target);
const preview = await portability.previewImport(body);
res.json(preview);
});
Source: companies.ts – import preview
CLI dry-run:
paperclipai company import ./my-company --dry-run
Applying the Import
New company import:
paperclipai company import ./my-company
Existing company import with collision handling:
paperclipai company import ./my-company \
--target existing \
--company-id 123e4567-89ab-cdef-0123-456789abcdef \
--collision rename
The server-side apply logic in server/src/routes/companies.ts:
router.post(COMPANY_IMPORT_ROUTE_PATH, async (req, res) => {
assertBoard(req);
const rawImportBody: unknown = await resolveImportPayload(req, res);
await executeImportRequest(req, res, rawImportBody);
});
Source: companies.ts – import execution
Handling Large Packages: Chunked Transfer Protocol
When packages exceed the inline JSON limit (~48 MiB), Paperclip automatically switches to a resumable chunked transfer.
Chunked Transfer Flow
- Declare transfer —
POST /api/companies/import-transfersreturns a transfer ID and missing parts list - Upload parts —
PUT /api/companies/import-transfers/:transferId/parts/:partIndexwith SHA-256 verification per chunk - Preview assembled package —
POST /api/companies/import-transfers/:transferId/preview - Apply import —
POST /api/companies/import-transfers/:transferId/apply(verifies whole-file hash before processing)
The CLI handles this transparently through resolveChunkedImportZip and uploadCompanyImportTransfer in cli/src/commands/client/company.ts:
// Key functions in cli/src/commands/client/company.ts:
// - resolveInlineSourceFromPath: converts folder/zip to portable JSON
// - resolveChunkedImportZip: decides chunked vs. inline transfer
// - uploadCompanyImportTransfer: orchestrates chunked upload
Source: company.ts – CLI helpers
Source Files and Package Format
| File | Purpose |
|---|---|
server/src/routes/companies.ts |
HTTP endpoints for export, import, preview, and chunked transfer (lines ~90-150) |
packages/shared/src/types/company-portability.ts |
TypeScript types: CompanyPortabilityExportResult, CompanyPortabilityImportResult |
packages/shared/src/validators/company-portability.ts |
Zod schemas: companyPortabilityExportSchema, companyPortabilityPreviewSchema |
cli/src/commands/client/company.ts |
CLI implementation, zip handling, transfer orchestration |
doc/plans/2026-03-13-company-import-export-v2.md |
Product specification for markdown-first format |
doc/companies/companies-spec.md |
Canonical package layout specification |
Summary
- Export and import company configurations as versioned, markdown-first packages using
POST /api/companies/:companyId/exportsandPOST /api/companies/import - Preview changes before applying via
--dry-runor dedicated preview endpoints to avoid surprises - Handle large archives automatically through Paperclip's chunked transfer protocol with SHA-256 verification
- Control collision behavior with
rename,skip, orreplacestrategies when importing into existing companies - Require Board-level permissions for all import operations and company exports
Frequently Asked Questions
What permissions are required to export or import a company?
Exports require CEO or Board member status on the source company. Imports require Board member status system-wide, plus specific access to the target company when importing into an existing organization. These checks are enforced in assertSameCompanyCeoAgentOrBoard() and assertBoard() middleware in server/src/routes/companies.ts.
Can I import a company package into an existing organization without creating duplicates?
Yes. Use the --target existing --collision rename|skip|replace flags when importing. The preview endpoint shows exactly which entities will be created, updated, or skipped before you apply changes. The rename strategy appends numeric suffixes to conflicting names; skip preserves existing values; replace overwrites them.
What happens if my company export is larger than 48 MB?
The CLI automatically detects the size threshold and switches to chunked transfer mode. It declares a transfer ID, uploads the zip in verified parts, then assembles the package server-side before running the import preview or apply. This resume-capable protocol prevents network timeouts and supports unreliable connections.
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 →