@tekmidian/pai 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -10
- package/dist/{auto-route-D54Kv7yI.mjs → auto-route-CLYcToZ5.mjs} +4 -4
- package/dist/{auto-route-D54Kv7yI.mjs.map → auto-route-CLYcToZ5.mjs.map} +1 -1
- package/dist/cli/index.mjs +20 -10275
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/program.d.mts +11 -0
- package/dist/cli/program.d.mts.map +1 -0
- package/dist/cli/program.mjs +249 -0
- package/dist/cli/program.mjs.map +1 -0
- package/dist/{clusters-BwmdKB-V.mjs → clusters-BYPw7vfW.mjs} +2 -2
- package/dist/{clusters-BwmdKB-V.mjs.map → clusters-BYPw7vfW.mjs.map} +1 -1
- package/dist/{config-DqBY3aT0.mjs → config-BuhHWyOK.mjs} +1 -1
- package/dist/{config-DqBY3aT0.mjs.map → config-BuhHWyOK.mjs.map} +1 -1
- package/dist/daemon/index.mjs +16 -18
- package/dist/daemon/index.mjs.map +1 -1
- package/dist/{daemon-CSKj8Xm9.mjs → daemon-DDplhnm9.mjs} +185 -31
- package/dist/daemon-DDplhnm9.mjs.map +1 -0
- package/dist/daemon-mcp/index.mjs +2 -2
- package/dist/{db-CYmBWcjh.mjs → db-CmYbAVCD.mjs} +1 -1
- package/dist/{db-CYmBWcjh.mjs.map → db-CmYbAVCD.mjs.map} +1 -1
- package/dist/{detect-CdaA48EI.mjs → detect-KjycLtXM.mjs} +1 -1
- package/dist/{detect-CdaA48EI.mjs.map → detect-KjycLtXM.mjs.map} +1 -1
- package/dist/{detector-Q_lVXtj-.mjs → detector-ZiOhHszd.mjs} +2 -2
- package/dist/{detector-Q_lVXtj-.mjs.map → detector-ZiOhHszd.mjs.map} +1 -1
- package/dist/{embeddings-DGRAPAYb.mjs → embeddings-BJPOcbik.mjs} +1 -1
- package/dist/{embeddings-DGRAPAYb.mjs.map → embeddings-BJPOcbik.mjs.map} +1 -1
- package/dist/{factory-BufouUQ1.mjs → factory-CayQCMoN.mjs} +5 -8
- package/dist/{factory-BufouUQ1.mjs.map → factory-CayQCMoN.mjs.map} +1 -1
- package/dist/{helpers-crDEr6S2.mjs → helpers-IjZkXBhj.mjs} +1 -1
- package/dist/{helpers-crDEr6S2.mjs.map → helpers-IjZkXBhj.mjs.map} +1 -1
- package/dist/hooks/observe.mjs +21 -0
- package/dist/hooks/observe.mjs.map +2 -2
- package/dist/index.mjs +9 -10
- package/dist/{indexer-backend-DcYThufd.mjs → indexer-backend-Cm5RS7y0.mjs} +3 -3
- package/dist/{indexer-backend-DcYThufd.mjs.map → indexer-backend-Cm5RS7y0.mjs.map} +1 -1
- package/dist/{ipc-client-C3pjwy2m.mjs → ipc-client-CoyUHPod.mjs} +1 -1
- package/dist/{ipc-client-C3pjwy2m.mjs.map → ipc-client-CoyUHPod.mjs.map} +1 -1
- package/dist/{kg-entity-DVzTsy6G.mjs → kg-entity-LXblD7LZ.mjs} +1 -1
- package/dist/{kg-entity-DVzTsy6G.mjs.map → kg-entity-LXblD7LZ.mjs.map} +1 -1
- package/dist/{kg-extraction-iR1BKKWK.mjs → kg-extraction-C8DEUHTS.mjs} +17 -6
- package/dist/kg-extraction-C8DEUHTS.mjs.map +1 -0
- package/dist/{latent-ideas-dWVuI_dg.mjs → latent-ideas-RyC6eyqI.mjs} +4 -4
- package/dist/{latent-ideas-dWVuI_dg.mjs.map → latent-ideas-RyC6eyqI.mjs.map} +1 -1
- package/dist/main-resolver-uFxNiDy7.mjs +1339 -0
- package/dist/main-resolver-uFxNiDy7.mjs.map +1 -0
- package/dist/{migrate-fLD6rAdO.mjs → migrate-B02wDDgS.mjs} +2 -2
- package/dist/{migrate-fLD6rAdO.mjs.map → migrate-B02wDDgS.mjs.map} +1 -1
- package/dist/{neighborhood-DixmpfPT.mjs → neighborhood-CklGIB8r.mjs} +2 -2
- package/dist/{neighborhood-DixmpfPT.mjs.map → neighborhood-CklGIB8r.mjs.map} +1 -1
- package/dist/{note-context-BY7rfGdl.mjs → note-context-qvZlVXVO.mjs} +1 -1
- package/dist/{note-context-BY7rfGdl.mjs.map → note-context-qvZlVXVO.mjs.map} +1 -1
- package/dist/{pai-marker-CXQPX2P6.mjs → pai-marker-HVBwwBW-.mjs} +1 -1
- package/dist/{pai-marker-CXQPX2P6.mjs.map → pai-marker-HVBwwBW-.mjs.map} +1 -1
- package/dist/pick-Dt21ojcW.mjs +8250 -0
- package/dist/pick-Dt21ojcW.mjs.map +1 -0
- package/dist/{postgres-Cp25xZes.mjs → postgres-B451Hnkm.mjs} +2 -2
- package/dist/{postgres-Cp25xZes.mjs.map → postgres-B451Hnkm.mjs.map} +1 -1
- package/dist/{query-feedback-C0hKUHVz.mjs → query-feedback-fapbqRgh.mjs} +1 -1
- package/dist/{query-feedback-C0hKUHVz.mjs.map → query-feedback-fapbqRgh.mjs.map} +1 -1
- package/dist/{reranker-CMNZcfVx.mjs → reranker-C08R99zn.mjs} +1 -1
- package/dist/{reranker-CMNZcfVx.mjs.map → reranker-C08R99zn.mjs.map} +1 -1
- package/dist/{search-i2nlQ-JM.mjs → search-HcdKtMla.mjs} +3 -3
- package/dist/{search-i2nlQ-JM.mjs.map → search-HcdKtMla.mjs.map} +1 -1
- package/dist/{sqlite-B3JHfJc2.mjs → sqlite-DQpY1Esi.mjs} +3 -3
- package/dist/{sqlite-B3JHfJc2.mjs.map → sqlite-DQpY1Esi.mjs.map} +1 -1
- package/dist/{state-BHZAhLou.mjs → state-BIlxNRUn.mjs} +1 -1
- package/dist/{state-BHZAhLou.mjs.map → state-BIlxNRUn.mjs.map} +1 -1
- package/dist/{stop-words-BaMEGVeY.mjs → stop-words-BwplsQ3z.mjs} +1 -1
- package/dist/{stop-words-BaMEGVeY.mjs.map → stop-words-BwplsQ3z.mjs.map} +1 -1
- package/dist/{sync-CmBKOL3K.mjs → sync-uPR4g438.mjs} +205 -6
- package/dist/sync-uPR4g438.mjs.map +1 -0
- package/dist/{themes-DO8mUVwD.mjs → themes-Cg8oG9Ra.mjs} +3 -3
- package/dist/{themes-DO8mUVwD.mjs.map → themes-Cg8oG9Ra.mjs.map} +1 -1
- package/dist/{tools-C1JNgya7.mjs → tools-Op3C2Nm6.mjs} +26 -26
- package/dist/{tools-C1JNgya7.mjs.map → tools-Op3C2Nm6.mjs.map} +1 -1
- package/dist/{trace-TYCLMCkY.mjs → trace-CLK-NPkb.mjs} +1 -1
- package/dist/{trace-TYCLMCkY.mjs.map → trace-CLK-NPkb.mjs.map} +1 -1
- package/dist/{utils-BAxjW3j8.mjs → utils-CqqgB0dH.mjs} +1 -1
- package/dist/{utils-BAxjW3j8.mjs.map → utils-CqqgB0dH.mjs.map} +1 -1
- package/dist/{vault-indexer-vNnL3Azb.mjs → vault-indexer-Dn_BccVK.mjs} +2 -2
- package/dist/{vault-indexer-vNnL3Azb.mjs.map → vault-indexer-Dn_BccVK.mjs.map} +1 -1
- package/dist/{work-queue-worker-BxsBtz6j.mjs → work-queue-worker-DHOIVVQ7.mjs} +5 -5
- package/dist/{work-queue-worker-BxsBtz6j.mjs.map → work-queue-worker-DHOIVVQ7.mjs.map} +1 -1
- package/dist/{zettelkasten-B-94vghH.mjs → zettelkasten-NwBD1NsT.mjs} +4 -4
- package/dist/{zettelkasten-B-94vghH.mjs.map → zettelkasten-NwBD1NsT.mjs.map} +1 -1
- package/docs/commands/README.md +151 -0
- package/docs/commands/_examples/kg.md +13 -0
- package/docs/commands/_examples/memory.md +13 -0
- package/docs/commands/_examples/observation.md +13 -0
- package/docs/commands/_examples/projects.md +16 -0
- package/docs/commands/_examples/skill.md +13 -0
- package/docs/commands/_examples/zettel.md +13 -0
- package/docs/commands/backup.md +24 -0
- package/docs/commands/clear-names.md +27 -0
- package/docs/commands/daemon.md +78 -0
- package/docs/commands/db.md +74 -0
- package/docs/commands/end.md +24 -0
- package/docs/commands/help.md +30 -0
- package/docs/commands/kg.md +89 -0
- package/docs/commands/mcp.md +35 -0
- package/docs/commands/memory.md +125 -0
- package/docs/commands/notify.md +83 -0
- package/docs/commands/observation.md +80 -0
- package/docs/commands/obsidian.md +60 -0
- package/docs/commands/pause.md +35 -0
- package/docs/commands/project.md +345 -0
- package/docs/commands/projects.md +364 -0
- package/docs/commands/registry.md +68 -0
- package/docs/commands/restore.md +31 -0
- package/docs/commands/sessions.md +25 -0
- package/docs/commands/setup.md +20 -0
- package/docs/commands/shell-init.md +18 -0
- package/docs/commands/skill.md +54 -0
- package/docs/commands/topic.md +46 -0
- package/docs/commands/update.md +18 -0
- package/docs/commands/zettel.md +151 -0
- package/docs/mcp-skill-guide.md +292 -0
- package/package.json +4 -2
- package/scripts/build-docs.mjs +371 -0
- package/src/hooks/ts/post-tool-use/observe.ts +43 -0
- package/dist/daemon-CSKj8Xm9.mjs.map +0 -1
- package/dist/db-BtuN768f.mjs +0 -206
- package/dist/db-BtuN768f.mjs.map +0 -1
- package/dist/indexer-D7MvSQPY.mjs +0 -1
- package/dist/kg-extraction-iR1BKKWK.mjs.map +0 -1
- package/dist/sync-CmBKOL3K.mjs.map +0 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<!-- GENERATED by scripts/build-docs.mjs from the live Commander tree (src/cli/program.ts). Do not edit by hand. -->
|
|
2
|
+
|
|
3
|
+
# pai zettel
|
|
4
|
+
|
|
5
|
+
> Zettelkasten intelligence: explore, surprise, converse, themes, health, suggest
|
|
6
|
+
|
|
7
|
+
## Synopsis
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pai zettel <subcommand> [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Subcommands
|
|
14
|
+
|
|
15
|
+
| Command | Description |
|
|
16
|
+
|---------|-------------|
|
|
17
|
+
| [`pai zettel explore <note>`](#pai-zettel-explore-note) | Follow link chains from a starting note |
|
|
18
|
+
| [`pai zettel health`](#pai-zettel-health) | Vault structural health audit: dead links, orphans, connectivity |
|
|
19
|
+
| [`pai zettel surprise <note>`](#pai-zettel-surprise-note) | Find semantically similar but graph-distant notes (surprising connections) |
|
|
20
|
+
| [`pai zettel suggest <note>`](#pai-zettel-suggest-note) | Suggest new wikilink connections for a note |
|
|
21
|
+
| [`pai zettel converse <question>`](#pai-zettel-converse-question) | Ask the vault a question and get a synthesis prompt with relevant notes |
|
|
22
|
+
| [`pai zettel themes`](#pai-zettel-themes) | Detect emerging theme clusters in recently edited notes |
|
|
23
|
+
|
|
24
|
+
### pai zettel explore <note>
|
|
25
|
+
|
|
26
|
+
Follow link chains from a starting note
|
|
27
|
+
|
|
28
|
+
**Arguments**
|
|
29
|
+
|
|
30
|
+
| Argument | Kind |
|
|
31
|
+
|----------|------|
|
|
32
|
+
| `<note>` | required |
|
|
33
|
+
|
|
34
|
+
**Options**
|
|
35
|
+
|
|
36
|
+
| Option | Description | Default |
|
|
37
|
+
|--------|-------------|---------|
|
|
38
|
+
| `--depth <n>` | Maximum traversal depth (1-10) | `3` |
|
|
39
|
+
| `--direction <d>` | Link direction: forward \| backward \| both | `both` |
|
|
40
|
+
| `--mode <m>` | Edge mode: sequential \| associative \| all | `all` |
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### pai zettel health
|
|
44
|
+
|
|
45
|
+
Vault structural health audit: dead links, orphans, connectivity
|
|
46
|
+
|
|
47
|
+
**Options**
|
|
48
|
+
|
|
49
|
+
| Option | Description | Default |
|
|
50
|
+
|--------|-------------|---------|
|
|
51
|
+
| `--scope <s>` | Scope: full \| recent \| project | `full` |
|
|
52
|
+
| `--project <path>` | Project path prefix (requires --scope project) | |
|
|
53
|
+
| `--days <n>` | Look-back window in days (requires --scope recent) | `30` |
|
|
54
|
+
| `--include <types>` | Comma-separated subset: dead_links,orphans,disconnected,low_connectivity | |
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
### pai zettel surprise <note>
|
|
58
|
+
|
|
59
|
+
Find semantically similar but graph-distant notes (surprising connections)
|
|
60
|
+
|
|
61
|
+
**Arguments**
|
|
62
|
+
|
|
63
|
+
| Argument | Kind |
|
|
64
|
+
|----------|------|
|
|
65
|
+
| `<note>` | required |
|
|
66
|
+
|
|
67
|
+
**Options**
|
|
68
|
+
|
|
69
|
+
| Option | Description | Default |
|
|
70
|
+
|--------|-------------|---------|
|
|
71
|
+
| `--vault-project-id <n>` | Project ID for the vault in the federation DB | |
|
|
72
|
+
| `--limit <n>` | Maximum results | `10` |
|
|
73
|
+
| `--min-similarity <f>` | Minimum cosine similarity (0–1) | `0.3` |
|
|
74
|
+
| `--min-distance <n>` | Minimum graph distance | `3` |
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
### pai zettel suggest <note>
|
|
78
|
+
|
|
79
|
+
Suggest new wikilink connections for a note
|
|
80
|
+
|
|
81
|
+
**Arguments**
|
|
82
|
+
|
|
83
|
+
| Argument | Kind |
|
|
84
|
+
|----------|------|
|
|
85
|
+
| `<note>` | required |
|
|
86
|
+
|
|
87
|
+
**Options**
|
|
88
|
+
|
|
89
|
+
| Option | Description | Default |
|
|
90
|
+
|--------|-------------|---------|
|
|
91
|
+
| `--vault-project-id <n>` | Project ID for the vault in the federation DB | |
|
|
92
|
+
| `--limit <n>` | Maximum suggestions | `5` |
|
|
93
|
+
| `--no-exclude-linked` | Include notes already linked from this one | |
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
### pai zettel converse <question>
|
|
97
|
+
|
|
98
|
+
Ask the vault a question and get a synthesis prompt with relevant notes
|
|
99
|
+
|
|
100
|
+
**Arguments**
|
|
101
|
+
|
|
102
|
+
| Argument | Kind |
|
|
103
|
+
|----------|------|
|
|
104
|
+
| `<question>` | required |
|
|
105
|
+
|
|
106
|
+
**Options**
|
|
107
|
+
|
|
108
|
+
| Option | Description | Default |
|
|
109
|
+
|--------|-------------|---------|
|
|
110
|
+
| `--vault-project-id <n>` | Project ID for the vault in the federation DB | |
|
|
111
|
+
| `--depth <n>` | Graph expansion depth around matched notes | `2` |
|
|
112
|
+
| `--limit <n>` | Maximum relevant notes to include | `15` |
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### pai zettel themes
|
|
116
|
+
|
|
117
|
+
Detect emerging theme clusters in recently edited notes
|
|
118
|
+
|
|
119
|
+
**Options**
|
|
120
|
+
|
|
121
|
+
| Option | Description | Default |
|
|
122
|
+
|--------|-------------|---------|
|
|
123
|
+
| `--vault-project-id <n>` | Project ID for the vault in the federation DB | |
|
|
124
|
+
| `--days <n>` | Look-back window in days | `30` |
|
|
125
|
+
| `--min-size <n>` | Minimum notes per cluster | `3` |
|
|
126
|
+
| `--max-themes <n>` | Maximum themes to return | `10` |
|
|
127
|
+
| `--threshold <f>` | Similarity threshold for clustering (0–1) | `0.65` |
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## Examples
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Explore the neighbourhood of a note
|
|
134
|
+
pai zettel explore "token factory"
|
|
135
|
+
|
|
136
|
+
# Surface an unexpected connection
|
|
137
|
+
pai zettel surprise
|
|
138
|
+
|
|
139
|
+
# Emergent themes across the vault
|
|
140
|
+
pai zettel themes
|
|
141
|
+
|
|
142
|
+
# Vault connectivity health (orphans, dead links)
|
|
143
|
+
pai zettel health
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## See also
|
|
147
|
+
|
|
148
|
+
[`pai backup`](backup.md) · [`pai clear-names`](clear-names.md) · [`pai daemon`](daemon.md) · [`pai db`](db.md) · [`pai end`](end.md) · [`pai help`](help.md) · [`pai kg`](kg.md) · [`pai mcp`](mcp.md) · [`pai memory`](memory.md) · [`pai notify`](notify.md) · [`pai observation`](observation.md) · [`pai obsidian`](obsidian.md) · [`pai pause`](pause.md) · [`pai project`](project.md) · [`pai projects`](projects.md) · [`pai registry`](registry.md) · [`pai restore`](restore.md) · [`pai sessions`](sessions.md) · [`pai setup`](setup.md) · [`pai shell-init`](shell-init.md) · [`pai skill`](skill.md) · [`pai topic`](topic.md) · [`pai update`](update.md)
|
|
149
|
+
|
|
150
|
+
Run `pai help <area>` to read any of these in the terminal.
|
|
151
|
+
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# MCP Skill Delivery Guide
|
|
2
|
+
|
|
3
|
+
How to structure MCP server instructions, prompts, and resources for optimal context efficiency.
|
|
4
|
+
|
|
5
|
+
## The Three-Tier Architecture
|
|
6
|
+
|
|
7
|
+
MCP provides three mechanisms for delivering content to Claude. Each tier has a specific purpose. Mixing them up is the most common source of context bloat and skill drift.
|
|
8
|
+
|
|
9
|
+
### Tier 1: instructions (Always Loaded)
|
|
10
|
+
|
|
11
|
+
The `instructions` field is loaded into EVERY message's context for the lifetime of the MCP connection. Keep it thin.
|
|
12
|
+
|
|
13
|
+
**What belongs here:**
|
|
14
|
+
- Brief description of the MCP server (1-2 sentences)
|
|
15
|
+
- Routing table: "When user says X, fetch prompt Y"
|
|
16
|
+
- Core behavioral rules that apply to every interaction
|
|
17
|
+
- Resource directory: "Fetch pai://name for full guide on X"
|
|
18
|
+
|
|
19
|
+
**What does NOT belong here:**
|
|
20
|
+
- Full skill descriptions and workflow steps
|
|
21
|
+
- Reference documentation (aesthetic guides, API docs)
|
|
22
|
+
- Examples and tutorials
|
|
23
|
+
- Anything that changes rarely and is only needed sometimes
|
|
24
|
+
|
|
25
|
+
**Target size:** Under 2KB. If it exceeds this, you are stuffing the wrong tier.
|
|
26
|
+
|
|
27
|
+
### Tier 2: prompts (On-Demand Workflows)
|
|
28
|
+
|
|
29
|
+
Prompts are fetched by Claude when a specific skill is triggered via `prompts/get`. The user does not see these directly — they are instructions for Claude.
|
|
30
|
+
|
|
31
|
+
**What belongs here:**
|
|
32
|
+
- Complete skill workflow instructions
|
|
33
|
+
- USE WHEN trigger conditions
|
|
34
|
+
- Step-by-step workflow routing tables
|
|
35
|
+
- Platform-specific rules (LinkedIn vs X vs Bluesky)
|
|
36
|
+
- Command tables and data source lists
|
|
37
|
+
|
|
38
|
+
**Registration:**
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
server.prompt(
|
|
42
|
+
"review",
|
|
43
|
+
"Weekly/daily/monthly review of work accomplished",
|
|
44
|
+
() => ({
|
|
45
|
+
messages: [{
|
|
46
|
+
role: "user" as const,
|
|
47
|
+
content: {
|
|
48
|
+
type: "text" as const,
|
|
49
|
+
text: reviewSkillContent,
|
|
50
|
+
},
|
|
51
|
+
}],
|
|
52
|
+
})
|
|
53
|
+
);
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Naming convention:** lowercase-kebab. Examples: `review`, `share`, `vault-context`.
|
|
57
|
+
|
|
58
|
+
### Tier 3: resources (Reference Documentation)
|
|
59
|
+
|
|
60
|
+
Resources are reference documents that Claude reads when it needs detailed information. Unlike prompts, they are not workflow instructions — they are reference material fetched via `resources/read`.
|
|
61
|
+
|
|
62
|
+
**What belongs here:**
|
|
63
|
+
- Style guides (aesthetic, voice, prosody)
|
|
64
|
+
- Constitutional documents (philosophy, architecture)
|
|
65
|
+
- API reference documentation
|
|
66
|
+
- Configuration schemas
|
|
67
|
+
- Technical specifications
|
|
68
|
+
|
|
69
|
+
**Registration:**
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
server.resource(
|
|
73
|
+
"aesthetic",
|
|
74
|
+
"pai://aesthetic",
|
|
75
|
+
{ mimeType: "text/markdown" },
|
|
76
|
+
async () => ({
|
|
77
|
+
contents: [{
|
|
78
|
+
uri: "pai://aesthetic",
|
|
79
|
+
mimeType: "text/markdown",
|
|
80
|
+
text: aestheticGuideContent,
|
|
81
|
+
}],
|
|
82
|
+
})
|
|
83
|
+
);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**URI convention:** Use a consistent scheme like `pai://name` or `mcp://server-name/resource`.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Decision Matrix
|
|
91
|
+
|
|
92
|
+
| Content Type | Tier | Reasoning |
|
|
93
|
+
|--------------|------|-----------|
|
|
94
|
+
| "When user says X, fetch prompt Y" | instructions | Routes to the right skill |
|
|
95
|
+
| Full skill workflow (20+ lines) | prompt | Only needed when skill triggers |
|
|
96
|
+
| Aesthetic style guide | resource | Reference, not workflow |
|
|
97
|
+
| Core operating rules (git, security, format) | instructions | Applies to every interaction |
|
|
98
|
+
| Platform-specific post formatting | prompt | Part of share skill workflow |
|
|
99
|
+
| Voice prosody guide | resource | Reference, rarely needed |
|
|
100
|
+
| Session lifecycle commands | instructions | Always applicable |
|
|
101
|
+
| API endpoint documentation | resource | Reference, read on demand |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Anti-Patterns
|
|
106
|
+
|
|
107
|
+
### Anti-Pattern 1: Stuffing everything into instructions
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// WRONG — 20 full skill descriptions in instructions
|
|
111
|
+
const PAI_INSTRUCTIONS = `
|
|
112
|
+
## Review Skill
|
|
113
|
+
USE WHEN user says 'review'...
|
|
114
|
+
[200 lines of workflow details]
|
|
115
|
+
|
|
116
|
+
## Journal Skill
|
|
117
|
+
USE WHEN user says 'journal'...
|
|
118
|
+
[150 lines of workflow details]
|
|
119
|
+
|
|
120
|
+
[18 more skills...]
|
|
121
|
+
`;
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Problem:** Consumes 8-15KB of context on every message. Most content is irrelevant 95% of the time.
|
|
125
|
+
|
|
126
|
+
**Fix:** One-line routing table in instructions. Full content in prompts.
|
|
127
|
+
|
|
128
|
+
### Anti-Pattern 2: File path references in instructions
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
// WRONG — hardcoded personal paths
|
|
132
|
+
"Read ~/.claude/Skills/Share/SKILL.md for social media instructions"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**Problem:** Paths are personal, not portable. The file may not exist. Reading a file wastes a tool call.
|
|
136
|
+
|
|
137
|
+
**Fix:** Embed content directly in prompts/resources. No file path reads needed.
|
|
138
|
+
|
|
139
|
+
### Anti-Pattern 3: Personal data in instructions
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
// WRONG — personal identifiers in shipped code
|
|
143
|
+
"You are assisting John Smith at Acme Corp. His timezone is PST..."
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Problem:** Instructions ship with the MCP server. If the server is open-source, personal data leaks.
|
|
147
|
+
|
|
148
|
+
**Fix:** Use placeholders (`${USER_NAME}`) or omit personal data from instructions entirely.
|
|
149
|
+
|
|
150
|
+
### Anti-Pattern 4: Duplicating content across tiers
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
// WRONG — routing table AND full skill in instructions
|
|
154
|
+
instructions: `
|
|
155
|
+
When user says 'share', use Share skill.
|
|
156
|
+
|
|
157
|
+
Share skill rules:
|
|
158
|
+
- LinkedIn: 1000-2000 chars, first-person builder voice...
|
|
159
|
+
[100 more lines]
|
|
160
|
+
`
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Fix:** Routing table in instructions, full skill in prompt. Never both.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## How to Add a New Skill
|
|
168
|
+
|
|
169
|
+
1. Write the full skill content (workflow steps, trigger conditions, examples)
|
|
170
|
+
2. Add a one-line entry to the routing table in instructions
|
|
171
|
+
3. Register as a prompt with `server.prompt()`
|
|
172
|
+
4. Test that the routing table correctly identifies trigger phrases
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
// Step 2: Add to routing table in instructions
|
|
176
|
+
`| When user says 'deploy' or 'push to production' | Fetch prompt: deploy |`
|
|
177
|
+
|
|
178
|
+
// Step 3: Register the prompt
|
|
179
|
+
server.prompt(
|
|
180
|
+
"deploy",
|
|
181
|
+
"Deploy to staging or production environments",
|
|
182
|
+
() => ({
|
|
183
|
+
messages: [{
|
|
184
|
+
role: "user" as const,
|
|
185
|
+
content: {
|
|
186
|
+
type: "text" as const,
|
|
187
|
+
text: deploySkillContent, // Full workflow here
|
|
188
|
+
},
|
|
189
|
+
}],
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## How to Add a New Resource
|
|
197
|
+
|
|
198
|
+
1. Write the reference content (guide, spec, configuration schema)
|
|
199
|
+
2. Add an entry to the resource directory in instructions
|
|
200
|
+
3. Register with `server.resource()`
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
// Step 2: Add to resource directory in instructions
|
|
204
|
+
`| API reference | pai://api-reference |`
|
|
205
|
+
|
|
206
|
+
// Step 3: Register the resource
|
|
207
|
+
server.resource(
|
|
208
|
+
"api-reference",
|
|
209
|
+
"pai://api-reference",
|
|
210
|
+
{ mimeType: "text/markdown" },
|
|
211
|
+
async () => ({
|
|
212
|
+
contents: [{
|
|
213
|
+
uri: "pai://api-reference",
|
|
214
|
+
mimeType: "text/markdown",
|
|
215
|
+
text: apiReferenceContent,
|
|
216
|
+
}],
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Testing Checklist
|
|
224
|
+
|
|
225
|
+
Before shipping a refactored MCP server:
|
|
226
|
+
|
|
227
|
+
- [ ] `instructions` field is under 2KB
|
|
228
|
+
- [ ] `instructions` contains ONLY routing table + core rules
|
|
229
|
+
- [ ] Each skill has a registered prompt (`server.prompt`)
|
|
230
|
+
- [ ] Each reference doc has a registered resource (`server.resource`)
|
|
231
|
+
- [ ] No full skill descriptions in `instructions`
|
|
232
|
+
- [ ] No hardcoded personal paths in `instructions`
|
|
233
|
+
- [ ] No personal data (names, emails, timezones) in `instructions`
|
|
234
|
+
- [ ] Prompts are fetchable: `prompts/list` returns all expected prompts
|
|
235
|
+
- [ ] Resources are readable: `resources/list` returns all expected resources
|
|
236
|
+
- [ ] All tools are unchanged (only instructions/prompts/resources changed)
|
|
237
|
+
- [ ] Build succeeds
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Context Size Impact Example
|
|
242
|
+
|
|
243
|
+
PAI MCP before and after applying this guide:
|
|
244
|
+
|
|
245
|
+
| Metric | Before | After |
|
|
246
|
+
|--------|--------|-------|
|
|
247
|
+
| `instructions` size | ~8KB (20 skills) | ~1.5KB (routing table) |
|
|
248
|
+
| Context loaded per message | ~8KB | ~1.5KB |
|
|
249
|
+
| Full skill content when triggered | ~8KB (all skills) | ~0.5KB (one skill) |
|
|
250
|
+
| Context savings (typical session) | — | ~6.5KB per message |
|
|
251
|
+
|
|
252
|
+
At 200 messages per session, that is 1.3MB of context saved — equivalent to several extra tool calls worth of working memory.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Using `@modelcontextprotocol/sdk`
|
|
257
|
+
|
|
258
|
+
The high-level `McpServer` class handles protocol details. Use it unless you need low-level control.
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
262
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
263
|
+
|
|
264
|
+
const server = new McpServer(
|
|
265
|
+
{ name: "my-server", version: "1.0.0" },
|
|
266
|
+
{ instructions: thinRoutingTable }
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
// Register a prompt
|
|
270
|
+
server.prompt("skill-name", "One-line description", () => ({
|
|
271
|
+
messages: [{ role: "user", content: { type: "text", text: fullContent } }],
|
|
272
|
+
}));
|
|
273
|
+
|
|
274
|
+
// Register a resource
|
|
275
|
+
server.resource("doc-name", "scheme://uri", { mimeType: "text/markdown" }, async () => ({
|
|
276
|
+
contents: [{ uri: "scheme://uri", mimeType: "text/markdown", text: docContent }],
|
|
277
|
+
}));
|
|
278
|
+
|
|
279
|
+
// Register a tool (unchanged by refactor)
|
|
280
|
+
server.tool("tool-name", "Tool description", { param: z.string() }, async (args) => ({
|
|
281
|
+
content: [{ type: "text", text: "result" }],
|
|
282
|
+
}));
|
|
283
|
+
|
|
284
|
+
const transport = new StdioServerTransport();
|
|
285
|
+
await server.connect(transport);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Summary
|
|
291
|
+
|
|
292
|
+
The three-tier rule in one sentence: put routing metadata in instructions, put workflow execution steps in prompts, and put reference documentation in resources. Everything else is implementation detail.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tekmidian/pai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "PAI Knowledge OS — Personal AI Infrastructure with federated memory and project management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"tab-color-command.sh",
|
|
24
24
|
"scripts/build-hooks.mjs",
|
|
25
25
|
"scripts/build-skill-stubs.mjs",
|
|
26
|
+
"scripts/build-docs.mjs",
|
|
26
27
|
"src/hooks",
|
|
28
|
+
"docs",
|
|
27
29
|
"README.md",
|
|
28
30
|
"LICENSE",
|
|
29
31
|
"ARCHITECTURE.md",
|
|
@@ -54,7 +56,7 @@
|
|
|
54
56
|
"pai-daemon-mcp": "dist/daemon-mcp/index.mjs"
|
|
55
57
|
},
|
|
56
58
|
"scripts": {
|
|
57
|
-
"build": "tsdown && node scripts/build-hooks.mjs --sync && node scripts/build-skill-stubs.mjs --sync",
|
|
59
|
+
"build": "tsdown && node scripts/build-hooks.mjs --sync && node scripts/build-skill-stubs.mjs --sync && node scripts/build-docs.mjs",
|
|
58
60
|
"dev": "tsdown --watch",
|
|
59
61
|
"test": "vitest",
|
|
60
62
|
"lint": "tsc --noEmit",
|