Directory layout
Every installed pack lives at ~/.cognithor/packs/<namespace>/<pack_id>/:
<namespace>/<pack_id>/
pack_manifest.json # required — validated by the loader
pack.py # required — entry point (or custom via entrypoint field)
eula.md # required — SHA-256 pinned in manifest
.eula_accepted # auto-created when user accepts EULA
src/ # your implementation code
tests/ # unit tests
catalog/
catalog.mdx # marketplace listing content
pack_manifest.json
| Field | Type | Required | Description |
|---|---|---|---|
schema_version |
int |
yes | Always 1 |
namespace |
string |
yes | Publisher namespace, lowercase, 1-64 chars (a-z0-9-) |
pack_id |
string |
yes | Pack identifier, same format as namespace |
version |
string |
yes | Semver: X.Y.Z (e.g. 1.0.0) |
display_name |
string |
yes | Human-friendly name |
description |
string |
yes | One-paragraph description |
license |
string |
yes | "apache-2.0" or "proprietary" |
min_cognithor_version |
string |
yes | Version constraint (e.g. ">=0.92.0") |
max_cognithor_version |
string |
no | Upper bound (e.g. "<=2.0.0") |
entrypoint |
string |
no | Default: "pack.py" |
eula_sha256 |
string |
yes | SHA-256 hex digest of eula.md |
publisher |
object |
yes | { id, display_name, website?, contact_email? } |
revenue_share |
object |
no | Default: { creator: 70, platform: 30 } |
lead_sources |
string[] |
no | Declared source IDs (informational) |
tools |
string[] |
no | Declared tool names (informational) |
checkout_url |
string |
no | Lemon Squeezy or Stripe checkout link |
pricing |
object |
conditional | Required when license is "proprietary" |
Pricing tiers
"pricing": {
"indie": {
"list_price": 129,
"launch_price": 75,
"post_launch_price": 89,
"launch_cap": 50,
"currency": "EUR"
}
}
pack.py lifecycle
Your pack.py must export a class named Pack (case-sensitive) extending AgentPack:
from cognithor.packs.interface import AgentPack, PackContext
class Pack(AgentPack):
def register(self, context: PackContext) -> None:
# Called once at startup. Wire tools, sources, routes here.
pass
def unregister(self, context: PackContext) -> None:
# Optional cleanup on shutdown.
pass
PackContext
The context parameter gives you access to Cognithor internals:
| Attribute | Type | Usage |
|---|---|---|
context.mcp_client |
JarvisMCPClient |
Register MCP tools |
context.leads |
LeadService |
Register lead sources |
context.config |
JarvisConfig |
Read configuration |
context.gateway |
Gateway |
Advanced: register REST routes |
All attributes may be None — always check before use.
EULA
Every pack must include an eula.md file. The SHA-256 hash of this file must match the eula_sha256 field in the manifest. Users accept the EULA on first install.
Compute the hash:
python -c "import hashlib, pathlib; print(hashlib.sha256(pathlib.Path('eula.md').read_bytes()).hexdigest())"
Version constraints
The min_cognithor_version field supports operators: >=, >, <=, <, ==.
Example: ">=0.92.0" means your pack requires Cognithor 0.92.0 or newer.