claudient 0.1.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/.claude-plugin/plugin.json +42 -0
- package/CONTEXT.md +58 -0
- package/README.md +165 -0
- package/agents/build-resolvers/de/python-resolver.md +64 -0
- package/agents/build-resolvers/de/typescript-resolver.md +65 -0
- package/agents/build-resolvers/es/python-resolver.md +64 -0
- package/agents/build-resolvers/es/typescript-resolver.md +65 -0
- package/agents/build-resolvers/fr/python-resolver.md +64 -0
- package/agents/build-resolvers/fr/typescript-resolver.md +65 -0
- package/agents/build-resolvers/nl/python-resolver.md +64 -0
- package/agents/build-resolvers/nl/typescript-resolver.md +65 -0
- package/agents/build-resolvers/python-resolver.md +62 -0
- package/agents/build-resolvers/typescript-resolver.md +63 -0
- package/agents/core/architect.md +64 -0
- package/agents/core/code-reviewer.md +78 -0
- package/agents/core/de/architect.md +66 -0
- package/agents/core/de/code-reviewer.md +80 -0
- package/agents/core/de/planner.md +63 -0
- package/agents/core/de/security-reviewer.md +93 -0
- package/agents/core/es/architect.md +66 -0
- package/agents/core/es/code-reviewer.md +80 -0
- package/agents/core/es/planner.md +63 -0
- package/agents/core/es/security-reviewer.md +93 -0
- package/agents/core/fr/architect.md +66 -0
- package/agents/core/fr/code-reviewer.md +80 -0
- package/agents/core/fr/planner.md +63 -0
- package/agents/core/fr/security-reviewer.md +93 -0
- package/agents/core/nl/architect.md +66 -0
- package/agents/core/nl/code-reviewer.md +80 -0
- package/agents/core/nl/planner.md +63 -0
- package/agents/core/nl/security-reviewer.md +93 -0
- package/agents/core/planner.md +61 -0
- package/agents/core/security-reviewer.md +91 -0
- package/guides/agent-orchestration.md +231 -0
- package/guides/de/agent-orchestration.md +174 -0
- package/guides/de/getting-started.md +164 -0
- package/guides/de/hooks-cookbook.md +160 -0
- package/guides/de/memory-management.md +153 -0
- package/guides/de/security.md +180 -0
- package/guides/de/skill-authoring.md +214 -0
- package/guides/de/token-optimization.md +156 -0
- package/guides/es/agent-orchestration.md +174 -0
- package/guides/es/getting-started.md +164 -0
- package/guides/es/hooks-cookbook.md +160 -0
- package/guides/es/memory-management.md +153 -0
- package/guides/es/security.md +180 -0
- package/guides/es/skill-authoring.md +214 -0
- package/guides/es/token-optimization.md +156 -0
- package/guides/fr/agent-orchestration.md +174 -0
- package/guides/fr/getting-started.md +164 -0
- package/guides/fr/hooks-cookbook.md +227 -0
- package/guides/fr/memory-management.md +169 -0
- package/guides/fr/security.md +180 -0
- package/guides/fr/skill-authoring.md +214 -0
- package/guides/fr/token-optimization.md +158 -0
- package/guides/getting-started.md +164 -0
- package/guides/hooks-cookbook.md +423 -0
- package/guides/memory-management.md +192 -0
- package/guides/nl/agent-orchestration.md +174 -0
- package/guides/nl/getting-started.md +164 -0
- package/guides/nl/hooks-cookbook.md +160 -0
- package/guides/nl/memory-management.md +153 -0
- package/guides/nl/security.md +180 -0
- package/guides/nl/skill-authoring.md +214 -0
- package/guides/nl/token-optimization.md +156 -0
- package/guides/security.md +229 -0
- package/guides/skill-authoring.md +226 -0
- package/guides/token-optimization.md +169 -0
- package/hooks/lifecycle/cost-tracker.md +49 -0
- package/hooks/lifecycle/cost-tracker.sh +59 -0
- package/hooks/lifecycle/pre-compact-save.md +56 -0
- package/hooks/lifecycle/pre-compact-save.sh +37 -0
- package/hooks/lifecycle/session-start.md +50 -0
- package/hooks/lifecycle/session-start.sh +47 -0
- package/hooks/post-tool-use/audit-log.md +53 -0
- package/hooks/post-tool-use/audit-log.sh +53 -0
- package/hooks/post-tool-use/prettier.md +53 -0
- package/hooks/post-tool-use/prettier.sh +49 -0
- package/hooks/pre-tool-use/block-dangerous.md +48 -0
- package/hooks/pre-tool-use/block-dangerous.sh +76 -0
- package/hooks/pre-tool-use/git-push-confirm.md +46 -0
- package/hooks/pre-tool-use/git-push-confirm.sh +36 -0
- package/mcp/configs/github.json +11 -0
- package/mcp/configs/postgres.json +11 -0
- package/mcp/de/recommended-servers.md +170 -0
- package/mcp/es/recommended-servers.md +170 -0
- package/mcp/fr/recommended-servers.md +170 -0
- package/mcp/nl/recommended-servers.md +170 -0
- package/mcp/recommended-servers.md +168 -0
- package/package.json +45 -0
- package/prompts/project-starters/de/fastapi-project.md +62 -0
- package/prompts/project-starters/de/nextjs-project.md +82 -0
- package/prompts/project-starters/es/fastapi-project.md +62 -0
- package/prompts/project-starters/es/nextjs-project.md +82 -0
- package/prompts/project-starters/fastapi-project.md +60 -0
- package/prompts/project-starters/fr/fastapi-project.md +62 -0
- package/prompts/project-starters/fr/nextjs-project.md +82 -0
- package/prompts/project-starters/nextjs-project.md +80 -0
- package/prompts/project-starters/nl/fastapi-project.md +62 -0
- package/prompts/project-starters/nl/nextjs-project.md +82 -0
- package/prompts/system-prompts/ai-product.md +80 -0
- package/prompts/system-prompts/data-pipeline.md +76 -0
- package/prompts/system-prompts/de/ai-product.md +82 -0
- package/prompts/system-prompts/de/data-pipeline.md +78 -0
- package/prompts/system-prompts/de/saas-backend.md +71 -0
- package/prompts/system-prompts/es/ai-product.md +82 -0
- package/prompts/system-prompts/es/data-pipeline.md +78 -0
- package/prompts/system-prompts/es/saas-backend.md +71 -0
- package/prompts/system-prompts/fr/ai-product.md +82 -0
- package/prompts/system-prompts/fr/data-pipeline.md +78 -0
- package/prompts/system-prompts/fr/saas-backend.md +71 -0
- package/prompts/system-prompts/nl/ai-product.md +82 -0
- package/prompts/system-prompts/nl/data-pipeline.md +78 -0
- package/prompts/system-prompts/nl/saas-backend.md +71 -0
- package/prompts/system-prompts/saas-backend.md +69 -0
- package/prompts/task-specific/changelog.md +81 -0
- package/prompts/task-specific/de/changelog.md +83 -0
- package/prompts/task-specific/de/debugging.md +78 -0
- package/prompts/task-specific/de/pr-description.md +69 -0
- package/prompts/task-specific/debugging.md +76 -0
- package/prompts/task-specific/es/changelog.md +83 -0
- package/prompts/task-specific/es/debugging.md +78 -0
- package/prompts/task-specific/es/pr-description.md +69 -0
- package/prompts/task-specific/fr/changelog.md +83 -0
- package/prompts/task-specific/fr/debugging.md +78 -0
- package/prompts/task-specific/fr/pr-description.md +69 -0
- package/prompts/task-specific/nl/changelog.md +83 -0
- package/prompts/task-specific/nl/debugging.md +78 -0
- package/prompts/task-specific/nl/pr-description.md +69 -0
- package/prompts/task-specific/pr-description.md +67 -0
- package/rules/common/coding-style.md +45 -0
- package/rules/common/de/coding-style.md +47 -0
- package/rules/common/de/git.md +48 -0
- package/rules/common/de/performance.md +40 -0
- package/rules/common/de/security.md +45 -0
- package/rules/common/de/testing.md +45 -0
- package/rules/common/es/coding-style.md +47 -0
- package/rules/common/es/git.md +48 -0
- package/rules/common/es/performance.md +40 -0
- package/rules/common/es/security.md +45 -0
- package/rules/common/es/testing.md +45 -0
- package/rules/common/fr/coding-style.md +47 -0
- package/rules/common/fr/git.md +48 -0
- package/rules/common/fr/performance.md +40 -0
- package/rules/common/fr/security.md +45 -0
- package/rules/common/fr/testing.md +45 -0
- package/rules/common/git.md +46 -0
- package/rules/common/nl/coding-style.md +47 -0
- package/rules/common/nl/git.md +48 -0
- package/rules/common/nl/performance.md +40 -0
- package/rules/common/nl/security.md +45 -0
- package/rules/common/nl/testing.md +45 -0
- package/rules/common/performance.md +38 -0
- package/rules/common/security.md +43 -0
- package/rules/common/testing.md +43 -0
- package/rules/language-specific/de/go.md +48 -0
- package/rules/language-specific/de/python.md +38 -0
- package/rules/language-specific/de/typescript.md +51 -0
- package/rules/language-specific/es/go.md +48 -0
- package/rules/language-specific/es/python.md +38 -0
- package/rules/language-specific/es/typescript.md +51 -0
- package/rules/language-specific/fr/go.md +48 -0
- package/rules/language-specific/fr/python.md +38 -0
- package/rules/language-specific/fr/typescript.md +51 -0
- package/rules/language-specific/go.md +46 -0
- package/rules/language-specific/nl/go.md +48 -0
- package/rules/language-specific/nl/python.md +38 -0
- package/rules/language-specific/nl/typescript.md +51 -0
- package/rules/language-specific/python.md +36 -0
- package/rules/language-specific/typescript.md +49 -0
- package/scripts/cli.js +161 -0
- package/scripts/link-skills.sh +35 -0
- package/scripts/list-skills.sh +34 -0
- package/skills/ai-engineering/agent-construction.md +285 -0
- package/skills/ai-engineering/claude-api.md +248 -0
- package/skills/ai-engineering/de/agent-construction.md +287 -0
- package/skills/ai-engineering/de/claude-api.md +250 -0
- package/skills/ai-engineering/es/agent-construction.md +287 -0
- package/skills/ai-engineering/es/claude-api.md +250 -0
- package/skills/ai-engineering/fr/agent-construction.md +287 -0
- package/skills/ai-engineering/fr/claude-api.md +250 -0
- package/skills/ai-engineering/nl/agent-construction.md +287 -0
- package/skills/ai-engineering/nl/claude-api.md +250 -0
- package/skills/backend/dotnet/csharp.md +304 -0
- package/skills/backend/dotnet/de/csharp.md +306 -0
- package/skills/backend/dotnet/es/csharp.md +306 -0
- package/skills/backend/dotnet/fr/csharp.md +306 -0
- package/skills/backend/dotnet/nl/csharp.md +306 -0
- package/skills/backend/go/de/go.md +307 -0
- package/skills/backend/go/es/go.md +307 -0
- package/skills/backend/go/fr/go.md +307 -0
- package/skills/backend/go/go.md +305 -0
- package/skills/backend/go/nl/go.md +307 -0
- package/skills/backend/nodejs/de/nestjs.md +274 -0
- package/skills/backend/nodejs/de/nextjs.md +222 -0
- package/skills/backend/nodejs/es/nestjs.md +274 -0
- package/skills/backend/nodejs/es/nextjs.md +222 -0
- package/skills/backend/nodejs/fr/nestjs.md +274 -0
- package/skills/backend/nodejs/fr/nextjs.md +222 -0
- package/skills/backend/nodejs/nestjs.md +272 -0
- package/skills/backend/nodejs/nextjs.md +220 -0
- package/skills/backend/nodejs/nl/nestjs.md +274 -0
- package/skills/backend/nodejs/nl/nextjs.md +222 -0
- package/skills/backend/python/de/django.md +285 -0
- package/skills/backend/python/de/fastapi.md +244 -0
- package/skills/backend/python/django.md +283 -0
- package/skills/backend/python/es/django.md +285 -0
- package/skills/backend/python/es/fastapi.md +244 -0
- package/skills/backend/python/fastapi.md +242 -0
- package/skills/backend/python/fr/django.md +285 -0
- package/skills/backend/python/fr/fastapi.md +244 -0
- package/skills/backend/python/nl/django.md +285 -0
- package/skills/backend/python/nl/fastapi.md +244 -0
- package/skills/data-ml/dbt-data-pipelines.md +155 -0
- package/skills/data-ml/de/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/de/pandas-polars.md +147 -0
- package/skills/data-ml/de/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/es/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/es/pandas-polars.md +147 -0
- package/skills/data-ml/es/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/fr/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/fr/pandas-polars.md +147 -0
- package/skills/data-ml/fr/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/nl/dbt-data-pipelines.md +157 -0
- package/skills/data-ml/nl/pandas-polars.md +147 -0
- package/skills/data-ml/nl/pytorch-tensorflow.md +171 -0
- package/skills/data-ml/pandas-polars.md +145 -0
- package/skills/data-ml/pytorch-tensorflow.md +169 -0
- package/skills/database/de/graphql.md +181 -0
- package/skills/database/es/graphql.md +181 -0
- package/skills/database/fr/graphql.md +181 -0
- package/skills/database/graphql.md +179 -0
- package/skills/database/nl/graphql.md +181 -0
- package/skills/devops-infra/de/docker.md +133 -0
- package/skills/devops-infra/de/github-actions.md +179 -0
- package/skills/devops-infra/de/kubernetes.md +129 -0
- package/skills/devops-infra/de/terraform.md +130 -0
- package/skills/devops-infra/docker.md +131 -0
- package/skills/devops-infra/es/docker.md +133 -0
- package/skills/devops-infra/es/github-actions.md +179 -0
- package/skills/devops-infra/es/kubernetes.md +129 -0
- package/skills/devops-infra/es/terraform.md +130 -0
- package/skills/devops-infra/fr/docker.md +133 -0
- package/skills/devops-infra/fr/github-actions.md +179 -0
- package/skills/devops-infra/fr/kubernetes.md +129 -0
- package/skills/devops-infra/fr/terraform.md +130 -0
- package/skills/devops-infra/github-actions.md +177 -0
- package/skills/devops-infra/kubernetes.md +127 -0
- package/skills/devops-infra/nl/docker.md +133 -0
- package/skills/devops-infra/nl/github-actions.md +179 -0
- package/skills/devops-infra/nl/kubernetes.md +129 -0
- package/skills/devops-infra/nl/terraform.md +130 -0
- package/skills/devops-infra/terraform.md +128 -0
- package/skills/finance-payments/de/stripe.md +187 -0
- package/skills/finance-payments/es/stripe.md +187 -0
- package/skills/finance-payments/fr/stripe.md +187 -0
- package/skills/finance-payments/nl/stripe.md +187 -0
- package/skills/finance-payments/stripe.md +185 -0
- package/workflows/code-review.md +151 -0
- package/workflows/de/code-review.md +153 -0
- package/workflows/de/debugging-session.md +146 -0
- package/workflows/de/feature-development.md +155 -0
- package/workflows/de/new-project-bootstrap.md +175 -0
- package/workflows/de/refactor-safely.md +150 -0
- package/workflows/debugging-session.md +144 -0
- package/workflows/es/code-review.md +153 -0
- package/workflows/es/debugging-session.md +146 -0
- package/workflows/es/feature-development.md +155 -0
- package/workflows/es/new-project-bootstrap.md +175 -0
- package/workflows/es/refactor-safely.md +150 -0
- package/workflows/feature-development.md +153 -0
- package/workflows/fr/code-review.md +153 -0
- package/workflows/fr/debugging-session.md +146 -0
- package/workflows/fr/feature-development.md +155 -0
- package/workflows/fr/new-project-bootstrap.md +175 -0
- package/workflows/fr/refactor-safely.md +150 -0
- package/workflows/new-project-bootstrap.md +173 -0
- package/workflows/nl/code-review.md +153 -0
- package/workflows/nl/debugging-session.md +146 -0
- package/workflows/nl/feature-development.md +155 -0
- package/workflows/nl/new-project-bootstrap.md +175 -0
- package/workflows/nl/refactor-safely.md +150 -0
- package/workflows/refactor-safely.md +148 -0
package/scripts/cli.js
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const os = require('os')
|
|
6
|
+
|
|
7
|
+
const REPO_ROOT = path.resolve(__dirname, '..')
|
|
8
|
+
const CLAUDE_DIR = path.join(os.homedir(), '.claude')
|
|
9
|
+
const SKILLS_DEST = path.join(CLAUDE_DIR, 'skills')
|
|
10
|
+
|
|
11
|
+
const VALID_CATEGORIES = [
|
|
12
|
+
'backend',
|
|
13
|
+
'devops-infra',
|
|
14
|
+
'data-ml',
|
|
15
|
+
'database',
|
|
16
|
+
'finance-payments',
|
|
17
|
+
'ai-engineering',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
function usage() {
|
|
21
|
+
console.log(`
|
|
22
|
+
claudient — Claude Code knowledge system installer
|
|
23
|
+
|
|
24
|
+
Usage:
|
|
25
|
+
npx claudient add <category> Add skills from a specific category
|
|
26
|
+
npx claudient add all Add all skills
|
|
27
|
+
npx claudient list List available categories and skills
|
|
28
|
+
npx claudient help Show this help
|
|
29
|
+
|
|
30
|
+
Categories:
|
|
31
|
+
${VALID_CATEGORIES.join('\n ')}
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
npx claudient add backend
|
|
35
|
+
npx claudient add ai-engineering
|
|
36
|
+
npx claudient add all
|
|
37
|
+
`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function checkClaudeInstalled() {
|
|
41
|
+
if (!fs.existsSync(CLAUDE_DIR)) {
|
|
42
|
+
console.error(`
|
|
43
|
+
Error: ~/.claude directory not found.
|
|
44
|
+
|
|
45
|
+
Claude Code must be installed first. Install it from:
|
|
46
|
+
https://claude.ai/code
|
|
47
|
+
|
|
48
|
+
Or install the CLI:
|
|
49
|
+
npm install -g @anthropic-ai/claude-code
|
|
50
|
+
`)
|
|
51
|
+
process.exit(1)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function copyDir(src, dest, prefix = '') {
|
|
56
|
+
if (!fs.existsSync(src)) return 0
|
|
57
|
+
fs.mkdirSync(dest, { recursive: true })
|
|
58
|
+
|
|
59
|
+
let count = 0
|
|
60
|
+
const entries = fs.readdirSync(src, { withFileTypes: true })
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
const srcPath = path.join(src, entry.name)
|
|
63
|
+
const destPath = path.join(dest, entry.name)
|
|
64
|
+
if (entry.isDirectory()) {
|
|
65
|
+
count += copyDir(srcPath, destPath, prefix + entry.name + '/')
|
|
66
|
+
} else if (entry.name.endsWith('.md')) {
|
|
67
|
+
fs.copyFileSync(srcPath, destPath)
|
|
68
|
+
console.log(` + ${prefix}${entry.name}`)
|
|
69
|
+
count++
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return count
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function addCategory(category) {
|
|
76
|
+
checkClaudeInstalled()
|
|
77
|
+
|
|
78
|
+
if (category === 'all') {
|
|
79
|
+
let total = 0
|
|
80
|
+
console.log(`Installing all Claudient skills to ${SKILLS_DEST}...\n`)
|
|
81
|
+
for (const cat of VALID_CATEGORIES) {
|
|
82
|
+
const src = path.join(REPO_ROOT, 'skills', cat)
|
|
83
|
+
const dest = path.join(SKILLS_DEST, cat)
|
|
84
|
+
const count = copyDir(src, dest, cat + '/')
|
|
85
|
+
if (count > 0) console.log(` ✓ ${cat} (${count} files)`)
|
|
86
|
+
}
|
|
87
|
+
console.log(`\nDone. Skills installed to: ${SKILLS_DEST}`)
|
|
88
|
+
console.log('Restart Claude Code to activate the new skills.')
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (!VALID_CATEGORIES.includes(category)) {
|
|
93
|
+
console.error(`Unknown category: "${category}"`)
|
|
94
|
+
console.error(`Valid categories: ${VALID_CATEGORIES.join(', ')}`)
|
|
95
|
+
process.exit(1)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const src = path.join(REPO_ROOT, 'skills', category)
|
|
99
|
+
if (!fs.existsSync(src)) {
|
|
100
|
+
console.error(`Category directory not found: ${src}`)
|
|
101
|
+
process.exit(1)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const dest = path.join(SKILLS_DEST, category)
|
|
105
|
+
console.log(`Installing ${category} skills to ${dest}...\n`)
|
|
106
|
+
const count = copyDir(src, dest, category + '/')
|
|
107
|
+
console.log(`\nInstalled ${count} skill file(s).`)
|
|
108
|
+
console.log('Restart Claude Code to activate the new skills.')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function listSkills() {
|
|
112
|
+
console.log('Available Claudient skill categories:\n')
|
|
113
|
+
for (const cat of VALID_CATEGORIES) {
|
|
114
|
+
const catDir = path.join(REPO_ROOT, 'skills', cat)
|
|
115
|
+
if (!fs.existsSync(catDir)) continue
|
|
116
|
+
const files = getSkillFiles(catDir, '')
|
|
117
|
+
console.log(`${cat}/ (${files.length} skills)`)
|
|
118
|
+
for (const f of files) {
|
|
119
|
+
console.log(` ${f}`)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getSkillFiles(dir, prefix) {
|
|
125
|
+
const results = []
|
|
126
|
+
if (!fs.existsSync(dir)) return results
|
|
127
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
128
|
+
const p = path.join(dir, entry.name)
|
|
129
|
+
if (entry.isDirectory()) {
|
|
130
|
+
results.push(...getSkillFiles(p, prefix + entry.name + '/'))
|
|
131
|
+
} else if (entry.name.endsWith('.md')) {
|
|
132
|
+
results.push(prefix + entry.name)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return results
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const [, , command, ...args] = process.argv
|
|
139
|
+
|
|
140
|
+
switch (command) {
|
|
141
|
+
case 'add':
|
|
142
|
+
if (!args[0]) {
|
|
143
|
+
console.error('Usage: claudient add <category|all>')
|
|
144
|
+
process.exit(1)
|
|
145
|
+
}
|
|
146
|
+
addCategory(args[0])
|
|
147
|
+
break
|
|
148
|
+
case 'list':
|
|
149
|
+
listSkills()
|
|
150
|
+
break
|
|
151
|
+
case 'help':
|
|
152
|
+
case '--help':
|
|
153
|
+
case '-h':
|
|
154
|
+
case undefined:
|
|
155
|
+
usage()
|
|
156
|
+
break
|
|
157
|
+
default:
|
|
158
|
+
console.error(`Unknown command: ${command}`)
|
|
159
|
+
usage()
|
|
160
|
+
process.exit(1)
|
|
161
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# link-skills.sh — symlink all Claudient skills to ~/.claude/skills for local development
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
7
|
+
CLAUDE_DIR="${HOME}/.claude"
|
|
8
|
+
SKILLS_DEST="${CLAUDE_DIR}/skills"
|
|
9
|
+
|
|
10
|
+
if [ ! -d "${CLAUDE_DIR}" ]; then
|
|
11
|
+
echo "Error: ~/.claude not found. Install Claude Code first."
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
mkdir -p "${SKILLS_DEST}"
|
|
16
|
+
|
|
17
|
+
linked=0
|
|
18
|
+
for category_dir in "${REPO_ROOT}/skills"/*/; do
|
|
19
|
+
category="$(basename "${category_dir}")"
|
|
20
|
+
dest="${SKILLS_DEST}/${category}"
|
|
21
|
+
|
|
22
|
+
if [ -L "${dest}" ]; then
|
|
23
|
+
echo " ~ ${category}/ (already linked)"
|
|
24
|
+
elif [ -d "${dest}" ]; then
|
|
25
|
+
echo " ! ${category}/ (exists as real dir — remove it first to symlink)"
|
|
26
|
+
else
|
|
27
|
+
ln -s "${category_dir}" "${dest}"
|
|
28
|
+
echo " + ${category}/ → ${category_dir}"
|
|
29
|
+
((linked++))
|
|
30
|
+
fi
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Done. Linked ${linked} new category symlink(s) to ${SKILLS_DEST}"
|
|
35
|
+
echo "Restart Claude Code to pick up the skills."
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# list-skills.sh — enumerate all skill .md files in the Claudient repo
|
|
3
|
+
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
7
|
+
SKILLS_DIR="${REPO_ROOT}/skills"
|
|
8
|
+
|
|
9
|
+
total=0
|
|
10
|
+
|
|
11
|
+
for category_dir in "${SKILLS_DIR}"/*/; do
|
|
12
|
+
category="$(basename "${category_dir}")"
|
|
13
|
+
files=()
|
|
14
|
+
|
|
15
|
+
while IFS= read -r -d '' file; do
|
|
16
|
+
# Skip translation directories (fr/, de/, nl/, es/)
|
|
17
|
+
rel="${file#${category_dir}}"
|
|
18
|
+
if [[ "${rel}" =~ ^(fr|de|nl|es)/ ]]; then
|
|
19
|
+
continue
|
|
20
|
+
fi
|
|
21
|
+
files+=("${rel}")
|
|
22
|
+
((total++))
|
|
23
|
+
done < <(find "${category_dir}" -name "*.md" -not -path "*/fr/*" -not -path "*/de/*" -not -path "*/nl/*" -not -path "*/es/*" -print0 | sort -z)
|
|
24
|
+
|
|
25
|
+
if [ ${#files[@]} -gt 0 ]; then
|
|
26
|
+
echo "${category}/ (${#files[@]})"
|
|
27
|
+
for f in "${files[@]}"; do
|
|
28
|
+
echo " ${category}/${f}"
|
|
29
|
+
done
|
|
30
|
+
fi
|
|
31
|
+
done
|
|
32
|
+
|
|
33
|
+
echo ""
|
|
34
|
+
echo "Total: ${total} skill(s)"
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
# Agent Construction Skill
|
|
2
|
+
|
|
3
|
+
## When to activate
|
|
4
|
+
- Designing a multi-agent system with Claude (orchestrator + subagents)
|
|
5
|
+
- Building a Claude-powered agent that uses tools across multiple turns
|
|
6
|
+
- Designing memory for a long-running agent (in-context vs. external)
|
|
7
|
+
- Handling agent errors, retries, and stopping conditions
|
|
8
|
+
- Implementing agent handoffs between specialized subagents
|
|
9
|
+
|
|
10
|
+
## When NOT to use
|
|
11
|
+
- Single-turn Claude API calls — the Claude API skill is sufficient
|
|
12
|
+
- Simple chatbots without tool use or autonomous decision-making
|
|
13
|
+
- LangChain/LlamaIndex abstractions — address the abstraction layer directly
|
|
14
|
+
|
|
15
|
+
## Instructions
|
|
16
|
+
|
|
17
|
+
### Agent architecture patterns
|
|
18
|
+
|
|
19
|
+
**Single agent with tools** — one Claude instance, multiple tools, loops until task is done:
|
|
20
|
+
```
|
|
21
|
+
User → Agent → [Tool A] → [Tool B] → Agent → User
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Orchestrator + subagents** — one parent spawns specialized children:
|
|
25
|
+
```
|
|
26
|
+
User → Orchestrator → [ResearchAgent] → [WriterAgent] → Orchestrator → User
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Pipeline** — agents hand off results in sequence:
|
|
30
|
+
```
|
|
31
|
+
User → Agent1(classify) → Agent2(extract) → Agent3(generate) → User
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Choose the simplest architecture that solves the problem. Single agent with tools handles most cases.
|
|
35
|
+
|
|
36
|
+
### Tool design
|
|
37
|
+
```python
|
|
38
|
+
# Tool definitions for multi-turn agent loop
|
|
39
|
+
tools = [
|
|
40
|
+
{
|
|
41
|
+
"name": "search_web",
|
|
42
|
+
"description": "Search the web for current information. Use when you need facts not in your training data.",
|
|
43
|
+
"input_schema": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"properties": {
|
|
46
|
+
"query": {"type": "string", "description": "Search query"}
|
|
47
|
+
},
|
|
48
|
+
"required": ["query"]
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "read_file",
|
|
53
|
+
"description": "Read contents of a file by path.",
|
|
54
|
+
"input_schema": {
|
|
55
|
+
"type": "object",
|
|
56
|
+
"properties": {
|
|
57
|
+
"path": {"type": "string", "description": "Absolute file path"}
|
|
58
|
+
},
|
|
59
|
+
"required": ["path"]
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "write_file",
|
|
64
|
+
"description": "Write content to a file. Creates the file if it doesn't exist.",
|
|
65
|
+
"input_schema": {
|
|
66
|
+
"type": "object",
|
|
67
|
+
"properties": {
|
|
68
|
+
"path": {"type": "string"},
|
|
69
|
+
"content": {"type": "string"}
|
|
70
|
+
},
|
|
71
|
+
"required": ["path", "content"]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Tool design rules:
|
|
78
|
+
- Description must tell Claude WHEN to use it, not just what it does
|
|
79
|
+
- Keep `input_schema` minimal — only required fields, no optional noise
|
|
80
|
+
- Return structured data (JSON), not prose, so Claude can use it reliably
|
|
81
|
+
- One tool per action — don't bundle read+write into one tool
|
|
82
|
+
|
|
83
|
+
### Agent loop
|
|
84
|
+
```python
|
|
85
|
+
import anthropic
|
|
86
|
+
import json
|
|
87
|
+
|
|
88
|
+
client = anthropic.Anthropic()
|
|
89
|
+
|
|
90
|
+
def run_agent(task: str, max_iterations: int = 20) -> str:
|
|
91
|
+
messages = [{"role": "user", "content": task}]
|
|
92
|
+
|
|
93
|
+
for iteration in range(max_iterations):
|
|
94
|
+
response = client.messages.create(
|
|
95
|
+
model="claude-sonnet-4-6",
|
|
96
|
+
max_tokens=4096,
|
|
97
|
+
system=AGENT_SYSTEM_PROMPT,
|
|
98
|
+
tools=tools,
|
|
99
|
+
messages=messages,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
# Append assistant's response
|
|
103
|
+
messages.append({"role": "assistant", "content": response.content})
|
|
104
|
+
|
|
105
|
+
if response.stop_reason == "end_turn":
|
|
106
|
+
# Extract final text response
|
|
107
|
+
return next(b.text for b in response.content if hasattr(b, "text"))
|
|
108
|
+
|
|
109
|
+
if response.stop_reason == "tool_use":
|
|
110
|
+
# Execute all tool calls in this response
|
|
111
|
+
tool_results = []
|
|
112
|
+
for block in response.content:
|
|
113
|
+
if block.type == "tool_use":
|
|
114
|
+
result = execute_tool(block.name, block.input)
|
|
115
|
+
tool_results.append({
|
|
116
|
+
"type": "tool_result",
|
|
117
|
+
"tool_use_id": block.id,
|
|
118
|
+
"content": json.dumps(result) if not isinstance(result, str) else result
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
messages.append({"role": "user", "content": tool_results})
|
|
122
|
+
else:
|
|
123
|
+
# Unexpected stop reason
|
|
124
|
+
break
|
|
125
|
+
|
|
126
|
+
raise RuntimeError(f"Agent exceeded {max_iterations} iterations without completing")
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def execute_tool(name: str, inputs: dict) -> any:
|
|
130
|
+
match name:
|
|
131
|
+
case "search_web":
|
|
132
|
+
return search(inputs["query"])
|
|
133
|
+
case "read_file":
|
|
134
|
+
return Path(inputs["path"]).read_text()
|
|
135
|
+
case "write_file":
|
|
136
|
+
Path(inputs["path"]).write_text(inputs["content"])
|
|
137
|
+
return {"success": True, "path": inputs["path"]}
|
|
138
|
+
case _:
|
|
139
|
+
return {"error": f"Unknown tool: {name}"}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### System prompt for agents
|
|
143
|
+
```
|
|
144
|
+
AGENT_SYSTEM_PROMPT = """You are an autonomous agent completing tasks step by step.
|
|
145
|
+
|
|
146
|
+
Approach:
|
|
147
|
+
1. Analyze the task before acting
|
|
148
|
+
2. Use the minimum tools necessary
|
|
149
|
+
3. Check your work before declaring done
|
|
150
|
+
4. If a tool returns an error, diagnose and retry once — if it fails again, report the error
|
|
151
|
+
|
|
152
|
+
Stopping conditions — declare "DONE: <result>" when:
|
|
153
|
+
- The task is fully complete
|
|
154
|
+
- You've hit an unrecoverable error after retrying
|
|
155
|
+
- You've been asked to do something harmful or impossible
|
|
156
|
+
|
|
157
|
+
Never loop more than 3 times on the same tool call with the same inputs.
|
|
158
|
+
"""
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Memory patterns
|
|
162
|
+
|
|
163
|
+
**In-context memory** (messages array) — for single session, small state:
|
|
164
|
+
```python
|
|
165
|
+
# Summarize when context grows large
|
|
166
|
+
if count_tokens(messages) > 150_000:
|
|
167
|
+
summary = summarize_messages(messages[:-5]) # keep last 5 turns
|
|
168
|
+
messages = [
|
|
169
|
+
{"role": "user", "content": f"[Previous context summary]\n{summary}"},
|
|
170
|
+
{"role": "assistant", "content": "Understood. Continuing from where we left off."},
|
|
171
|
+
*messages[-5:]
|
|
172
|
+
]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
**External memory** (for multi-session agents):
|
|
176
|
+
```python
|
|
177
|
+
# Simple file-based memory
|
|
178
|
+
class AgentMemory:
|
|
179
|
+
def __init__(self, path: str):
|
|
180
|
+
self.path = Path(path)
|
|
181
|
+
self.data = json.loads(self.path.read_text()) if self.path.exists() else {}
|
|
182
|
+
|
|
183
|
+
def remember(self, key: str, value: any):
|
|
184
|
+
self.data[key] = {"value": value, "timestamp": datetime.utcnow().isoformat()}
|
|
185
|
+
self.path.write_text(json.dumps(self.data, indent=2))
|
|
186
|
+
|
|
187
|
+
def recall(self, key: str) -> any:
|
|
188
|
+
entry = self.data.get(key)
|
|
189
|
+
return entry["value"] if entry else None
|
|
190
|
+
|
|
191
|
+
def as_context(self) -> str:
|
|
192
|
+
if not self.data:
|
|
193
|
+
return ""
|
|
194
|
+
lines = [f"- {k}: {v['value']}" for k, v in self.data.items()]
|
|
195
|
+
return "Known context:\n" + "\n".join(lines)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Orchestrator pattern
|
|
199
|
+
```python
|
|
200
|
+
def orchestrate(task: str) -> str:
|
|
201
|
+
# Step 1: Planning agent decomposes the task
|
|
202
|
+
plan = run_subagent(
|
|
203
|
+
model="claude-sonnet-4-6",
|
|
204
|
+
system="You are a planner. Decompose tasks into numbered steps.",
|
|
205
|
+
task=f"Decompose this task into steps: {task}",
|
|
206
|
+
tools=[] # No tools needed for planning
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Step 2: Execute each step with specialized agents
|
|
210
|
+
results = []
|
|
211
|
+
for step in parse_steps(plan):
|
|
212
|
+
agent_type = classify_step(step) # "research" | "code" | "write"
|
|
213
|
+
result = run_subagent(
|
|
214
|
+
model=agent_model(agent_type),
|
|
215
|
+
system=agent_system_prompt(agent_type),
|
|
216
|
+
task=step,
|
|
217
|
+
tools=agent_tools(agent_type),
|
|
218
|
+
context="\n".join(results) # Give context from previous steps
|
|
219
|
+
)
|
|
220
|
+
results.append(f"Step result: {result}")
|
|
221
|
+
|
|
222
|
+
# Step 3: Synthesis agent combines results
|
|
223
|
+
return run_subagent(
|
|
224
|
+
model="claude-sonnet-4-6",
|
|
225
|
+
system="You are a synthesizer. Combine step results into a final answer.",
|
|
226
|
+
task=f"Original task: {task}\n\nStep results:\n" + "\n".join(results),
|
|
227
|
+
tools=[]
|
|
228
|
+
)
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Error handling and stopping conditions
|
|
232
|
+
```python
|
|
233
|
+
class AgentError(Exception):
|
|
234
|
+
pass
|
|
235
|
+
|
|
236
|
+
class MaxIterationsError(AgentError):
|
|
237
|
+
pass
|
|
238
|
+
|
|
239
|
+
class ToolFailureError(AgentError):
|
|
240
|
+
pass
|
|
241
|
+
|
|
242
|
+
def execute_tool_safe(name: str, inputs: dict, consecutive_failures: dict) -> dict:
|
|
243
|
+
try:
|
|
244
|
+
result = execute_tool(name, inputs)
|
|
245
|
+
consecutive_failures[name] = 0
|
|
246
|
+
return {"success": True, "result": result}
|
|
247
|
+
except Exception as e:
|
|
248
|
+
consecutive_failures[name] = consecutive_failures.get(name, 0) + 1
|
|
249
|
+
if consecutive_failures[name] >= 3:
|
|
250
|
+
raise ToolFailureError(f"Tool {name} failed 3 consecutive times: {e}")
|
|
251
|
+
return {"success": False, "error": str(e), "retry": True}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Handoff pattern
|
|
255
|
+
```python
|
|
256
|
+
# Parent agent passes context explicitly — subagents have no session memory
|
|
257
|
+
def handoff_to_specialist(context: dict, task: str, specialist: str) -> str:
|
|
258
|
+
handoff_prompt = f"""
|
|
259
|
+
Context from orchestrator:
|
|
260
|
+
{json.dumps(context, indent=2)}
|
|
261
|
+
|
|
262
|
+
Your task:
|
|
263
|
+
{task}
|
|
264
|
+
"""
|
|
265
|
+
return run_subagent(
|
|
266
|
+
system=SPECIALIST_PROMPTS[specialist],
|
|
267
|
+
task=handoff_prompt,
|
|
268
|
+
tools=SPECIALIST_TOOLS[specialist]
|
|
269
|
+
)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Example
|
|
273
|
+
|
|
274
|
+
**User:** Build a research agent that takes a topic, searches the web for 3 sources, reads each URL, and writes a 500-word summary with citations to a file.
|
|
275
|
+
|
|
276
|
+
**Expected output:**
|
|
277
|
+
- `tools` list: `search_web`, `fetch_url`, `write_file`
|
|
278
|
+
- System prompt: instructs agent to search → fetch 3 URLs → synthesize → write file before declaring done
|
|
279
|
+
- `run_agent(task)` loop with `max_iterations=15`
|
|
280
|
+
- Error handling: if `fetch_url` fails, try next search result
|
|
281
|
+
- Final output: path to the written summary file
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
> **Work with us:** Claudient is backed by [Uitbreiden](https://uitbreiden.com/) — we build AI products and B2B solutions with developer communities. [uitbreiden.com](https://uitbreiden.com/)
|