@vibe-agent-toolkit/vat-development-agents 0.1.22-rc.2 → 0.1.22

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.
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "vibe-agent-toolkit",
3
3
  "description": "Development agents and skills for building with vibe-agent-toolkit",
4
+ "version": "0.1.22",
4
5
  "author": {
5
6
  "name": "vibe-agent-toolkit contributors"
6
7
  }
@@ -0,0 +1,337 @@
1
+ ---
2
+ name: org-admin
3
+ description: Anthropic org administration for Enterprise/Team admins. Requires ANTHROPIC_ADMIN_API_KEY. Use for org user management, API key auditing, cost/usage reporting, workspace administration, and enterprise skill distribution via the Anthropic Admin API. Not for regular users — admin access required.
4
+ ---
5
+
6
+ # Claude Org Administration
7
+
8
+ **For Anthropic org admins only.** Requires `ANTHROPIC_ADMIN_API_KEY` (Enterprise/Team plan).
9
+ If you don't have an admin key, this skill is not for you — use `vibe-agent-toolkit:distribution`
10
+ for local plugin management instead.
11
+
12
+ ## Two Ways to Use It
13
+
14
+ ### CLI — Quick Queries
15
+
16
+ ```bash
17
+ vat claude org info # Org identity
18
+ vat claude org users list # All members
19
+ vat claude org api-keys list --status active # Active API keys
20
+ vat claude org cost --group-by description # Cost breakdown by model
21
+ vat claude org usage --from 2025-01-01T00:00:00Z # Token usage since Jan
22
+ vat claude org skills list # Workspace-scoped skills (requires ANTHROPIC_API_KEY)
23
+ ```
24
+
25
+ ### Library — Scripts and Automation
26
+
27
+ ```typescript
28
+ import { OrgApiClient, createOrgApiClientFromEnv } from '@vibe-agent-toolkit/claude-marketplace';
29
+
30
+ // Reads ANTHROPIC_ADMIN_API_KEY and optionally ANTHROPIC_API_KEY from env
31
+ const client = createOrgApiClientFromEnv();
32
+
33
+ // Or construct directly
34
+ const client = new OrgApiClient({
35
+ adminApiKey: 'sk-ant-admin-...',
36
+ apiKey: 'sk-ant-api03-...', // only needed for skills endpoints
37
+ });
38
+ ```
39
+
40
+ ## API Reference
41
+
42
+ ### Auth: Two Keys, Two Surfaces
43
+
44
+ | Key | Env Var | Endpoints | Who Has It |
45
+ |---|---|---|---|
46
+ | Admin API key | `ANTHROPIC_ADMIN_API_KEY` | `/v1/organizations/*` | Org admins only |
47
+ | Regular API key | `ANTHROPIC_API_KEY` | `/v1/skills` (beta) | Any workspace member |
48
+
49
+ ### Endpoints and Methods
50
+
51
+ **Org identity:**
52
+ ```typescript
53
+ const org = await client.get<{ id: string; type: string; name: string }>('/v1/organizations/me');
54
+ ```
55
+
56
+ **Users:**
57
+ ```typescript
58
+ // List (paginated with limit/after_id)
59
+ const users = await client.get<{ data: OrgUser[]; has_more: boolean }>(
60
+ '/v1/organizations/users', { limit: 100 }
61
+ );
62
+
63
+ // Get single user
64
+ const user = await client.get<OrgUser>('/v1/organizations/users/user_abc123');
65
+ ```
66
+
67
+ **Invites:**
68
+ ```typescript
69
+ const invites = await client.get<{ data: OrgInvite[]; has_more: boolean }>(
70
+ '/v1/organizations/invites'
71
+ );
72
+ ```
73
+
74
+ **Workspaces:**
75
+ ```typescript
76
+ const workspaces = await client.get<{ data: OrgWorkspace[]; has_more: boolean }>(
77
+ '/v1/organizations/workspaces'
78
+ );
79
+
80
+ // Workspace members
81
+ const members = await client.get<{ data: WorkspaceMember[]; has_more: boolean }>(
82
+ '/v1/organizations/workspaces/ws_abc/members'
83
+ );
84
+ ```
85
+
86
+ **API keys:**
87
+ ```typescript
88
+ const keys = await client.get<{ data: ApiKey[]; has_more: boolean }>(
89
+ '/v1/organizations/api_keys',
90
+ { status: 'active', workspace_id: 'ws_abc' } // both filters optional
91
+ );
92
+ ```
93
+
94
+ **Skills (beta — uses regular API key):**
95
+ ```typescript
96
+ // List skills
97
+ const skills = await client.getSkills<{ data: Skill[]; has_more: boolean }>('/v1/skills');
98
+ // Adds anthropic-beta: skills-2025-10-02 header automatically
99
+
100
+ // Upload a skill (multipart/form-data)
101
+ import { buildMultipartFormData } from '@vibe-agent-toolkit/claude-marketplace';
102
+ const multipart = buildMultipartFormData(
103
+ { display_title: 'My Skill' },
104
+ [{ fieldName: 'files[]', filename: 'SKILL.md', content: Buffer.from(skillContent) }],
105
+ );
106
+ const created = await client.uploadSkill<{ id: string; latest_version: string }>(multipart);
107
+
108
+ // Delete a skill
109
+ const deleted = await client.deleteSkill<{ id: string; type: string }>(skillId);
110
+ ```
111
+
112
+ ### Report Endpoints — Pagination Quirk
113
+
114
+ Usage, cost, and code-analytics endpoints have a **non-standard pagination model**.
115
+ They return `has_more: true` with a `next_page` cursor, but the API **rejects `next_page`
116
+ as a query parameter**. Paginate by advancing `starting_at` to the last bucket's `ending_at`.
117
+
118
+ **Usage report (daily token buckets):**
119
+ ```typescript
120
+ interface UsageBucket {
121
+ starting_at: string;
122
+ ending_at: string;
123
+ results: Array<{
124
+ uncached_input_tokens: number;
125
+ cache_read_input_tokens: number;
126
+ output_tokens: number;
127
+ model: string | null;
128
+ workspace_id: string | null;
129
+ api_key_id: string | null;
130
+ service_tier: string | null;
131
+ // ... other dimension fields, null if not applicable
132
+ }>;
133
+ }
134
+
135
+ // First page
136
+ let resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(
137
+ '/v1/organizations/usage_report/messages',
138
+ { starting_at: '2025-01-01T00:00:00Z', ending_at: '2025-12-31T23:59:59Z' }
139
+ );
140
+
141
+ // Subsequent pages — advance starting_at, do NOT pass next_page
142
+ const lastBucket = resp.data.at(-1);
143
+ resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(
144
+ '/v1/organizations/usage_report/messages',
145
+ { starting_at: lastBucket.ending_at, ending_at: '2025-12-31T23:59:59Z' }
146
+ );
147
+ ```
148
+
149
+ **Cost report:**
150
+ ```typescript
151
+ // amount is a STRING, not a number — parse before arithmetic
152
+ interface CostResult {
153
+ currency: string;
154
+ amount: string; // "7.0812" — use parseFloat()
155
+ description: string | null;
156
+ model: string | null;
157
+ token_type: string | null;
158
+ // ...
159
+ }
160
+
161
+ // group_by[] needs URLSearchParams for repeated params
162
+ const qs = new URLSearchParams();
163
+ qs.set('starting_at', '2025-03-01T00:00:00Z');
164
+ qs.set('ending_at', '2025-03-31T23:59:59Z');
165
+ qs.append('group_by[]', 'description');
166
+ qs.append('group_by[]', 'workspace_id');
167
+ const resp = await client.get<{ data: CostBucket[] }>(
168
+ `/v1/organizations/cost_report?${qs.toString()}`
169
+ );
170
+
171
+ // Sum costs
172
+ const total = resp.data
173
+ .flatMap(b => b.results)
174
+ .reduce((sum, r) => sum + parseFloat(r.amount), 0);
175
+ ```
176
+
177
+ **Code analytics (Claude Code productivity):**
178
+ ```typescript
179
+ // Date-only format YYYY-MM-DD. No ending_at parameter.
180
+ const resp = await client.get<{ data: unknown[] }>(
181
+ '/v1/organizations/usage_report/claude_code',
182
+ { starting_at: '2025-03-01' } // NOT ISO datetime
183
+ );
184
+ // Returns empty data[] when no Claude Code enterprise seats are active
185
+ ```
186
+
187
+ ## Common Recipes
188
+
189
+ ### Monthly cost summary script
190
+
191
+ ```typescript
192
+ import { createOrgApiClientFromEnv } from '@vibe-agent-toolkit/claude-marketplace';
193
+
194
+ const client = createOrgApiClientFromEnv();
195
+ const qs = new URLSearchParams();
196
+ qs.set('starting_at', '2025-03-01T00:00:00Z');
197
+ qs.set('ending_at', '2025-04-01T00:00:00Z');
198
+ qs.append('group_by[]', 'description');
199
+
200
+ const allResults = [];
201
+ let startingAt = '2025-03-01T00:00:00Z';
202
+ let hasMore = true;
203
+
204
+ while (hasMore) {
205
+ qs.set('starting_at', startingAt);
206
+ const resp = await client.get(`/v1/organizations/cost_report?${qs.toString()}`);
207
+ allResults.push(...resp.data);
208
+ const last = resp.data.at(-1);
209
+ hasMore = resp.has_more && last;
210
+ if (last) startingAt = last.ending_at;
211
+ }
212
+
213
+ const byDescription = new Map();
214
+ for (const bucket of allResults) {
215
+ for (const r of bucket.results) {
216
+ const key = r.description ?? 'unclassified';
217
+ byDescription.set(key, (byDescription.get(key) ?? 0) + parseFloat(r.amount));
218
+ }
219
+ }
220
+ for (const [desc, total] of byDescription) {
221
+ console.log(`${desc}: $${total.toFixed(2)}`);
222
+ }
223
+ ```
224
+
225
+ ### API key security audit
226
+
227
+ ```typescript
228
+ const client = createOrgApiClientFromEnv();
229
+ const { data: keys } = await client.get('/v1/organizations/api_keys', { limit: 100 });
230
+
231
+ const issues = [];
232
+ for (const key of keys) {
233
+ if (key.status === 'active' && !key.expires_at) {
234
+ issues.push(`${key.name}: active with no expiry`);
235
+ }
236
+ if (key.status === 'active' && !key.workspace_id) {
237
+ issues.push(`${key.name}: not scoped to a workspace`);
238
+ }
239
+ }
240
+ console.log(issues.length ? issues.join('\n') : 'All keys look good');
241
+ ```
242
+
243
+ ### List org users who haven't accepted invites
244
+
245
+ ```typescript
246
+ const client = createOrgApiClientFromEnv();
247
+ const { data: invites } = await client.get('/v1/organizations/invites');
248
+ const pending = invites.filter(i => i.status !== 'accepted');
249
+ console.log(`${pending.length} pending invites:`, pending.map(i => i.email));
250
+ ```
251
+
252
+ ## CLI Reference
253
+
254
+ All commands require `ANTHROPIC_ADMIN_API_KEY` unless noted.
255
+
256
+ ```
257
+ vat claude org info Org identity (id, name)
258
+ vat claude org users list [--limit N] List members
259
+ vat claude org users get <user-id> Get single member
260
+ vat claude org invites list List invitations
261
+ vat claude org workspaces list List API workspaces
262
+ vat claude org workspaces get <id> Get single workspace
263
+ vat claude org workspaces members list <id> Workspace members
264
+ vat claude org api-keys list [--status S] API key inventory
265
+ vat claude org usage [--from DT] [--to DT] Token usage report
266
+ vat claude org cost [--from DT] [--group-by F] USD cost report
267
+ vat claude org code-analytics [--from DATE] Claude Code metrics (YYYY-MM-DD)
268
+ vat claude org skills list Workspace skills (needs ANTHROPIC_API_KEY)
269
+ vat claude org skills install <source> Upload skill dir or ZIP to org
270
+ vat claude org skills delete <skill-id> Delete a skill (versions first)
271
+ vat claude org skills versions list <skill-id> List skill versions
272
+ vat claude org skills versions delete <id> <ver> Delete a skill version
273
+ ```
274
+
275
+ Exit codes: `0` success, `1` expected failure (stubs), `2` system error (missing key, API error).
276
+
277
+ **Skill deletion lifecycle:** The API requires all versions to be deleted before the skill itself.
278
+ Use `versions list` to find versions, `versions delete` each one, then `delete` the skill.
279
+
280
+ ## Enterprise Skill Distribution
281
+
282
+ ### Skills API (claude.ai / Console)
283
+
284
+ Skills uploaded via `POST /v1/skills` are **workspace-scoped** and **automatically available to
285
+ all workspace members**. There is no per-user enable/disable via the API — visibility is
286
+ workspace-level only. The admin UI may have additional controls not exposed in the API.
287
+
288
+ **Upload from npm package:**
289
+ ```bash
290
+ # Upload all skills from a package
291
+ vat claude org skills install --from-npm @scope/my-skills-package@1.0.0
292
+
293
+ # Upload a single skill
294
+ vat claude org skills install --from-npm @scope/my-skills-package@1.0.0 --skill my-skill
295
+ ```
296
+
297
+ The package must contain `dist/skills/<name>/SKILL.md` (produced by `vat skills build`).
298
+ If skills are in a sub-dependency, the command searches `node_modules/*/dist/skills/` too.
299
+
300
+ **Duplicate titles are rejected** — the API enforces unique `display_title` per workspace.
301
+ When uploading multiple skills, failures are non-fatal; partial results are reported.
302
+
303
+ ### Managed Settings (Claude Code plugins)
304
+
305
+ For enterprise-wide Claude Code plugin deployment (not the Skills API), use managed settings
306
+ pushed via MDM (Jamf, Intune, SCCM, etc.):
307
+
308
+ | Platform | Path |
309
+ |---|---|
310
+ | macOS | `/Library/Application Support/ClaudeCode/managed-settings.json` |
311
+ | Linux | `/etc/claude-code/managed-settings.json` |
312
+ | Windows | `C:\Program Files\ClaudeCode\managed-settings.json` |
313
+
314
+ Managed settings are **highest priority** in the settings cascade — they override user settings.
315
+ Use this to force-enable plugins, lock down permissions, or configure organization defaults.
316
+
317
+ ```json
318
+ {
319
+ "enabledPlugins": {
320
+ "my-plugin@my-marketplace": true
321
+ }
322
+ }
323
+ ```
324
+
325
+ Combine with `npm install -g <package>` (via IT software deployment) to install the plugin
326
+ binary, then managed settings to enable it across all machines.
327
+
328
+ ## Not Yet Implemented
329
+
330
+ These commands exist with the correct CLI shape but return structured
331
+ `not-yet-implemented` stubs (exit 1). Coming in a future release:
332
+
333
+ - `org users update/remove` — role changes, offboarding
334
+ - `org invites create/delete` — programmatic invitations
335
+ - `org workspaces create/archive` — workspace lifecycle
336
+ - `org workspaces members add/update/remove` — workspace membership
337
+ - `org api-keys update` — rename keys
@@ -40,6 +40,7 @@ non-TypeScript/JavaScript projects, or cases where you need deep framework-speci
40
40
  | `--target claude-web` ZIP format | `vibe-agent-toolkit:distribution` |
41
41
  | Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | `vibe-agent-toolkit:install` |
42
42
  | `vat audit`, `--compat`, CI validation | `vibe-agent-toolkit:audit` |
43
+ | `vat claude org`, Admin API, org users/cost/usage/skills, ANTHROPIC_ADMIN_API_KEY | `vibe-agent-toolkit:org-admin` |
43
44
  | VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | `vibe-agent-toolkit:debugging` |
44
45
 
45
46
  ## Agent Archetypes (Quick Reference)
@@ -7,7 +7,7 @@ export const meta = {
7
7
  description: "Use when building, adopting, or learning vibe-agent-toolkit (VAT). Covers agent creation, CLI commands (vat skills, vat resources, vat audit, vat rag), runtime adapters, skill packaging, and resource validation. Routes to specialized sub-skills."
8
8
  };
9
9
 
10
- export const text = "\n# Vibe Agent Toolkit Skill\n\n**Vibe Agent Toolkit (VAT)** is a modular toolkit for building portable AI agents that work across\nmultiple LLM frameworks and deployment targets. Write your agent logic once as plain TypeScript,\nthen deploy it to Vercel AI SDK, LangChain, OpenAI, Claude Agent SDK, or any other runtime using\nframework adapters. No vendor lock-in.\n\n## Purpose: For Users, Not Contributors\n\n- **This skill** = How to USE VAT to build agents\n- **\`vibe-agent-toolkit:debugging\`** = When VAT itself behaves unexpectedly or you need to test a fix\n- **Root CLAUDE.md** = How to DEVELOP the VAT codebase itself\n\n## When to Use VAT\n\n**VAT is great for:** Multi-framework projects, reusable agent libraries, testing across LLM\nproviders, complex multi-agent orchestration, human-in-the-loop workflows.\n\n**VAT may not be needed for:** Simple one-off scripts where the framework is already decided,\nnon-TypeScript/JavaScript projects, or cases where you need deep framework-specific features.\n\n## Skill Routing Table\n\n| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |\n\n## Agent Archetypes (Quick Reference)\n\nFour patterns cover most use cases. For full code examples, see \`vibe-agent-toolkit:authoring\`.\n\n| Archetype | When to Use |\n|---|---|\n| **Pure Function Tool** | Stateless validation, transformation, computation — no LLM needed |\n| **One-Shot LLM Analyzer** | Single LLM call for analysis, classification, or generation |\n| **Conversational Assistant** | Multi-turn dialogue with session state across turns |\n| **External Event Integrator** | Waiting for human approval, webhooks, or third-party APIs |\n\n## Core CLI Commands\n\n\`\`\`bash\n# Install VAT CLI globally\nnpm install -g vibe-agent-toolkit\n\n# Top-level orchestration\nvat build # build all artifacts (skills then claude plugins)\nvat verify # verify all artifacts (resources, skills, claude)\n\n# Claude plugin commands\nvat claude build # generate plugin artifacts from built skills\nvat claude verify # validate plugin artifacts\n\n# Skills\nvat skills list # list skills in current project\nvat skills list --user # list user-installed skills\nvat skills install npm:@org/my-skills # install from npm (routes through plugin system)\nvat skills build # build portable skills only\nvat skills validate # validate skill quality\n\n# Resources\nvat resources validate # validate collections (reads config)\nvat resources validate docs/ --frontmatter-schema schema.json\n\n# Audit\nvat audit # audit current directory recursively\nvat audit --user # audit entire Claude installation\nvat audit ./plugins/ --compat # check surface compatibility\n\n# RAG\nvat rag index docs/ # index markdown into vector DB\nvat rag query \"my question\" --limit 5 # semantic search\n\n# Get help for any command\nvat --help\nvat skills --help\n\`\`\`\n\n## agent-generator: Creating New Agents\n\nThe **agent-generator** is a built-in meta-agent that guides you through designing\nhigh-quality agents via a 4-phase workflow:\n\n1. **GATHER** — Understand your intent and goals\n2. **ANALYZE** — Identify agent pattern and requirements\n3. **DESIGN** — Make architecture decisions (LLM, tools, prompts)\n4. **GENERATE** — Create validated agent package\n\nMinimum input needed:\n\`\`\`json\n{\n \"agentPurpose\": \"Review PRs for security issues\",\n \"successCriteria\": \"Catches 100% of critical vulnerabilities\"\n}\n\`\`\`\n\nThe generator produces: \`agent.yaml\`, \`prompts/system.md\`, \`prompts/user.md\`,\n\`schemas/input.schema.json\`, \`schemas/output.schema.json\`, and \`README.md\`.\n\n**Tips for better results:**\n- Be specific about success criteria (\"Under 30s, zero false negatives\") not vague (\"fast enough\")\n- Name the tools the agent needs upfront (file readers, APIs, etc.)\n- Describe domain context (OWASP Top 10, company coding standards, etc.)\n\n## Packaging Markdown for Reuse\n\nVAT\'s resource compiler transforms markdown files into type-safe TypeScript modules,\nenabling prompt libraries, RAG knowledge bases, and shared content across projects.\n\n\`\`\`bash\nnpm install -D @vibe-agent-toolkit/resource-compiler\nnpx vat-compile-resources compile resources/ generated/resources/\n\`\`\`\n\n\`\`\`typescript\nimport * as Doc from \'./generated/resources/doc.js\';\n\nDoc.meta.title; // type-safe frontmatter\nDoc.fragments.introduction.text; // H2 section content\nDoc.text; // full markdown\n\`\`\`\n\nUse cases: agent prompt libraries, RAG knowledge bases packaged as npm modules,\nmulti-project content sharing with versioning.\n\n## Common Workflows\n\n**Create a new agent:**\n\`\`\`bash\n# Use agent-generator interactively, then:\nvat agent import my-skill/SKILL.md # import to VAT format\nvat skills validate # check quality\nvat skills build # package for distribution\n\`\`\`\n\n**Install and use a community skill:**\n\`\`\`bash\nvat skills install npm:@vibe-agent-toolkit/vat-cat-agents\nvat skills list --user\n# Plugin-aware packages register in Claude\'s plugin system\n# Skills are invoked as /plugin-name:skill-name in Claude Code\n\`\`\`\n\n**Build and publish your own skill package:**\n\`\`\`bash\n# Configure vat.skills in package.json + claude: in vibe-agent-toolkit.config.yaml, then:\nvat build # builds skills + claude plugin artifacts\nvat verify # validates everything\nnpm publish # publishes to npm (postinstall registers the plugin)\n# Users install with: vat skills install npm:@myorg/my-skills\n\`\`\`\n\n## Success Criteria\n\nYou\'ve successfully adopted VAT when:\n- Agents have clear input/output schemas (Zod-validated)\n- Errors are handled as data (result envelopes), never thrown\n- Tests cover success and error paths without real API calls (mock mode)\n- Agents work across multiple runtimes via adapters\n- Multi-agent pipelines compose via \`andThen()\` / \`match()\` helpers\n\n## Documentation Index\n\n- [Getting Started Guide](../../../../docs/getting-started.md)\n- [Agent Authoring Guide](../../../../docs/agent-authoring.md) — patterns and code examples\n- [Orchestration Guide](../../../../docs/orchestration.md) — multi-agent workflows\n- [RAG Usage Guide](../../../../docs/guides/rag-usage-guide.md)\n- [Resource Compiler Guide](../../../../docs/guides/resource-compiler/compiling-markdown-to-typescript.md)\n- [Runtime Adapters](../../../../docs/adding-runtime-adapters.md)\n- Examples: \`@vibe-agent-toolkit/vat-example-cat-agents\`\n\n## Getting Help\n\n- **CLI Help:** \`vat --help\`, \`vat skills --help\`, etc.\n- **Examples:** \`packages/vat-example-cat-agents/\`\n- **GitHub Issues:** Report bugs or ask questions\n\nHappy agent building!\n";
10
+ export const text = "\n# Vibe Agent Toolkit Skill\n\n**Vibe Agent Toolkit (VAT)** is a modular toolkit for building portable AI agents that work across\nmultiple LLM frameworks and deployment targets. Write your agent logic once as plain TypeScript,\nthen deploy it to Vercel AI SDK, LangChain, OpenAI, Claude Agent SDK, or any other runtime using\nframework adapters. No vendor lock-in.\n\n## Purpose: For Users, Not Contributors\n\n- **This skill** = How to USE VAT to build agents\n- **\`vibe-agent-toolkit:debugging\`** = When VAT itself behaves unexpectedly or you need to test a fix\n- **Root CLAUDE.md** = How to DEVELOP the VAT codebase itself\n\n## When to Use VAT\n\n**VAT is great for:** Multi-framework projects, reusable agent libraries, testing across LLM\nproviders, complex multi-agent orchestration, human-in-the-loop workflows.\n\n**VAT may not be needed for:** Simple one-off scripts where the framework is already decided,\nnon-TypeScript/JavaScript projects, or cases where you need deep framework-specific features.\n\n## Skill Routing Table\n\n| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| \`vat claude org\`, Admin API, org users/cost/usage/skills, ANTHROPIC_ADMIN_API_KEY | \`vibe-agent-toolkit:org-admin\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |\n\n## Agent Archetypes (Quick Reference)\n\nFour patterns cover most use cases. For full code examples, see \`vibe-agent-toolkit:authoring\`.\n\n| Archetype | When to Use |\n|---|---|\n| **Pure Function Tool** | Stateless validation, transformation, computation — no LLM needed |\n| **One-Shot LLM Analyzer** | Single LLM call for analysis, classification, or generation |\n| **Conversational Assistant** | Multi-turn dialogue with session state across turns |\n| **External Event Integrator** | Waiting for human approval, webhooks, or third-party APIs |\n\n## Core CLI Commands\n\n\`\`\`bash\n# Install VAT CLI globally\nnpm install -g vibe-agent-toolkit\n\n# Top-level orchestration\nvat build # build all artifacts (skills then claude plugins)\nvat verify # verify all artifacts (resources, skills, claude)\n\n# Claude plugin commands\nvat claude build # generate plugin artifacts from built skills\nvat claude verify # validate plugin artifacts\n\n# Skills\nvat skills list # list skills in current project\nvat skills list --user # list user-installed skills\nvat skills install npm:@org/my-skills # install from npm (routes through plugin system)\nvat skills build # build portable skills only\nvat skills validate # validate skill quality\n\n# Resources\nvat resources validate # validate collections (reads config)\nvat resources validate docs/ --frontmatter-schema schema.json\n\n# Audit\nvat audit # audit current directory recursively\nvat audit --user # audit entire Claude installation\nvat audit ./plugins/ --compat # check surface compatibility\n\n# RAG\nvat rag index docs/ # index markdown into vector DB\nvat rag query \"my question\" --limit 5 # semantic search\n\n# Get help for any command\nvat --help\nvat skills --help\n\`\`\`\n\n## agent-generator: Creating New Agents\n\nThe **agent-generator** is a built-in meta-agent that guides you through designing\nhigh-quality agents via a 4-phase workflow:\n\n1. **GATHER** — Understand your intent and goals\n2. **ANALYZE** — Identify agent pattern and requirements\n3. **DESIGN** — Make architecture decisions (LLM, tools, prompts)\n4. **GENERATE** — Create validated agent package\n\nMinimum input needed:\n\`\`\`json\n{\n \"agentPurpose\": \"Review PRs for security issues\",\n \"successCriteria\": \"Catches 100% of critical vulnerabilities\"\n}\n\`\`\`\n\nThe generator produces: \`agent.yaml\`, \`prompts/system.md\`, \`prompts/user.md\`,\n\`schemas/input.schema.json\`, \`schemas/output.schema.json\`, and \`README.md\`.\n\n**Tips for better results:**\n- Be specific about success criteria (\"Under 30s, zero false negatives\") not vague (\"fast enough\")\n- Name the tools the agent needs upfront (file readers, APIs, etc.)\n- Describe domain context (OWASP Top 10, company coding standards, etc.)\n\n## Packaging Markdown for Reuse\n\nVAT\'s resource compiler transforms markdown files into type-safe TypeScript modules,\nenabling prompt libraries, RAG knowledge bases, and shared content across projects.\n\n\`\`\`bash\nnpm install -D @vibe-agent-toolkit/resource-compiler\nnpx vat-compile-resources compile resources/ generated/resources/\n\`\`\`\n\n\`\`\`typescript\nimport * as Doc from \'./generated/resources/doc.js\';\n\nDoc.meta.title; // type-safe frontmatter\nDoc.fragments.introduction.text; // H2 section content\nDoc.text; // full markdown\n\`\`\`\n\nUse cases: agent prompt libraries, RAG knowledge bases packaged as npm modules,\nmulti-project content sharing with versioning.\n\n## Common Workflows\n\n**Create a new agent:**\n\`\`\`bash\n# Use agent-generator interactively, then:\nvat agent import my-skill/SKILL.md # import to VAT format\nvat skills validate # check quality\nvat skills build # package for distribution\n\`\`\`\n\n**Install and use a community skill:**\n\`\`\`bash\nvat skills install npm:@vibe-agent-toolkit/vat-cat-agents\nvat skills list --user\n# Plugin-aware packages register in Claude\'s plugin system\n# Skills are invoked as /plugin-name:skill-name in Claude Code\n\`\`\`\n\n**Build and publish your own skill package:**\n\`\`\`bash\n# Configure vat.skills in package.json + claude: in vibe-agent-toolkit.config.yaml, then:\nvat build # builds skills + claude plugin artifacts\nvat verify # validates everything\nnpm publish # publishes to npm (postinstall registers the plugin)\n# Users install with: vat skills install npm:@myorg/my-skills\n\`\`\`\n\n## Success Criteria\n\nYou\'ve successfully adopted VAT when:\n- Agents have clear input/output schemas (Zod-validated)\n- Errors are handled as data (result envelopes), never thrown\n- Tests cover success and error paths without real API calls (mock mode)\n- Agents work across multiple runtimes via adapters\n- Multi-agent pipelines compose via \`andThen()\` / \`match()\` helpers\n\n## Documentation Index\n\n- [Getting Started Guide](../../../../docs/getting-started.md)\n- [Agent Authoring Guide](../../../../docs/agent-authoring.md) — patterns and code examples\n- [Orchestration Guide](../../../../docs/orchestration.md) — multi-agent workflows\n- [RAG Usage Guide](../../../../docs/guides/rag-usage-guide.md)\n- [Resource Compiler Guide](../../../../docs/guides/resource-compiler/compiling-markdown-to-typescript.md)\n- [Runtime Adapters](../../../../docs/adding-runtime-adapters.md)\n- Examples: \`@vibe-agent-toolkit/vat-example-cat-agents\`\n\n## Getting Help\n\n- **CLI Help:** \`vat --help\`, \`vat skills --help\`, etc.\n- **Examples:** \`packages/vat-example-cat-agents/\`\n- **GitHub Issues:** Report bugs or ask questions\n\nHappy agent building!\n";
11
11
 
12
12
  export const fragments = {
13
13
  purposeForUsersNotContributors: {
@@ -22,8 +22,8 @@ export const fragments = {
22
22
  },
23
23
  skillRoutingTable: {
24
24
  header: "## Skill Routing Table",
25
- body: "| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |",
26
- text: "## Skill Routing Table\n\n| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |"
25
+ body: "| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| \`vat claude org\`, Admin API, org users/cost/usage/skills, ANTHROPIC_ADMIN_API_KEY | \`vibe-agent-toolkit:org-admin\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |",
26
+ text: "## Skill Routing Table\n\n| If you\'re working on... | Use this skill |\n|---|---|\n| Writing or structuring a \`SKILL.md\` file | \`vibe-agent-toolkit:authoring\` |\n| Agent archetypes, orchestration patterns, result envelopes | \`vibe-agent-toolkit:authoring\` |\n| \`packagingOptions\` (linkFollowDepth, excludeReferencesFromBundle) | \`vibe-agent-toolkit:authoring\` |\n| Resource collections, frontmatter schema validation | \`vibe-agent-toolkit:resources\` |\n| \`vat resources validate\`, collection config | \`vibe-agent-toolkit:resources\` |\n| Setting up \`vat build\` + \`vat claude build\` for a project | \`vibe-agent-toolkit:distribution\` |\n| Configuring \`claude:\` section in vibe-agent-toolkit.config.yaml | \`vibe-agent-toolkit:distribution\` |\n| npm publishing with plugin postinstall | \`vibe-agent-toolkit:distribution\` |\n| \`vat build\` / \`vat verify\` orchestration | \`vibe-agent-toolkit:distribution\` |\n| \`--target claude-web\` ZIP format | \`vibe-agent-toolkit:distribution\` |\n| Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | \`vibe-agent-toolkit:install\` |\n| \`vat audit\`, \`--compat\`, CI validation | \`vibe-agent-toolkit:audit\` |\n| \`vat claude org\`, Admin API, org users/cost/usage/skills, ANTHROPIC_ADMIN_API_KEY | \`vibe-agent-toolkit:org-admin\` |\n| VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | \`vibe-agent-toolkit:debugging\` |"
27
27
  },
28
28
  agentArchetypesQuickReference: {
29
29
  header: "## Agent Archetypes (Quick Reference)",
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Generated TypeScript declarations - DO NOT EDIT
3
+ */
4
+
5
+ export interface Fragment {
6
+ readonly header: string;
7
+ readonly body: string;
8
+ readonly text: string;
9
+ }
10
+
11
+ export const meta: {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ };
15
+
16
+ export const text: string;
17
+
18
+ export const fragments: {
19
+ readonly twoWaysToUseIt: Fragment;
20
+ readonly apiReference: Fragment;
21
+ readonly commonRecipes: Fragment;
22
+ readonly cliReference: Fragment;
23
+ readonly enterpriseSkillDistribution: Fragment;
24
+ readonly notYetImplemented: Fragment;
25
+ };
26
+
27
+ export type FragmentName = keyof typeof fragments;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Generated from markdown file - DO NOT EDIT
3
+ */
4
+
5
+ export const meta = {
6
+ name: "org-admin",
7
+ description: "Anthropic org administration for Enterprise/Team admins. Requires ANTHROPIC_ADMIN_API_KEY. Use for org user management, API key auditing, cost/usage reporting, workspace administration, and enterprise skill distribution via the Anthropic Admin API. Not for regular users — admin access required."
8
+ };
9
+
10
+ export const text = "\n# Claude Org Administration\n\n**For Anthropic org admins only.** Requires \`ANTHROPIC_ADMIN_API_KEY\` (Enterprise/Team plan).\nIf you don\'t have an admin key, this skill is not for you — use \`vibe-agent-toolkit:distribution\`\nfor local plugin management instead.\n\n## Two Ways to Use It\n\n### CLI — Quick Queries\n\n\`\`\`bash\nvat claude org info # Org identity\nvat claude org users list # All members\nvat claude org api-keys list --status active # Active API keys\nvat claude org cost --group-by description # Cost breakdown by model\nvat claude org usage --from 2025-01-01T00:00:00Z # Token usage since Jan\nvat claude org skills list # Workspace-scoped skills (requires ANTHROPIC_API_KEY)\n\`\`\`\n\n### Library — Scripts and Automation\n\n\`\`\`typescript\nimport { OrgApiClient, createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\n// Reads ANTHROPIC_ADMIN_API_KEY and optionally ANTHROPIC_API_KEY from env\nconst client = createOrgApiClientFromEnv();\n\n// Or construct directly\nconst client = new OrgApiClient({\n adminApiKey: \'sk-ant-admin-...\',\n apiKey: \'sk-ant-api03-...\', // only needed for skills endpoints\n});\n\`\`\`\n\n## API Reference\n\n### Auth: Two Keys, Two Surfaces\n\n| Key | Env Var | Endpoints | Who Has It |\n|---|---|---|---|\n| Admin API key | \`ANTHROPIC_ADMIN_API_KEY\` | \`/v1/organizations/*\` | Org admins only |\n| Regular API key | \`ANTHROPIC_API_KEY\` | \`/v1/skills\` (beta) | Any workspace member |\n\n### Endpoints and Methods\n\n**Org identity:**\n\`\`\`typescript\nconst org = await client.get<{ id: string; type: string; name: string }>(\'/v1/organizations/me\');\n\`\`\`\n\n**Users:**\n\`\`\`typescript\n// List (paginated with limit/after_id)\nconst users = await client.get<{ data: OrgUser[]; has_more: boolean }>(\n \'/v1/organizations/users\', { limit: 100 }\n);\n\n// Get single user\nconst user = await client.get<OrgUser>(\'/v1/organizations/users/user_abc123\');\n\`\`\`\n\n**Invites:**\n\`\`\`typescript\nconst invites = await client.get<{ data: OrgInvite[]; has_more: boolean }>(\n \'/v1/organizations/invites\'\n);\n\`\`\`\n\n**Workspaces:**\n\`\`\`typescript\nconst workspaces = await client.get<{ data: OrgWorkspace[]; has_more: boolean }>(\n \'/v1/organizations/workspaces\'\n);\n\n// Workspace members\nconst members = await client.get<{ data: WorkspaceMember[]; has_more: boolean }>(\n \'/v1/organizations/workspaces/ws_abc/members\'\n);\n\`\`\`\n\n**API keys:**\n\`\`\`typescript\nconst keys = await client.get<{ data: ApiKey[]; has_more: boolean }>(\n \'/v1/organizations/api_keys\',\n { status: \'active\', workspace_id: \'ws_abc\' } // both filters optional\n);\n\`\`\`\n\n**Skills (beta — uses regular API key):**\n\`\`\`typescript\n// List skills\nconst skills = await client.getSkills<{ data: Skill[]; has_more: boolean }>(\'/v1/skills\');\n// Adds anthropic-beta: skills-2025-10-02 header automatically\n\n// Upload a skill (multipart/form-data)\nimport { buildMultipartFormData } from \'@vibe-agent-toolkit/claude-marketplace\';\nconst multipart = buildMultipartFormData(\n { display_title: \'My Skill\' },\n [{ fieldName: \'files[]\', filename: \'SKILL.md\', content: Buffer.from(skillContent) }],\n);\nconst created = await client.uploadSkill<{ id: string; latest_version: string }>(multipart);\n\n// Delete a skill\nconst deleted = await client.deleteSkill<{ id: string; type: string }>(skillId);\n\`\`\`\n\n### Report Endpoints — Pagination Quirk\n\nUsage, cost, and code-analytics endpoints have a **non-standard pagination model**.\nThey return \`has_more: true\` with a \`next_page\` cursor, but the API **rejects \`next_page\`\nas a query parameter**. Paginate by advancing \`starting_at\` to the last bucket\'s \`ending_at\`.\n\n**Usage report (daily token buckets):**\n\`\`\`typescript\ninterface UsageBucket {\n starting_at: string;\n ending_at: string;\n results: Array<{\n uncached_input_tokens: number;\n cache_read_input_tokens: number;\n output_tokens: number;\n model: string | null;\n workspace_id: string | null;\n api_key_id: string | null;\n service_tier: string | null;\n // ... other dimension fields, null if not applicable\n }>;\n}\n\n// First page\nlet resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: \'2025-01-01T00:00:00Z\', ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\n// Subsequent pages — advance starting_at, do NOT pass next_page\nconst lastBucket = resp.data.at(-1);\nresp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: lastBucket.ending_at, ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\`\`\`\n\n**Cost report:**\n\`\`\`typescript\n// amount is a STRING, not a number — parse before arithmetic\ninterface CostResult {\n currency: string;\n amount: string; // \"7.0812\" — use parseFloat()\n description: string | null;\n model: string | null;\n token_type: string | null;\n // ...\n}\n\n// group_by[] needs URLSearchParams for repeated params\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-03-31T23:59:59Z\');\nqs.append(\'group_by[]\', \'description\');\nqs.append(\'group_by[]\', \'workspace_id\');\nconst resp = await client.get<{ data: CostBucket[] }>(\n \`/v1/organizations/cost_report?${qs.toString()}\`\n);\n\n// Sum costs\nconst total = resp.data\n .flatMap(b => b.results)\n .reduce((sum, r) => sum + parseFloat(r.amount), 0);\n\`\`\`\n\n**Code analytics (Claude Code productivity):**\n\`\`\`typescript\n// Date-only format YYYY-MM-DD. No ending_at parameter.\nconst resp = await client.get<{ data: unknown[] }>(\n \'/v1/organizations/usage_report/claude_code\',\n { starting_at: \'2025-03-01\' } // NOT ISO datetime\n);\n// Returns empty data[] when no Claude Code enterprise seats are active\n\`\`\`\n\n## Common Recipes\n\n### Monthly cost summary script\n\n\`\`\`typescript\nimport { createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\nconst client = createOrgApiClientFromEnv();\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-04-01T00:00:00Z\');\nqs.append(\'group_by[]\', \'description\');\n\nconst allResults = [];\nlet startingAt = \'2025-03-01T00:00:00Z\';\nlet hasMore = true;\n\nwhile (hasMore) {\n qs.set(\'starting_at\', startingAt);\n const resp = await client.get(\`/v1/organizations/cost_report?${qs.toString()}\`);\n allResults.push(...resp.data);\n const last = resp.data.at(-1);\n hasMore = resp.has_more && last;\n if (last) startingAt = last.ending_at;\n}\n\nconst byDescription = new Map();\nfor (const bucket of allResults) {\n for (const r of bucket.results) {\n const key = r.description ?? \'unclassified\';\n byDescription.set(key, (byDescription.get(key) ?? 0) + parseFloat(r.amount));\n }\n}\nfor (const [desc, total] of byDescription) {\n console.log(\`${desc}: $${total.toFixed(2)}\`);\n}\n\`\`\`\n\n### API key security audit\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: keys } = await client.get(\'/v1/organizations/api_keys\', { limit: 100 });\n\nconst issues = [];\nfor (const key of keys) {\n if (key.status === \'active\' && !key.expires_at) {\n issues.push(\`${key.name}: active with no expiry\`);\n }\n if (key.status === \'active\' && !key.workspace_id) {\n issues.push(\`${key.name}: not scoped to a workspace\`);\n }\n}\nconsole.log(issues.length ? issues.join(\'\\n\') : \'All keys look good\');\n\`\`\`\n\n### List org users who haven\'t accepted invites\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: invites } = await client.get(\'/v1/organizations/invites\');\nconst pending = invites.filter(i => i.status !== \'accepted\');\nconsole.log(\`${pending.length} pending invites:\`, pending.map(i => i.email));\n\`\`\`\n\n## CLI Reference\n\nAll commands require \`ANTHROPIC_ADMIN_API_KEY\` unless noted.\n\n\`\`\`\nvat claude org info Org identity (id, name)\nvat claude org users list [--limit N] List members\nvat claude org users get <user-id> Get single member\nvat claude org invites list List invitations\nvat claude org workspaces list List API workspaces\nvat claude org workspaces get <id> Get single workspace\nvat claude org workspaces members list <id> Workspace members\nvat claude org api-keys list [--status S] API key inventory\nvat claude org usage [--from DT] [--to DT] Token usage report\nvat claude org cost [--from DT] [--group-by F] USD cost report\nvat claude org code-analytics [--from DATE] Claude Code metrics (YYYY-MM-DD)\nvat claude org skills list Workspace skills (needs ANTHROPIC_API_KEY)\nvat claude org skills install <source> Upload skill dir or ZIP to org\nvat claude org skills delete <skill-id> Delete a skill (versions first)\nvat claude org skills versions list <skill-id> List skill versions\nvat claude org skills versions delete <id> <ver> Delete a skill version\n\`\`\`\n\nExit codes: \`0\` success, \`1\` expected failure (stubs), \`2\` system error (missing key, API error).\n\n**Skill deletion lifecycle:** The API requires all versions to be deleted before the skill itself.\nUse \`versions list\` to find versions, \`versions delete\` each one, then \`delete\` the skill.\n\n## Enterprise Skill Distribution\n\n### Skills API (claude.ai / Console)\n\nSkills uploaded via \`POST /v1/skills\` are **workspace-scoped** and **automatically available to\nall workspace members**. There is no per-user enable/disable via the API — visibility is\nworkspace-level only. The admin UI may have additional controls not exposed in the API.\n\n**Upload from npm package:**\n\`\`\`bash\n# Upload all skills from a package\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0\n\n# Upload a single skill\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0 --skill my-skill\n\`\`\`\n\nThe package must contain \`dist/skills/<name>/SKILL.md\` (produced by \`vat skills build\`).\nIf skills are in a sub-dependency, the command searches \`node_modules/*/dist/skills/\` too.\n\n**Duplicate titles are rejected** — the API enforces unique \`display_title\` per workspace.\nWhen uploading multiple skills, failures are non-fatal; partial results are reported.\n\n### Managed Settings (Claude Code plugins)\n\nFor enterprise-wide Claude Code plugin deployment (not the Skills API), use managed settings\npushed via MDM (Jamf, Intune, SCCM, etc.):\n\n| Platform | Path |\n|---|---|\n| macOS | \`/Library/Application Support/ClaudeCode/managed-settings.json\` |\n| Linux | \`/etc/claude-code/managed-settings.json\` |\n| Windows | \`C:\\Program Files\\ClaudeCode\\managed-settings.json\` |\n\nManaged settings are **highest priority** in the settings cascade — they override user settings.\nUse this to force-enable plugins, lock down permissions, or configure organization defaults.\n\n\`\`\`json\n{\n \"enabledPlugins\": {\n \"my-plugin@my-marketplace\": true\n }\n}\n\`\`\`\n\nCombine with \`npm install -g <package>\` (via IT software deployment) to install the plugin\nbinary, then managed settings to enable it across all machines.\n\n## Not Yet Implemented\n\nThese commands exist with the correct CLI shape but return structured\n\`not-yet-implemented\` stubs (exit 1). Coming in a future release:\n\n- \`org users update/remove\` — role changes, offboarding\n- \`org invites create/delete\` — programmatic invitations\n- \`org workspaces create/archive\` — workspace lifecycle\n- \`org workspaces members add/update/remove\` — workspace membership\n- \`org api-keys update\` — rename keys\n";
11
+
12
+ export const fragments = {
13
+ twoWaysToUseIt: {
14
+ header: "## Two Ways to Use It",
15
+ body: "### CLI — Quick Queries\n\n\`\`\`bash\nvat claude org info # Org identity\nvat claude org users list # All members\nvat claude org api-keys list --status active # Active API keys\nvat claude org cost --group-by description # Cost breakdown by model\nvat claude org usage --from 2025-01-01T00:00:00Z # Token usage since Jan\nvat claude org skills list # Workspace-scoped skills (requires ANTHROPIC_API_KEY)\n\`\`\`\n\n### Library — Scripts and Automation\n\n\`\`\`typescript\nimport { OrgApiClient, createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\n// Reads ANTHROPIC_ADMIN_API_KEY and optionally ANTHROPIC_API_KEY from env\nconst client = createOrgApiClientFromEnv();\n\n// Or construct directly\nconst client = new OrgApiClient({\n adminApiKey: \'sk-ant-admin-...\',\n apiKey: \'sk-ant-api03-...\', // only needed for skills endpoints\n});\n\`\`\`",
16
+ text: "## Two Ways to Use It\n\n### CLI — Quick Queries\n\n\`\`\`bash\nvat claude org info # Org identity\nvat claude org users list # All members\nvat claude org api-keys list --status active # Active API keys\nvat claude org cost --group-by description # Cost breakdown by model\nvat claude org usage --from 2025-01-01T00:00:00Z # Token usage since Jan\nvat claude org skills list # Workspace-scoped skills (requires ANTHROPIC_API_KEY)\n\`\`\`\n\n### Library — Scripts and Automation\n\n\`\`\`typescript\nimport { OrgApiClient, createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\n// Reads ANTHROPIC_ADMIN_API_KEY and optionally ANTHROPIC_API_KEY from env\nconst client = createOrgApiClientFromEnv();\n\n// Or construct directly\nconst client = new OrgApiClient({\n adminApiKey: \'sk-ant-admin-...\',\n apiKey: \'sk-ant-api03-...\', // only needed for skills endpoints\n});\n\`\`\`"
17
+ },
18
+ apiReference: {
19
+ header: "## API Reference",
20
+ body: "### Auth: Two Keys, Two Surfaces\n\n| Key | Env Var | Endpoints | Who Has It |\n|---|---|---|---|\n| Admin API key | \`ANTHROPIC_ADMIN_API_KEY\` | \`/v1/organizations/*\` | Org admins only |\n| Regular API key | \`ANTHROPIC_API_KEY\` | \`/v1/skills\` (beta) | Any workspace member |\n\n### Endpoints and Methods\n\n**Org identity:**\n\`\`\`typescript\nconst org = await client.get<{ id: string; type: string; name: string }>(\'/v1/organizations/me\');\n\`\`\`\n\n**Users:**\n\`\`\`typescript\n// List (paginated with limit/after_id)\nconst users = await client.get<{ data: OrgUser[]; has_more: boolean }>(\n \'/v1/organizations/users\', { limit: 100 }\n);\n\n// Get single user\nconst user = await client.get<OrgUser>(\'/v1/organizations/users/user_abc123\');\n\`\`\`\n\n**Invites:**\n\`\`\`typescript\nconst invites = await client.get<{ data: OrgInvite[]; has_more: boolean }>(\n \'/v1/organizations/invites\'\n);\n\`\`\`\n\n**Workspaces:**\n\`\`\`typescript\nconst workspaces = await client.get<{ data: OrgWorkspace[]; has_more: boolean }>(\n \'/v1/organizations/workspaces\'\n);\n\n// Workspace members\nconst members = await client.get<{ data: WorkspaceMember[]; has_more: boolean }>(\n \'/v1/organizations/workspaces/ws_abc/members\'\n);\n\`\`\`\n\n**API keys:**\n\`\`\`typescript\nconst keys = await client.get<{ data: ApiKey[]; has_more: boolean }>(\n \'/v1/organizations/api_keys\',\n { status: \'active\', workspace_id: \'ws_abc\' } // both filters optional\n);\n\`\`\`\n\n**Skills (beta — uses regular API key):**\n\`\`\`typescript\n// List skills\nconst skills = await client.getSkills<{ data: Skill[]; has_more: boolean }>(\'/v1/skills\');\n// Adds anthropic-beta: skills-2025-10-02 header automatically\n\n// Upload a skill (multipart/form-data)\nimport { buildMultipartFormData } from \'@vibe-agent-toolkit/claude-marketplace\';\nconst multipart = buildMultipartFormData(\n { display_title: \'My Skill\' },\n [{ fieldName: \'files[]\', filename: \'SKILL.md\', content: Buffer.from(skillContent) }],\n);\nconst created = await client.uploadSkill<{ id: string; latest_version: string }>(multipart);\n\n// Delete a skill\nconst deleted = await client.deleteSkill<{ id: string; type: string }>(skillId);\n\`\`\`\n\n### Report Endpoints — Pagination Quirk\n\nUsage, cost, and code-analytics endpoints have a **non-standard pagination model**.\nThey return \`has_more: true\` with a \`next_page\` cursor, but the API **rejects \`next_page\`\nas a query parameter**. Paginate by advancing \`starting_at\` to the last bucket\'s \`ending_at\`.\n\n**Usage report (daily token buckets):**\n\`\`\`typescript\ninterface UsageBucket {\n starting_at: string;\n ending_at: string;\n results: Array<{\n uncached_input_tokens: number;\n cache_read_input_tokens: number;\n output_tokens: number;\n model: string | null;\n workspace_id: string | null;\n api_key_id: string | null;\n service_tier: string | null;\n // ... other dimension fields, null if not applicable\n }>;\n}\n\n// First page\nlet resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: \'2025-01-01T00:00:00Z\', ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\n// Subsequent pages — advance starting_at, do NOT pass next_page\nconst lastBucket = resp.data.at(-1);\nresp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: lastBucket.ending_at, ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\`\`\`\n\n**Cost report:**\n\`\`\`typescript\n// amount is a STRING, not a number — parse before arithmetic\ninterface CostResult {\n currency: string;\n amount: string; // \"7.0812\" — use parseFloat()\n description: string | null;\n model: string | null;\n token_type: string | null;\n // ...\n}\n\n// group_by[] needs URLSearchParams for repeated params\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-03-31T23:59:59Z\');\nqs.append(\'group_by[]\', \'description\');\nqs.append(\'group_by[]\', \'workspace_id\');\nconst resp = await client.get<{ data: CostBucket[] }>(\n \`/v1/organizations/cost_report?${qs.toString()}\`\n);\n\n// Sum costs\nconst total = resp.data\n .flatMap(b => b.results)\n .reduce((sum, r) => sum + parseFloat(r.amount), 0);\n\`\`\`\n\n**Code analytics (Claude Code productivity):**\n\`\`\`typescript\n// Date-only format YYYY-MM-DD. No ending_at parameter.\nconst resp = await client.get<{ data: unknown[] }>(\n \'/v1/organizations/usage_report/claude_code\',\n { starting_at: \'2025-03-01\' } // NOT ISO datetime\n);\n// Returns empty data[] when no Claude Code enterprise seats are active\n\`\`\`",
21
+ text: "## API Reference\n\n### Auth: Two Keys, Two Surfaces\n\n| Key | Env Var | Endpoints | Who Has It |\n|---|---|---|---|\n| Admin API key | \`ANTHROPIC_ADMIN_API_KEY\` | \`/v1/organizations/*\` | Org admins only |\n| Regular API key | \`ANTHROPIC_API_KEY\` | \`/v1/skills\` (beta) | Any workspace member |\n\n### Endpoints and Methods\n\n**Org identity:**\n\`\`\`typescript\nconst org = await client.get<{ id: string; type: string; name: string }>(\'/v1/organizations/me\');\n\`\`\`\n\n**Users:**\n\`\`\`typescript\n// List (paginated with limit/after_id)\nconst users = await client.get<{ data: OrgUser[]; has_more: boolean }>(\n \'/v1/organizations/users\', { limit: 100 }\n);\n\n// Get single user\nconst user = await client.get<OrgUser>(\'/v1/organizations/users/user_abc123\');\n\`\`\`\n\n**Invites:**\n\`\`\`typescript\nconst invites = await client.get<{ data: OrgInvite[]; has_more: boolean }>(\n \'/v1/organizations/invites\'\n);\n\`\`\`\n\n**Workspaces:**\n\`\`\`typescript\nconst workspaces = await client.get<{ data: OrgWorkspace[]; has_more: boolean }>(\n \'/v1/organizations/workspaces\'\n);\n\n// Workspace members\nconst members = await client.get<{ data: WorkspaceMember[]; has_more: boolean }>(\n \'/v1/organizations/workspaces/ws_abc/members\'\n);\n\`\`\`\n\n**API keys:**\n\`\`\`typescript\nconst keys = await client.get<{ data: ApiKey[]; has_more: boolean }>(\n \'/v1/organizations/api_keys\',\n { status: \'active\', workspace_id: \'ws_abc\' } // both filters optional\n);\n\`\`\`\n\n**Skills (beta — uses regular API key):**\n\`\`\`typescript\n// List skills\nconst skills = await client.getSkills<{ data: Skill[]; has_more: boolean }>(\'/v1/skills\');\n// Adds anthropic-beta: skills-2025-10-02 header automatically\n\n// Upload a skill (multipart/form-data)\nimport { buildMultipartFormData } from \'@vibe-agent-toolkit/claude-marketplace\';\nconst multipart = buildMultipartFormData(\n { display_title: \'My Skill\' },\n [{ fieldName: \'files[]\', filename: \'SKILL.md\', content: Buffer.from(skillContent) }],\n);\nconst created = await client.uploadSkill<{ id: string; latest_version: string }>(multipart);\n\n// Delete a skill\nconst deleted = await client.deleteSkill<{ id: string; type: string }>(skillId);\n\`\`\`\n\n### Report Endpoints — Pagination Quirk\n\nUsage, cost, and code-analytics endpoints have a **non-standard pagination model**.\nThey return \`has_more: true\` with a \`next_page\` cursor, but the API **rejects \`next_page\`\nas a query parameter**. Paginate by advancing \`starting_at\` to the last bucket\'s \`ending_at\`.\n\n**Usage report (daily token buckets):**\n\`\`\`typescript\ninterface UsageBucket {\n starting_at: string;\n ending_at: string;\n results: Array<{\n uncached_input_tokens: number;\n cache_read_input_tokens: number;\n output_tokens: number;\n model: string | null;\n workspace_id: string | null;\n api_key_id: string | null;\n service_tier: string | null;\n // ... other dimension fields, null if not applicable\n }>;\n}\n\n// First page\nlet resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: \'2025-01-01T00:00:00Z\', ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\n// Subsequent pages — advance starting_at, do NOT pass next_page\nconst lastBucket = resp.data.at(-1);\nresp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(\n \'/v1/organizations/usage_report/messages\',\n { starting_at: lastBucket.ending_at, ending_at: \'2025-12-31T23:59:59Z\' }\n);\n\`\`\`\n\n**Cost report:**\n\`\`\`typescript\n// amount is a STRING, not a number — parse before arithmetic\ninterface CostResult {\n currency: string;\n amount: string; // \"7.0812\" — use parseFloat()\n description: string | null;\n model: string | null;\n token_type: string | null;\n // ...\n}\n\n// group_by[] needs URLSearchParams for repeated params\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-03-31T23:59:59Z\');\nqs.append(\'group_by[]\', \'description\');\nqs.append(\'group_by[]\', \'workspace_id\');\nconst resp = await client.get<{ data: CostBucket[] }>(\n \`/v1/organizations/cost_report?${qs.toString()}\`\n);\n\n// Sum costs\nconst total = resp.data\n .flatMap(b => b.results)\n .reduce((sum, r) => sum + parseFloat(r.amount), 0);\n\`\`\`\n\n**Code analytics (Claude Code productivity):**\n\`\`\`typescript\n// Date-only format YYYY-MM-DD. No ending_at parameter.\nconst resp = await client.get<{ data: unknown[] }>(\n \'/v1/organizations/usage_report/claude_code\',\n { starting_at: \'2025-03-01\' } // NOT ISO datetime\n);\n// Returns empty data[] when no Claude Code enterprise seats are active\n\`\`\`"
22
+ },
23
+ commonRecipes: {
24
+ header: "## Common Recipes",
25
+ body: "### Monthly cost summary script\n\n\`\`\`typescript\nimport { createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\nconst client = createOrgApiClientFromEnv();\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-04-01T00:00:00Z\');\nqs.append(\'group_by[]\', \'description\');\n\nconst allResults = [];\nlet startingAt = \'2025-03-01T00:00:00Z\';\nlet hasMore = true;\n\nwhile (hasMore) {\n qs.set(\'starting_at\', startingAt);\n const resp = await client.get(\`/v1/organizations/cost_report?${qs.toString()}\`);\n allResults.push(...resp.data);\n const last = resp.data.at(-1);\n hasMore = resp.has_more && last;\n if (last) startingAt = last.ending_at;\n}\n\nconst byDescription = new Map();\nfor (const bucket of allResults) {\n for (const r of bucket.results) {\n const key = r.description ?? \'unclassified\';\n byDescription.set(key, (byDescription.get(key) ?? 0) + parseFloat(r.amount));\n }\n}\nfor (const [desc, total] of byDescription) {\n console.log(\`${desc}: $${total.toFixed(2)}\`);\n}\n\`\`\`\n\n### API key security audit\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: keys } = await client.get(\'/v1/organizations/api_keys\', { limit: 100 });\n\nconst issues = [];\nfor (const key of keys) {\n if (key.status === \'active\' && !key.expires_at) {\n issues.push(\`${key.name}: active with no expiry\`);\n }\n if (key.status === \'active\' && !key.workspace_id) {\n issues.push(\`${key.name}: not scoped to a workspace\`);\n }\n}\nconsole.log(issues.length ? issues.join(\'\\n\') : \'All keys look good\');\n\`\`\`\n\n### List org users who haven\'t accepted invites\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: invites } = await client.get(\'/v1/organizations/invites\');\nconst pending = invites.filter(i => i.status !== \'accepted\');\nconsole.log(\`${pending.length} pending invites:\`, pending.map(i => i.email));\n\`\`\`",
26
+ text: "## Common Recipes\n\n### Monthly cost summary script\n\n\`\`\`typescript\nimport { createOrgApiClientFromEnv } from \'@vibe-agent-toolkit/claude-marketplace\';\n\nconst client = createOrgApiClientFromEnv();\nconst qs = new URLSearchParams();\nqs.set(\'starting_at\', \'2025-03-01T00:00:00Z\');\nqs.set(\'ending_at\', \'2025-04-01T00:00:00Z\');\nqs.append(\'group_by[]\', \'description\');\n\nconst allResults = [];\nlet startingAt = \'2025-03-01T00:00:00Z\';\nlet hasMore = true;\n\nwhile (hasMore) {\n qs.set(\'starting_at\', startingAt);\n const resp = await client.get(\`/v1/organizations/cost_report?${qs.toString()}\`);\n allResults.push(...resp.data);\n const last = resp.data.at(-1);\n hasMore = resp.has_more && last;\n if (last) startingAt = last.ending_at;\n}\n\nconst byDescription = new Map();\nfor (const bucket of allResults) {\n for (const r of bucket.results) {\n const key = r.description ?? \'unclassified\';\n byDescription.set(key, (byDescription.get(key) ?? 0) + parseFloat(r.amount));\n }\n}\nfor (const [desc, total] of byDescription) {\n console.log(\`${desc}: $${total.toFixed(2)}\`);\n}\n\`\`\`\n\n### API key security audit\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: keys } = await client.get(\'/v1/organizations/api_keys\', { limit: 100 });\n\nconst issues = [];\nfor (const key of keys) {\n if (key.status === \'active\' && !key.expires_at) {\n issues.push(\`${key.name}: active with no expiry\`);\n }\n if (key.status === \'active\' && !key.workspace_id) {\n issues.push(\`${key.name}: not scoped to a workspace\`);\n }\n}\nconsole.log(issues.length ? issues.join(\'\\n\') : \'All keys look good\');\n\`\`\`\n\n### List org users who haven\'t accepted invites\n\n\`\`\`typescript\nconst client = createOrgApiClientFromEnv();\nconst { data: invites } = await client.get(\'/v1/organizations/invites\');\nconst pending = invites.filter(i => i.status !== \'accepted\');\nconsole.log(\`${pending.length} pending invites:\`, pending.map(i => i.email));\n\`\`\`"
27
+ },
28
+ cliReference: {
29
+ header: "## CLI Reference",
30
+ body: "All commands require \`ANTHROPIC_ADMIN_API_KEY\` unless noted.\n\n\`\`\`\nvat claude org info Org identity (id, name)\nvat claude org users list [--limit N] List members\nvat claude org users get <user-id> Get single member\nvat claude org invites list List invitations\nvat claude org workspaces list List API workspaces\nvat claude org workspaces get <id> Get single workspace\nvat claude org workspaces members list <id> Workspace members\nvat claude org api-keys list [--status S] API key inventory\nvat claude org usage [--from DT] [--to DT] Token usage report\nvat claude org cost [--from DT] [--group-by F] USD cost report\nvat claude org code-analytics [--from DATE] Claude Code metrics (YYYY-MM-DD)\nvat claude org skills list Workspace skills (needs ANTHROPIC_API_KEY)\nvat claude org skills install <source> Upload skill dir or ZIP to org\nvat claude org skills delete <skill-id> Delete a skill (versions first)\nvat claude org skills versions list <skill-id> List skill versions\nvat claude org skills versions delete <id> <ver> Delete a skill version\n\`\`\`\n\nExit codes: \`0\` success, \`1\` expected failure (stubs), \`2\` system error (missing key, API error).\n\n**Skill deletion lifecycle:** The API requires all versions to be deleted before the skill itself.\nUse \`versions list\` to find versions, \`versions delete\` each one, then \`delete\` the skill.",
31
+ text: "## CLI Reference\n\nAll commands require \`ANTHROPIC_ADMIN_API_KEY\` unless noted.\n\n\`\`\`\nvat claude org info Org identity (id, name)\nvat claude org users list [--limit N] List members\nvat claude org users get <user-id> Get single member\nvat claude org invites list List invitations\nvat claude org workspaces list List API workspaces\nvat claude org workspaces get <id> Get single workspace\nvat claude org workspaces members list <id> Workspace members\nvat claude org api-keys list [--status S] API key inventory\nvat claude org usage [--from DT] [--to DT] Token usage report\nvat claude org cost [--from DT] [--group-by F] USD cost report\nvat claude org code-analytics [--from DATE] Claude Code metrics (YYYY-MM-DD)\nvat claude org skills list Workspace skills (needs ANTHROPIC_API_KEY)\nvat claude org skills install <source> Upload skill dir or ZIP to org\nvat claude org skills delete <skill-id> Delete a skill (versions first)\nvat claude org skills versions list <skill-id> List skill versions\nvat claude org skills versions delete <id> <ver> Delete a skill version\n\`\`\`\n\nExit codes: \`0\` success, \`1\` expected failure (stubs), \`2\` system error (missing key, API error).\n\n**Skill deletion lifecycle:** The API requires all versions to be deleted before the skill itself.\nUse \`versions list\` to find versions, \`versions delete\` each one, then \`delete\` the skill."
32
+ },
33
+ enterpriseSkillDistribution: {
34
+ header: "## Enterprise Skill Distribution",
35
+ body: "### Skills API (claude.ai / Console)\n\nSkills uploaded via \`POST /v1/skills\` are **workspace-scoped** and **automatically available to\nall workspace members**. There is no per-user enable/disable via the API — visibility is\nworkspace-level only. The admin UI may have additional controls not exposed in the API.\n\n**Upload from npm package:**\n\`\`\`bash\n# Upload all skills from a package\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0\n\n# Upload a single skill\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0 --skill my-skill\n\`\`\`\n\nThe package must contain \`dist/skills/<name>/SKILL.md\` (produced by \`vat skills build\`).\nIf skills are in a sub-dependency, the command searches \`node_modules/*/dist/skills/\` too.\n\n**Duplicate titles are rejected** — the API enforces unique \`display_title\` per workspace.\nWhen uploading multiple skills, failures are non-fatal; partial results are reported.\n\n### Managed Settings (Claude Code plugins)\n\nFor enterprise-wide Claude Code plugin deployment (not the Skills API), use managed settings\npushed via MDM (Jamf, Intune, SCCM, etc.):\n\n| Platform | Path |\n|---|---|\n| macOS | \`/Library/Application Support/ClaudeCode/managed-settings.json\` |\n| Linux | \`/etc/claude-code/managed-settings.json\` |\n| Windows | \`C:\\Program Files\\ClaudeCode\\managed-settings.json\` |\n\nManaged settings are **highest priority** in the settings cascade — they override user settings.\nUse this to force-enable plugins, lock down permissions, or configure organization defaults.\n\n\`\`\`json\n{\n \"enabledPlugins\": {\n \"my-plugin@my-marketplace\": true\n }\n}\n\`\`\`\n\nCombine with \`npm install -g <package>\` (via IT software deployment) to install the plugin\nbinary, then managed settings to enable it across all machines.",
36
+ text: "## Enterprise Skill Distribution\n\n### Skills API (claude.ai / Console)\n\nSkills uploaded via \`POST /v1/skills\` are **workspace-scoped** and **automatically available to\nall workspace members**. There is no per-user enable/disable via the API — visibility is\nworkspace-level only. The admin UI may have additional controls not exposed in the API.\n\n**Upload from npm package:**\n\`\`\`bash\n# Upload all skills from a package\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0\n\n# Upload a single skill\nvat claude org skills install --from-npm @scope/my-skills-package@1.0.0 --skill my-skill\n\`\`\`\n\nThe package must contain \`dist/skills/<name>/SKILL.md\` (produced by \`vat skills build\`).\nIf skills are in a sub-dependency, the command searches \`node_modules/*/dist/skills/\` too.\n\n**Duplicate titles are rejected** — the API enforces unique \`display_title\` per workspace.\nWhen uploading multiple skills, failures are non-fatal; partial results are reported.\n\n### Managed Settings (Claude Code plugins)\n\nFor enterprise-wide Claude Code plugin deployment (not the Skills API), use managed settings\npushed via MDM (Jamf, Intune, SCCM, etc.):\n\n| Platform | Path |\n|---|---|\n| macOS | \`/Library/Application Support/ClaudeCode/managed-settings.json\` |\n| Linux | \`/etc/claude-code/managed-settings.json\` |\n| Windows | \`C:\\Program Files\\ClaudeCode\\managed-settings.json\` |\n\nManaged settings are **highest priority** in the settings cascade — they override user settings.\nUse this to force-enable plugins, lock down permissions, or configure organization defaults.\n\n\`\`\`json\n{\n \"enabledPlugins\": {\n \"my-plugin@my-marketplace\": true\n }\n}\n\`\`\`\n\nCombine with \`npm install -g <package>\` (via IT software deployment) to install the plugin\nbinary, then managed settings to enable it across all machines."
37
+ },
38
+ notYetImplemented: {
39
+ header: "## Not Yet Implemented",
40
+ body: "These commands exist with the correct CLI shape but return structured\n\`not-yet-implemented\` stubs (exit 1). Coming in a future release:\n\n- \`org users update/remove\` — role changes, offboarding\n- \`org invites create/delete\` — programmatic invitations\n- \`org workspaces create/archive\` — workspace lifecycle\n- \`org workspaces members add/update/remove\` — workspace membership\n- \`org api-keys update\` — rename keys",
41
+ text: "## Not Yet Implemented\n\nThese commands exist with the correct CLI shape but return structured\n\`not-yet-implemented\` stubs (exit 1). Coming in a future release:\n\n- \`org users update/remove\` — role changes, offboarding\n- \`org invites create/delete\` — programmatic invitations\n- \`org workspaces create/archive\` — workspace lifecycle\n- \`org workspaces members add/update/remove\` — workspace membership\n- \`org api-keys update\` — rename keys"
42
+ }
43
+ };
@@ -0,0 +1,337 @@
1
+ ---
2
+ name: org-admin
3
+ description: Anthropic org administration for Enterprise/Team admins. Requires ANTHROPIC_ADMIN_API_KEY. Use for org user management, API key auditing, cost/usage reporting, workspace administration, and enterprise skill distribution via the Anthropic Admin API. Not for regular users — admin access required.
4
+ ---
5
+
6
+ # Claude Org Administration
7
+
8
+ **For Anthropic org admins only.** Requires `ANTHROPIC_ADMIN_API_KEY` (Enterprise/Team plan).
9
+ If you don't have an admin key, this skill is not for you — use `vibe-agent-toolkit:distribution`
10
+ for local plugin management instead.
11
+
12
+ ## Two Ways to Use It
13
+
14
+ ### CLI — Quick Queries
15
+
16
+ ```bash
17
+ vat claude org info # Org identity
18
+ vat claude org users list # All members
19
+ vat claude org api-keys list --status active # Active API keys
20
+ vat claude org cost --group-by description # Cost breakdown by model
21
+ vat claude org usage --from 2025-01-01T00:00:00Z # Token usage since Jan
22
+ vat claude org skills list # Workspace-scoped skills (requires ANTHROPIC_API_KEY)
23
+ ```
24
+
25
+ ### Library — Scripts and Automation
26
+
27
+ ```typescript
28
+ import { OrgApiClient, createOrgApiClientFromEnv } from '@vibe-agent-toolkit/claude-marketplace';
29
+
30
+ // Reads ANTHROPIC_ADMIN_API_KEY and optionally ANTHROPIC_API_KEY from env
31
+ const client = createOrgApiClientFromEnv();
32
+
33
+ // Or construct directly
34
+ const client = new OrgApiClient({
35
+ adminApiKey: 'sk-ant-admin-...',
36
+ apiKey: 'sk-ant-api03-...', // only needed for skills endpoints
37
+ });
38
+ ```
39
+
40
+ ## API Reference
41
+
42
+ ### Auth: Two Keys, Two Surfaces
43
+
44
+ | Key | Env Var | Endpoints | Who Has It |
45
+ |---|---|---|---|
46
+ | Admin API key | `ANTHROPIC_ADMIN_API_KEY` | `/v1/organizations/*` | Org admins only |
47
+ | Regular API key | `ANTHROPIC_API_KEY` | `/v1/skills` (beta) | Any workspace member |
48
+
49
+ ### Endpoints and Methods
50
+
51
+ **Org identity:**
52
+ ```typescript
53
+ const org = await client.get<{ id: string; type: string; name: string }>('/v1/organizations/me');
54
+ ```
55
+
56
+ **Users:**
57
+ ```typescript
58
+ // List (paginated with limit/after_id)
59
+ const users = await client.get<{ data: OrgUser[]; has_more: boolean }>(
60
+ '/v1/organizations/users', { limit: 100 }
61
+ );
62
+
63
+ // Get single user
64
+ const user = await client.get<OrgUser>('/v1/organizations/users/user_abc123');
65
+ ```
66
+
67
+ **Invites:**
68
+ ```typescript
69
+ const invites = await client.get<{ data: OrgInvite[]; has_more: boolean }>(
70
+ '/v1/organizations/invites'
71
+ );
72
+ ```
73
+
74
+ **Workspaces:**
75
+ ```typescript
76
+ const workspaces = await client.get<{ data: OrgWorkspace[]; has_more: boolean }>(
77
+ '/v1/organizations/workspaces'
78
+ );
79
+
80
+ // Workspace members
81
+ const members = await client.get<{ data: WorkspaceMember[]; has_more: boolean }>(
82
+ '/v1/organizations/workspaces/ws_abc/members'
83
+ );
84
+ ```
85
+
86
+ **API keys:**
87
+ ```typescript
88
+ const keys = await client.get<{ data: ApiKey[]; has_more: boolean }>(
89
+ '/v1/organizations/api_keys',
90
+ { status: 'active', workspace_id: 'ws_abc' } // both filters optional
91
+ );
92
+ ```
93
+
94
+ **Skills (beta — uses regular API key):**
95
+ ```typescript
96
+ // List skills
97
+ const skills = await client.getSkills<{ data: Skill[]; has_more: boolean }>('/v1/skills');
98
+ // Adds anthropic-beta: skills-2025-10-02 header automatically
99
+
100
+ // Upload a skill (multipart/form-data)
101
+ import { buildMultipartFormData } from '@vibe-agent-toolkit/claude-marketplace';
102
+ const multipart = buildMultipartFormData(
103
+ { display_title: 'My Skill' },
104
+ [{ fieldName: 'files[]', filename: 'SKILL.md', content: Buffer.from(skillContent) }],
105
+ );
106
+ const created = await client.uploadSkill<{ id: string; latest_version: string }>(multipart);
107
+
108
+ // Delete a skill
109
+ const deleted = await client.deleteSkill<{ id: string; type: string }>(skillId);
110
+ ```
111
+
112
+ ### Report Endpoints — Pagination Quirk
113
+
114
+ Usage, cost, and code-analytics endpoints have a **non-standard pagination model**.
115
+ They return `has_more: true` with a `next_page` cursor, but the API **rejects `next_page`
116
+ as a query parameter**. Paginate by advancing `starting_at` to the last bucket's `ending_at`.
117
+
118
+ **Usage report (daily token buckets):**
119
+ ```typescript
120
+ interface UsageBucket {
121
+ starting_at: string;
122
+ ending_at: string;
123
+ results: Array<{
124
+ uncached_input_tokens: number;
125
+ cache_read_input_tokens: number;
126
+ output_tokens: number;
127
+ model: string | null;
128
+ workspace_id: string | null;
129
+ api_key_id: string | null;
130
+ service_tier: string | null;
131
+ // ... other dimension fields, null if not applicable
132
+ }>;
133
+ }
134
+
135
+ // First page
136
+ let resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(
137
+ '/v1/organizations/usage_report/messages',
138
+ { starting_at: '2025-01-01T00:00:00Z', ending_at: '2025-12-31T23:59:59Z' }
139
+ );
140
+
141
+ // Subsequent pages — advance starting_at, do NOT pass next_page
142
+ const lastBucket = resp.data.at(-1);
143
+ resp = await client.get<{ data: UsageBucket[]; has_more: boolean }>(
144
+ '/v1/organizations/usage_report/messages',
145
+ { starting_at: lastBucket.ending_at, ending_at: '2025-12-31T23:59:59Z' }
146
+ );
147
+ ```
148
+
149
+ **Cost report:**
150
+ ```typescript
151
+ // amount is a STRING, not a number — parse before arithmetic
152
+ interface CostResult {
153
+ currency: string;
154
+ amount: string; // "7.0812" — use parseFloat()
155
+ description: string | null;
156
+ model: string | null;
157
+ token_type: string | null;
158
+ // ...
159
+ }
160
+
161
+ // group_by[] needs URLSearchParams for repeated params
162
+ const qs = new URLSearchParams();
163
+ qs.set('starting_at', '2025-03-01T00:00:00Z');
164
+ qs.set('ending_at', '2025-03-31T23:59:59Z');
165
+ qs.append('group_by[]', 'description');
166
+ qs.append('group_by[]', 'workspace_id');
167
+ const resp = await client.get<{ data: CostBucket[] }>(
168
+ `/v1/organizations/cost_report?${qs.toString()}`
169
+ );
170
+
171
+ // Sum costs
172
+ const total = resp.data
173
+ .flatMap(b => b.results)
174
+ .reduce((sum, r) => sum + parseFloat(r.amount), 0);
175
+ ```
176
+
177
+ **Code analytics (Claude Code productivity):**
178
+ ```typescript
179
+ // Date-only format YYYY-MM-DD. No ending_at parameter.
180
+ const resp = await client.get<{ data: unknown[] }>(
181
+ '/v1/organizations/usage_report/claude_code',
182
+ { starting_at: '2025-03-01' } // NOT ISO datetime
183
+ );
184
+ // Returns empty data[] when no Claude Code enterprise seats are active
185
+ ```
186
+
187
+ ## Common Recipes
188
+
189
+ ### Monthly cost summary script
190
+
191
+ ```typescript
192
+ import { createOrgApiClientFromEnv } from '@vibe-agent-toolkit/claude-marketplace';
193
+
194
+ const client = createOrgApiClientFromEnv();
195
+ const qs = new URLSearchParams();
196
+ qs.set('starting_at', '2025-03-01T00:00:00Z');
197
+ qs.set('ending_at', '2025-04-01T00:00:00Z');
198
+ qs.append('group_by[]', 'description');
199
+
200
+ const allResults = [];
201
+ let startingAt = '2025-03-01T00:00:00Z';
202
+ let hasMore = true;
203
+
204
+ while (hasMore) {
205
+ qs.set('starting_at', startingAt);
206
+ const resp = await client.get(`/v1/organizations/cost_report?${qs.toString()}`);
207
+ allResults.push(...resp.data);
208
+ const last = resp.data.at(-1);
209
+ hasMore = resp.has_more && last;
210
+ if (last) startingAt = last.ending_at;
211
+ }
212
+
213
+ const byDescription = new Map();
214
+ for (const bucket of allResults) {
215
+ for (const r of bucket.results) {
216
+ const key = r.description ?? 'unclassified';
217
+ byDescription.set(key, (byDescription.get(key) ?? 0) + parseFloat(r.amount));
218
+ }
219
+ }
220
+ for (const [desc, total] of byDescription) {
221
+ console.log(`${desc}: $${total.toFixed(2)}`);
222
+ }
223
+ ```
224
+
225
+ ### API key security audit
226
+
227
+ ```typescript
228
+ const client = createOrgApiClientFromEnv();
229
+ const { data: keys } = await client.get('/v1/organizations/api_keys', { limit: 100 });
230
+
231
+ const issues = [];
232
+ for (const key of keys) {
233
+ if (key.status === 'active' && !key.expires_at) {
234
+ issues.push(`${key.name}: active with no expiry`);
235
+ }
236
+ if (key.status === 'active' && !key.workspace_id) {
237
+ issues.push(`${key.name}: not scoped to a workspace`);
238
+ }
239
+ }
240
+ console.log(issues.length ? issues.join('\n') : 'All keys look good');
241
+ ```
242
+
243
+ ### List org users who haven't accepted invites
244
+
245
+ ```typescript
246
+ const client = createOrgApiClientFromEnv();
247
+ const { data: invites } = await client.get('/v1/organizations/invites');
248
+ const pending = invites.filter(i => i.status !== 'accepted');
249
+ console.log(`${pending.length} pending invites:`, pending.map(i => i.email));
250
+ ```
251
+
252
+ ## CLI Reference
253
+
254
+ All commands require `ANTHROPIC_ADMIN_API_KEY` unless noted.
255
+
256
+ ```
257
+ vat claude org info Org identity (id, name)
258
+ vat claude org users list [--limit N] List members
259
+ vat claude org users get <user-id> Get single member
260
+ vat claude org invites list List invitations
261
+ vat claude org workspaces list List API workspaces
262
+ vat claude org workspaces get <id> Get single workspace
263
+ vat claude org workspaces members list <id> Workspace members
264
+ vat claude org api-keys list [--status S] API key inventory
265
+ vat claude org usage [--from DT] [--to DT] Token usage report
266
+ vat claude org cost [--from DT] [--group-by F] USD cost report
267
+ vat claude org code-analytics [--from DATE] Claude Code metrics (YYYY-MM-DD)
268
+ vat claude org skills list Workspace skills (needs ANTHROPIC_API_KEY)
269
+ vat claude org skills install <source> Upload skill dir or ZIP to org
270
+ vat claude org skills delete <skill-id> Delete a skill (versions first)
271
+ vat claude org skills versions list <skill-id> List skill versions
272
+ vat claude org skills versions delete <id> <ver> Delete a skill version
273
+ ```
274
+
275
+ Exit codes: `0` success, `1` expected failure (stubs), `2` system error (missing key, API error).
276
+
277
+ **Skill deletion lifecycle:** The API requires all versions to be deleted before the skill itself.
278
+ Use `versions list` to find versions, `versions delete` each one, then `delete` the skill.
279
+
280
+ ## Enterprise Skill Distribution
281
+
282
+ ### Skills API (claude.ai / Console)
283
+
284
+ Skills uploaded via `POST /v1/skills` are **workspace-scoped** and **automatically available to
285
+ all workspace members**. There is no per-user enable/disable via the API — visibility is
286
+ workspace-level only. The admin UI may have additional controls not exposed in the API.
287
+
288
+ **Upload from npm package:**
289
+ ```bash
290
+ # Upload all skills from a package
291
+ vat claude org skills install --from-npm @scope/my-skills-package@1.0.0
292
+
293
+ # Upload a single skill
294
+ vat claude org skills install --from-npm @scope/my-skills-package@1.0.0 --skill my-skill
295
+ ```
296
+
297
+ The package must contain `dist/skills/<name>/SKILL.md` (produced by `vat skills build`).
298
+ If skills are in a sub-dependency, the command searches `node_modules/*/dist/skills/` too.
299
+
300
+ **Duplicate titles are rejected** — the API enforces unique `display_title` per workspace.
301
+ When uploading multiple skills, failures are non-fatal; partial results are reported.
302
+
303
+ ### Managed Settings (Claude Code plugins)
304
+
305
+ For enterprise-wide Claude Code plugin deployment (not the Skills API), use managed settings
306
+ pushed via MDM (Jamf, Intune, SCCM, etc.):
307
+
308
+ | Platform | Path |
309
+ |---|---|
310
+ | macOS | `/Library/Application Support/ClaudeCode/managed-settings.json` |
311
+ | Linux | `/etc/claude-code/managed-settings.json` |
312
+ | Windows | `C:\Program Files\ClaudeCode\managed-settings.json` |
313
+
314
+ Managed settings are **highest priority** in the settings cascade — they override user settings.
315
+ Use this to force-enable plugins, lock down permissions, or configure organization defaults.
316
+
317
+ ```json
318
+ {
319
+ "enabledPlugins": {
320
+ "my-plugin@my-marketplace": true
321
+ }
322
+ }
323
+ ```
324
+
325
+ Combine with `npm install -g <package>` (via IT software deployment) to install the plugin
326
+ binary, then managed settings to enable it across all machines.
327
+
328
+ ## Not Yet Implemented
329
+
330
+ These commands exist with the correct CLI shape but return structured
331
+ `not-yet-implemented` stubs (exit 1). Coming in a future release:
332
+
333
+ - `org users update/remove` — role changes, offboarding
334
+ - `org invites create/delete` — programmatic invitations
335
+ - `org workspaces create/archive` — workspace lifecycle
336
+ - `org workspaces members add/update/remove` — workspace membership
337
+ - `org api-keys update` — rename keys
@@ -40,6 +40,7 @@ non-TypeScript/JavaScript projects, or cases where you need deep framework-speci
40
40
  | `--target claude-web` ZIP format | `vibe-agent-toolkit:distribution` |
41
41
  | Install/uninstall methods, enterprise deployment, Desktop vs CLI paths | `vibe-agent-toolkit:install` |
42
42
  | `vat audit`, `--compat`, CI validation | `vibe-agent-toolkit:audit` |
43
+ | `vat claude org`, Admin API, org users/cost/usage/skills, ANTHROPIC_ADMIN_API_KEY | `vibe-agent-toolkit:org-admin` |
43
44
  | VAT behaves unexpectedly, debugging VAT, testing local VAT changes, VAT_ROOT_DIR | `vibe-agent-toolkit:debugging` |
44
45
 
45
46
  ## Agent Archetypes (Quick Reference)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibe-agent-toolkit/vat-development-agents",
3
- "version": "0.1.22-rc.2",
3
+ "version": "0.1.22",
4
4
  "description": "VAT development agents - dogfooding the vibe-agent-toolkit",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -64,13 +64,13 @@
64
64
  "postinstall": "vat claude plugin install --npm-postinstall || exit 0"
65
65
  },
66
66
  "dependencies": {
67
- "@vibe-agent-toolkit/agent-schema": "0.1.22-rc.2",
68
- "@vibe-agent-toolkit/cli": "0.1.22-rc.2",
67
+ "@vibe-agent-toolkit/agent-schema": "0.1.22",
68
+ "@vibe-agent-toolkit/cli": "0.1.22",
69
69
  "yaml": "^2.8.2"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@types/node": "^25.0.3",
73
- "@vibe-agent-toolkit/resource-compiler": "0.1.22-rc.2",
73
+ "@vibe-agent-toolkit/resource-compiler": "0.1.22",
74
74
  "ts-patch": "^3.2.1",
75
75
  "typescript": "^5.7.3"
76
76
  },