Skip to content

Commit 39ab20c

Browse files
committed
docs(spec): move lazy loading from design principles to aspirational appendix
Fixes #7 - Remove lazy loading as normative design principle #4, renumber remaining principles 4-6 - Remove standalone Lazy Loading section from spec body - Add D.4 Lazy Loading to Appendix D (Future Host Integration Targets) with current behavior notes - Update Host role description to remove lazy loading ref - Update Host Integration section to remove lazy loading ref - Rewrite lazy-loading.mdx as aspirational feature page - Move Lazy Loading sidebar entry to Reference group with "Aspirational" badge - Update design rationale to remove lazy loading references from Approach C description and implementation scope
1 parent a1ab97f commit 39ab20c

5 files changed

Lines changed: 56 additions & 60 deletions

File tree

astro.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ export default defineConfig({
5252
slug: "specification/install-lifecycle",
5353
},
5454
{ label: "Lockfile", slug: "specification/lockfile" },
55-
{ label: "Lazy Loading", slug: "specification/lazy-loading" },
5655
{ label: "Registry", slug: "specification/registry" },
5756
],
5857
},
@@ -63,6 +62,11 @@ export default defineConfig({
6362
{ label: "Portability", slug: "specification/portability" },
6463
{ label: "Versioning", slug: "specification/versioning" },
6564
{ label: "Appendices", slug: "specification/appendices" },
65+
{
66+
label: "Lazy Loading",
67+
slug: "specification/lazy-loading",
68+
badge: { text: "Aspirational", variant: "caution" },
69+
},
6670
],
6771
},
6872
],

spec/specification.md

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,11 @@ The following principles guide the design of the ccpkg format. Implementors SHOU
5151

5252
3. **Deterministic installation.** Installation MUST be deterministic. Given the same package archive and the same user configuration, the installed result MUST be identical.
5353

54-
4. **Lazy loading.** Installers SHOULD support lazy loading. Only package metadata is loaded at session startup; full component content is loaded on demand when invoked. This minimizes startup time and context token consumption.
54+
4. **No central authority.** No central registry is REQUIRED. Packages MAY be distributed via any URL, file path, or registry. Registries are optional and additive.
5555

56-
5. **No central authority.** No central registry is REQUIRED. Packages MAY be distributed via any URL, file path, or registry. Registries are optional and additive.
56+
5. **Separated configuration.** User configuration MUST be separated from package contents. Secrets, preferences, and environment-specific values live outside the archive and are injected at install or load time.
5757

58-
6. **Separated configuration.** User configuration MUST be separated from package contents. Secrets, preferences, and environment-specific values live outside the archive and are injected at install or load time.
59-
60-
7. **No install-time code execution.** Packages MUST NOT execute arbitrary code during installation. There are no postinstall scripts, no build steps, and no setup hooks. The installation process is purely declarative: extract, configure, register.
58+
6. **No install-time code execution.** Packages MUST NOT execute arbitrary code during installation. There are no postinstall scripts, no build steps, and no setup hooks. The installation process is purely declarative: extract, configure, register.
6159

6260
8. **No inter-package dependencies.** Inter-package dependencies are explicitly out of scope for this specification version. Each package MUST be self-contained and MUST NOT declare dependencies on other ccpkg packages. If a skill requires an MCP server, both MUST be packaged together in a single `.ccpkg` archive.
6361

@@ -90,7 +88,7 @@ flowchart LR
9088
| **Package Author** | Creates the `.ccpkg` archive containing components and a manifest. Authors are responsible for correctness, licensing, and security of package contents. |
9189
| **Registry** | An OPTIONAL service or static file that indexes available packages. Registries provide discovery and version resolution but are not required for installation. |
9290
| **Installer** | The tool or skill that processes `.ccpkg` archives. The installer downloads, verifies, extracts, configures, and registers packages. The ccpkg skill itself serves as the reference installer implementation. |
93-
| **Host** | The AI coding assistant (e.g., Claude Code, Codex CLI) that loads and uses installed components. The host is responsible for component activation, lazy loading, and runtime integration. |
91+
| **Host** | The AI coding assistant (e.g., Claude Code, Codex CLI) that loads and uses installed components. The host is responsible for component activation and runtime integration. |
9492
| **User** | The person who installs and uses packages. Users provide configuration values, approve hook scripts, and control what packages are active. |
9593

9694
### Component Lifecycle
@@ -1095,7 +1093,7 @@ For quick one-off testing without any persistent side effects, developers can us
10951093

10961094
## Host Integration
10971095

1098-
ccpkg integrates with Claude Code's plugin system to provide namespaced installation and component discovery. Rather than placing files directly in user-level directories (where namespacing is unavailable), ccpkg installs packages as Claude Code plugins and leverages the host's existing plugin runtime for component registration, namespace isolation, and lazy loading.
1096+
ccpkg integrates with Claude Code's plugin system to provide namespaced installation and component discovery. Rather than placing files directly in user-level directories (where namespacing is unavailable), ccpkg installs packages as Claude Code plugins and leverages the host's existing plugin runtime for component registration and namespace isolation.
10991097

11001098
### Bootstrap
11011099

@@ -1275,31 +1273,6 @@ The lockfile records the state of all installed packages at a given scope. It en
12751273

12761274
---
12771275

1278-
## Lazy Loading
1279-
1280-
Lazy loading minimizes startup overhead by deferring component activation until the component is actually needed.
1281-
1282-
### Startup Behavior
1283-
1284-
Claude Code already implements lazy loading for skills: frontmatter metadata (name and description) is loaded at startup for discovery, while the full SKILL.md body is loaded on invocation via the Skill tool. This same pattern applies to other component types.
1285-
1286-
ccpkg leverages this existing behavior by placing well-formed component files (SKILL.md, AGENT.md, commands, hooks) in standard plugin directories. No custom host-level lockfile reader is required — the host discovers ccpkg plugins via `extraKnownMarketplaces` → directory source → standard plugin component discovery.
1287-
1288-
At session start, the host scans the `~/.ccpkg/plugins/` directory (registered via `extraKnownMarketplaces`), reads each plugin's `.claude-plugin/plugin.json`, and indexes component metadata for discovery. Full component content is deferred until invocation.
1289-
1290-
### On-Demand Loading
1291-
1292-
| Component | Trigger | What Is Loaded |
1293-
|---|---|---|
1294-
| Skill | LLM decides to activate the skill based on name/description | Full `SKILL.md` body, then `scripts/` and `references/` as needed |
1295-
| Agent | User or LLM activates the agent | Full `AGENT.md` body |
1296-
| Command | User invokes the slash command | Full command file content |
1297-
| Hook | Host event fires matching the hook's event type | Hook script executed |
1298-
| MCP server | First tool invocation targeting the server | Server process started |
1299-
| LSP server | First file opened matching the server's language scope | Server process started |
1300-
1301-
> **Note:** These behaviors are provided by the host application's existing plugin runtime. ccpkg does not implement a custom lazy loading mechanism.
1302-
13031276
---
13041277

13051278
## Remote Component References
@@ -1719,6 +1692,25 @@ The following features are **not currently implementable** without changes to th
17191692

17201693
**Current behavior:** Components are either installed (files exist in the plugin directory and the plugin is enabled) or not. There is no intermediate state. The host loads component content on demand but does not expose activation state to external tools.
17211694

1695+
### D.4 Lazy Loading
1696+
1697+
**Description:** Only package metadata is loaded at session startup. Full component content (SKILL.md bodies, AGENT.md bodies, command files) is deferred until the component is actually invoked. This minimizes startup time and context token consumption.
1698+
1699+
**Requires:** A host-level mechanism to index component metadata (name, description, type) separately from component content, and to load full content on demand at invocation time.
1700+
1701+
**Ideal behavior:** At session start, the host reads only frontmatter or manifest-level metadata for each installed component. When a skill is activated, the full SKILL.md body is loaded. When a command is invoked, the full command file is read. MCP and LSP servers start their processes only on first relevant invocation.
1702+
1703+
| Component | Trigger | What Is Loaded |
1704+
|---|---|---|
1705+
| Skill | LLM activates based on name/description | Full SKILL.md body |
1706+
| Agent | User or LLM activates the agent | Full AGENT.md body |
1707+
| Command | User invokes the slash command | Full command file content |
1708+
| Hook | Host event fires matching the event type | Hook script executed |
1709+
| MCP server | First tool invocation targeting the server | Server process started |
1710+
| LSP server | First file matching the language scope | Server process started |
1711+
1712+
**Current behavior:** Claude Code loads skill frontmatter at startup and defers SKILL.md body loading until Skill tool invocation. This partial lazy loading is host-native behavior, not something ccpkg controls. Other component types do not have equivalent deferred loading. ccpkg packages should be structured to take advantage of whatever lazy loading the host provides, but MUST NOT depend on it.
1713+
17221714
---
17231715

17241716
*This specification is published under the terms of the project's license. For the latest version, see the [ccpkg repository](https://github.com/zircote/ccpkg).*

src/content/docs/design/rationale.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,17 +100,17 @@ Bundles (like Approach A) plus a manifest index file and a lockfile for version
100100

101101
**Pros**: Adds reproducibility via lockfile. Enables basic discovery through the index.
102102

103-
**Cons**: More complex than A without fully solving the problems. The registry is local-only, so discovery is still limited. No lazy loading.
103+
**Cons**: More complex than A without fully solving the problems. The registry is local-only, so discovery is still limited. No deferred component loading.
104104

105105
### Approach C: Lazy Bundle (Selected)
106106

107-
Archive bundles + lockfile + lazy loading + optional decentralized registries + checksum verification.
107+
Archive bundles + lockfile + optional decentralized registries + checksum verification.
108108

109109
**Pros**: Directly targets all three pain points. Builds on the proven mcpb archive pattern. Borrows lazy.nvim's best ideas (deferred loading + lockfiles). Keeps registries optional and decentralized (Homebrew tap model meets Terraform registry protocol). Checksum verification adds the trust layer.
110110

111111
**Cons**: Largest design surface. More to implement. But the complexity maps 1:1 to real problems -- there is no accidental complexity here.
112112

113-
**Selected Approach C.** The additional complexity over A and B is justified because each added component (lazy loading, lockfile, registry protocol) directly eliminates a specific user pain point.
113+
**Selected Approach C.** The additional complexity over A and B is justified because each added component (lockfile, registry protocol, checksum verification) directly eliminates a specific user pain point.
114114

115115
---
116116

@@ -132,7 +132,7 @@ ccpkg itself is a Claude Code plugin. It uses all four extension types available
132132

133133
- **Skills** for interactive, agentic operations (init wizard, search, describe). These are conversational -- Claude adapts its responses based on context.
134134
- **Commands** for deterministic operations (`/ccpkg:install`, `/ccpkg:pack`, `/ccpkg:verify`). Same input, same behavior, every time.
135-
- **Hooks** for enforcement (PostSessionStart lazy loading, integrity verification on install). These run without LLM interpretation.
135+
- **Hooks** for enforcement (integrity verification on install). These run without LLM interpretation.
136136
- **Scripts** (Node.js) for heavy lifting (ZIP handling, SHA256 checksums, lockfile resolution, cache management). Hooks and commands delegate to scripts for anything computationally intensive.
137137

138138
**Why this split?** Each extension type has a natural role. Using the wrong type creates friction: a skill that should be deterministic frustrates users with inconsistent behavior. A command that should be conversational cannot adapt to context. A hook that invokes the LLM adds latency to every session start. The four-type split matches each operation to its natural execution model.
@@ -269,7 +269,7 @@ The ccpkg manager is itself a Claude Code plugin. This is not a gimmick -- it va
269269

270270
- **Commands**: `/ccpkg:init`, `/ccpkg:pack`, `/ccpkg:install`, `/ccpkg:verify`, `/ccpkg:list`, `/ccpkg:update`, `/ccpkg:config`, `/ccpkg:search`
271271
- **Skills**: Interactive init wizard (guides authors through manifest creation), package discovery and search
272-
- **Hooks**: `PostSessionStart` for lazy loading installed packages, integrity verification on install
272+
- **Hooks**: integrity verification on install
273273
- **Scripts**: Node.js/TypeScript for ZIP handling, SHA256 checksum computation, lockfile resolution, cache management, registry queries
274274

275275
### Technology choices
Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
---
22
title: "Lazy Loading"
3-
description: "Startup behavior and on-demand component loading for minimal session overhead."
3+
description: "Aspirational lazy loading behavior for on-demand component activation."
44
---
55

6-
# Lazy Loading
6+
# Lazy Loading (Aspirational)
77

8-
Lazy loading minimizes startup overhead by deferring component activation until the component is actually needed.
8+
Lazy loading is a **future host integration target**, not a current normative requirement. It is documented here to guide host development and package authoring best practices. See [Appendix D](/specification/appendices/) for other aspirational features.
99

10-
## Startup Behavior
10+
ccpkg implementations MUST NOT depend on lazy loading and MUST NOT claim to provide it. Packages should be structured to benefit from whatever lazy loading the host provides natively.
1111

12-
At session start, the host performs the following:
12+
## Ideal Behavior
1313

14-
1. Read the lockfile(s) (user and project scope).
15-
2. For each installed package, load **only** the manifest metadata: `name`, `description`, and the `components` declaration.
16-
3. Register skill and agent names and descriptions for discovery (so the LLM can decide when to activate them).
17-
4. Register command names and descriptions for slash-command completion.
18-
5. Register hook event bindings (but do not execute hook scripts).
19-
20-
The host MUST NOT read full `SKILL.md`, `AGENT.md`, or command file contents at startup.
14+
Only package metadata is loaded at session startup. Full component content (SKILL.md bodies, AGENT.md bodies, command files) is deferred until the component is actually invoked. This minimizes startup time and context token consumption.
2115

2216
## On-Demand Loading
2317

2418
| Component | Trigger | What Is Loaded |
2519
|---|---|---|
26-
| Skill | LLM decides to activate the skill based on name/description | Full `SKILL.md` body, then `scripts/` and `references/` as needed |
27-
| Agent | User or LLM activates the agent | Full `AGENT.md` body |
20+
| Skill | LLM activates based on name/description | Full SKILL.md body |
21+
| Agent | User or LLM activates the agent | Full AGENT.md body |
2822
| Command | User invokes the slash command | Full command file content |
29-
| Hook | Host event fires matching the hook's event type | Hook script executed |
23+
| Hook | Host event fires matching the event type | Hook script executed |
3024
| MCP server | First tool invocation targeting the server | Server process started |
31-
| LSP server | First file opened matching the server's language scope | Server process started |
25+
| LSP server | First file matching the language scope | Server process started |
26+
27+
## Current Behavior
28+
29+
Claude Code loads skill frontmatter at startup and defers SKILL.md body loading until Skill tool invocation. This partial lazy loading is host-native behavior, not something ccpkg controls. Other component types do not have equivalent deferred loading.
30+
31+
## What This Requires
32+
33+
A host-level mechanism to index component metadata (name, description, type) separately from component content, and to load full content on demand at invocation time. No host currently provides this as a general-purpose API.

src/content/docs/specification/overview.mdx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,11 @@ The following principles guide the design of the ccpkg format. Implementors SHOU
5050

5151
3. **Deterministic installation.** Installation MUST be deterministic. Given the same package archive and the same user configuration, the installed result MUST be identical.
5252

53-
4. **Lazy loading.** Installers SHOULD support lazy loading. Only package metadata is loaded at session startup; full component content is loaded on demand when invoked. This minimizes startup time and context token consumption.
53+
4. **No central authority.** No central registry is REQUIRED. Packages MAY be distributed via any URL, file path, or registry. Registries are optional and additive.
5454

55-
5. **No central authority.** No central registry is REQUIRED. Packages MAY be distributed via any URL, file path, or registry. Registries are optional and additive.
55+
5. **Separated configuration.** User configuration MUST be separated from package contents. Secrets, preferences, and environment-specific values live outside the archive and are injected at install or load time.
5656

57-
6. **Separated configuration.** User configuration MUST be separated from package contents. Secrets, preferences, and environment-specific values live outside the archive and are injected at install or load time.
58-
59-
7. **No install-time code execution.** Packages MUST NOT execute arbitrary code during installation. There are no postinstall scripts, no build steps, and no setup hooks. The installation process is purely declarative: extract, configure, register.
57+
6. **No install-time code execution.** Packages MUST NOT execute arbitrary code during installation. There are no postinstall scripts, no build steps, and no setup hooks. The installation process is purely declarative: extract, configure, register.
6058

6159
8. **No inter-package dependencies.** Inter-package dependencies are explicitly out of scope for this specification version. Each package MUST be self-contained and MUST NOT declare dependencies on other ccpkg packages. If a skill requires an MCP server, both MUST be packaged together in a single `.ccpkg` archive.
6260

@@ -89,7 +87,7 @@ flowchart LR
8987
| **Package Author** | Creates the `.ccpkg` archive containing components and a manifest. Authors are responsible for correctness, licensing, and security of package contents. |
9088
| **Registry** | An OPTIONAL service or static file that indexes available packages. Registries provide discovery and version resolution but are not required for installation. |
9189
| **Installer** | The tool or skill that processes `.ccpkg` archives. The installer downloads, verifies, extracts, configures, and registers packages. The ccpkg skill itself serves as the reference installer implementation. |
92-
| **Host** | The AI coding assistant (e.g., Claude Code, Codex CLI) that loads and uses installed components. The host is responsible for component activation, lazy loading, and runtime integration. |
90+
| **Host** | The AI coding assistant (e.g., Claude Code, Codex CLI) that loads and uses installed components. The host is responsible for component activation and runtime integration. |
9391
| **User** | The person who installs and uses packages. Users provide configuration values, approve hook scripts, and control what packages are active. |
9492

9593
### Component Lifecycle

0 commit comments

Comments
 (0)