Skip to main content
Ink is Polpo’s package registry — a git-native system for distributing and installing playbooks, agent configs, and full company setups. Any GitHub repo (or local directory) that follows the file conventions becomes an Ink registry.
# Install everything from a registry
polpo ink add acme-corp/polpo-registry

# See what's installed
polpo ink list

# Update to latest
polpo ink update
Browse published packages at polpo.sh/ink.

How It Works

Ink uses convention-based discovery. When you run polpo ink add, Polpo clones the target repo and scans for packages by file path:
Package TypeConvention PathContent
Playbookplaybooks/<name>/playbook.jsonPlaybookDefinition
Agentagents/<name>.jsonAgentConfig
Companycompanies/<name>/polpo.jsonFull PolpoFileConfig
A single registry repo can contain any combination of these — up to 100 packages per registry.

Package Types

Playbooks

Reusable mission templates with parameters. Installed to .polpo/playbooks/<name>/.
my-registry/
  playbooks/
    code-review/
      playbook.json     # PlaybookDefinition with {{params}}
    bug-fix/
      playbook.json
After installing, run with polpo playbook run <name>. See Playbooks for the full spec.

Agents

Pre-configured agent definitions with roles, skills, and tool access. Installed to .polpo/ink-agents/<name>.json.
my-registry/
  agents/
    senior-backend-dev.json
    react-specialist.json
    security-auditor.json

Companies

Complete company configurations — multiple agents, team structure, settings, and review criteria. Installed to .polpo/ink-companies/<name>/.
my-registry/
  companies/
    saas-starter/
      polpo.json        # Full PolpoFileConfig
    content-agency/
      polpo.json

Installing Packages

# From a GitHub repo (owner/repo shorthand)
polpo ink add acme-corp/polpo-registry

# From a full GitHub URL
polpo ink add https://github.com/acme-corp/polpo-registry

# From a local directory
polpo ink add ./my-local-registry

# List available packages without installing
polpo ink add acme-corp/polpo-registry --list

# Skip confirmation (for CI/scripts)
polpo ink add acme-corp/polpo-registry --yes
Ink clones the repo into .polpo/ink-cache/, discovers packages by convention, validates each one, and copies them into the appropriate .polpo/ subdirectories.

Lock File

Every install creates or updates .polpo/ink.lock — a JSON file that records:
  • Source — the registry identifier (e.g. acme-corp/polpo-registry)
  • Commit hash — the exact git commit at install time
  • Installed packages — name, type, and content hash for each package
  • Timestamp — when the registry was installed
{
  "version": 1,
  "registries": [
    {
      "source": "acme-corp/polpo-registry",
      "commitHash": "a1b2c3d4e5f6...",
      "installedAt": "2026-03-01T12:00:00.000Z",
      "packages": [
        { "type": "playbook", "name": "code-review", "contentHash": "sha256..." },
        { "type": "agent", "name": "senior-backend-dev", "contentHash": "sha256..." }
      ]
    }
  ]
}
The lock file enables deterministic updates — polpo ink update compares content hashes to show exactly what changed (added, modified, removed) before applying.

Updating & Removing

# Update all installed registries to latest
polpo ink update

# Update a specific registry
polpo ink update acme-corp/polpo-registry

# Remove a registry and all its packages
polpo ink remove acme-corp/polpo-registry
When updating, Ink pulls the latest commit, re-discovers packages, and shows a diff:
  acme-corp/polpo-registry:
    + new  playbook data-pipeline
    ~ changed  agent senior-backend-dev
    - removed  agent deprecated-agent
Use --yes to apply without confirmation.

Security

Ink validates every package before installation:

Structural Validation

  • File size limit: 1 MB per package JSON file
  • Package limit: 100 packages per registry
  • JSON schema validation per type (playbooks must have name, description, mission; agents must have name; companies must have org and teams)

Security Warnings

Ink flags potentially dangerous patterns during installation:
  • Custom systemPrompt on agents — may contain prompt injection
  • Dangerous tools (bash, exec) in an agent’s allowedTools
  • Nested agent systemPrompts within company configs
Warnings are displayed during polpo ink add and require explicit --yes to proceed.

Content Hashing

Every package file is SHA-256 hashed at install time. The hash is stored in ink.lock and used during updates to detect changes.

Creating a Registry

To publish your own packages, create a git repo following the conventions:
mkdir my-registry && cd my-registry
git init

# Add a playbook
mkdir -p playbooks/my-workflow
cat > playbooks/my-workflow/playbook.json << 'EOF'
{
  "name": "my-workflow",
  "description": "A reusable workflow for common tasks",
  "version": "1.0.0",
  "author": "your-name",
  "tags": ["workflow", "automation"],
  "parameters": [
    { "name": "target", "type": "string", "required": true }
  ],
  "mission": {
    "tasks": [
      {
        "title": "Process {{target}}",
        "description": "Run the workflow on {{target}}",
        "assignTo": "default"
      }
    ]
  }
}
EOF

# Add an agent
mkdir -p agents
cat > agents/my-agent.json << 'EOF'
{
  "name": "my-agent",
  "role": "specialist",
  "version": "1.0.0",
  "author": "your-name",
  "tags": ["custom"]
}
EOF

git add . && git commit -m "Initial registry"
git remote add origin git@github.com:your-org/polpo-registry.git
git push
Others can then install with:
polpo ink add your-org/polpo-registry

Optional Metadata

All package types support optional metadata fields for discoverability:
FieldTypeDescription
versionstringSemantic version (e.g. "1.0.0")
authorstringAuthor name or org
tagsstring[]Tags for filtering and search
descriptionstringShort description
These fields are extracted during discovery and displayed during polpo ink add and on polpo.sh/ink.

Install Telemetry

When you install packages, Polpo sends a fire-and-forget POST to the Ink Hub API (polpo.sh/api/installs) with the package names, types, and source. This powers the install count leaderboard on polpo.sh/ink. The request is non-blocking and fails silently — it never interrupts your workflow.