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.
Files changed (283) hide show
  1. package/.claude-plugin/plugin.json +42 -0
  2. package/CONTEXT.md +58 -0
  3. package/README.md +165 -0
  4. package/agents/build-resolvers/de/python-resolver.md +64 -0
  5. package/agents/build-resolvers/de/typescript-resolver.md +65 -0
  6. package/agents/build-resolvers/es/python-resolver.md +64 -0
  7. package/agents/build-resolvers/es/typescript-resolver.md +65 -0
  8. package/agents/build-resolvers/fr/python-resolver.md +64 -0
  9. package/agents/build-resolvers/fr/typescript-resolver.md +65 -0
  10. package/agents/build-resolvers/nl/python-resolver.md +64 -0
  11. package/agents/build-resolvers/nl/typescript-resolver.md +65 -0
  12. package/agents/build-resolvers/python-resolver.md +62 -0
  13. package/agents/build-resolvers/typescript-resolver.md +63 -0
  14. package/agents/core/architect.md +64 -0
  15. package/agents/core/code-reviewer.md +78 -0
  16. package/agents/core/de/architect.md +66 -0
  17. package/agents/core/de/code-reviewer.md +80 -0
  18. package/agents/core/de/planner.md +63 -0
  19. package/agents/core/de/security-reviewer.md +93 -0
  20. package/agents/core/es/architect.md +66 -0
  21. package/agents/core/es/code-reviewer.md +80 -0
  22. package/agents/core/es/planner.md +63 -0
  23. package/agents/core/es/security-reviewer.md +93 -0
  24. package/agents/core/fr/architect.md +66 -0
  25. package/agents/core/fr/code-reviewer.md +80 -0
  26. package/agents/core/fr/planner.md +63 -0
  27. package/agents/core/fr/security-reviewer.md +93 -0
  28. package/agents/core/nl/architect.md +66 -0
  29. package/agents/core/nl/code-reviewer.md +80 -0
  30. package/agents/core/nl/planner.md +63 -0
  31. package/agents/core/nl/security-reviewer.md +93 -0
  32. package/agents/core/planner.md +61 -0
  33. package/agents/core/security-reviewer.md +91 -0
  34. package/guides/agent-orchestration.md +231 -0
  35. package/guides/de/agent-orchestration.md +174 -0
  36. package/guides/de/getting-started.md +164 -0
  37. package/guides/de/hooks-cookbook.md +160 -0
  38. package/guides/de/memory-management.md +153 -0
  39. package/guides/de/security.md +180 -0
  40. package/guides/de/skill-authoring.md +214 -0
  41. package/guides/de/token-optimization.md +156 -0
  42. package/guides/es/agent-orchestration.md +174 -0
  43. package/guides/es/getting-started.md +164 -0
  44. package/guides/es/hooks-cookbook.md +160 -0
  45. package/guides/es/memory-management.md +153 -0
  46. package/guides/es/security.md +180 -0
  47. package/guides/es/skill-authoring.md +214 -0
  48. package/guides/es/token-optimization.md +156 -0
  49. package/guides/fr/agent-orchestration.md +174 -0
  50. package/guides/fr/getting-started.md +164 -0
  51. package/guides/fr/hooks-cookbook.md +227 -0
  52. package/guides/fr/memory-management.md +169 -0
  53. package/guides/fr/security.md +180 -0
  54. package/guides/fr/skill-authoring.md +214 -0
  55. package/guides/fr/token-optimization.md +158 -0
  56. package/guides/getting-started.md +164 -0
  57. package/guides/hooks-cookbook.md +423 -0
  58. package/guides/memory-management.md +192 -0
  59. package/guides/nl/agent-orchestration.md +174 -0
  60. package/guides/nl/getting-started.md +164 -0
  61. package/guides/nl/hooks-cookbook.md +160 -0
  62. package/guides/nl/memory-management.md +153 -0
  63. package/guides/nl/security.md +180 -0
  64. package/guides/nl/skill-authoring.md +214 -0
  65. package/guides/nl/token-optimization.md +156 -0
  66. package/guides/security.md +229 -0
  67. package/guides/skill-authoring.md +226 -0
  68. package/guides/token-optimization.md +169 -0
  69. package/hooks/lifecycle/cost-tracker.md +49 -0
  70. package/hooks/lifecycle/cost-tracker.sh +59 -0
  71. package/hooks/lifecycle/pre-compact-save.md +56 -0
  72. package/hooks/lifecycle/pre-compact-save.sh +37 -0
  73. package/hooks/lifecycle/session-start.md +50 -0
  74. package/hooks/lifecycle/session-start.sh +47 -0
  75. package/hooks/post-tool-use/audit-log.md +53 -0
  76. package/hooks/post-tool-use/audit-log.sh +53 -0
  77. package/hooks/post-tool-use/prettier.md +53 -0
  78. package/hooks/post-tool-use/prettier.sh +49 -0
  79. package/hooks/pre-tool-use/block-dangerous.md +48 -0
  80. package/hooks/pre-tool-use/block-dangerous.sh +76 -0
  81. package/hooks/pre-tool-use/git-push-confirm.md +46 -0
  82. package/hooks/pre-tool-use/git-push-confirm.sh +36 -0
  83. package/mcp/configs/github.json +11 -0
  84. package/mcp/configs/postgres.json +11 -0
  85. package/mcp/de/recommended-servers.md +170 -0
  86. package/mcp/es/recommended-servers.md +170 -0
  87. package/mcp/fr/recommended-servers.md +170 -0
  88. package/mcp/nl/recommended-servers.md +170 -0
  89. package/mcp/recommended-servers.md +168 -0
  90. package/package.json +45 -0
  91. package/prompts/project-starters/de/fastapi-project.md +62 -0
  92. package/prompts/project-starters/de/nextjs-project.md +82 -0
  93. package/prompts/project-starters/es/fastapi-project.md +62 -0
  94. package/prompts/project-starters/es/nextjs-project.md +82 -0
  95. package/prompts/project-starters/fastapi-project.md +60 -0
  96. package/prompts/project-starters/fr/fastapi-project.md +62 -0
  97. package/prompts/project-starters/fr/nextjs-project.md +82 -0
  98. package/prompts/project-starters/nextjs-project.md +80 -0
  99. package/prompts/project-starters/nl/fastapi-project.md +62 -0
  100. package/prompts/project-starters/nl/nextjs-project.md +82 -0
  101. package/prompts/system-prompts/ai-product.md +80 -0
  102. package/prompts/system-prompts/data-pipeline.md +76 -0
  103. package/prompts/system-prompts/de/ai-product.md +82 -0
  104. package/prompts/system-prompts/de/data-pipeline.md +78 -0
  105. package/prompts/system-prompts/de/saas-backend.md +71 -0
  106. package/prompts/system-prompts/es/ai-product.md +82 -0
  107. package/prompts/system-prompts/es/data-pipeline.md +78 -0
  108. package/prompts/system-prompts/es/saas-backend.md +71 -0
  109. package/prompts/system-prompts/fr/ai-product.md +82 -0
  110. package/prompts/system-prompts/fr/data-pipeline.md +78 -0
  111. package/prompts/system-prompts/fr/saas-backend.md +71 -0
  112. package/prompts/system-prompts/nl/ai-product.md +82 -0
  113. package/prompts/system-prompts/nl/data-pipeline.md +78 -0
  114. package/prompts/system-prompts/nl/saas-backend.md +71 -0
  115. package/prompts/system-prompts/saas-backend.md +69 -0
  116. package/prompts/task-specific/changelog.md +81 -0
  117. package/prompts/task-specific/de/changelog.md +83 -0
  118. package/prompts/task-specific/de/debugging.md +78 -0
  119. package/prompts/task-specific/de/pr-description.md +69 -0
  120. package/prompts/task-specific/debugging.md +76 -0
  121. package/prompts/task-specific/es/changelog.md +83 -0
  122. package/prompts/task-specific/es/debugging.md +78 -0
  123. package/prompts/task-specific/es/pr-description.md +69 -0
  124. package/prompts/task-specific/fr/changelog.md +83 -0
  125. package/prompts/task-specific/fr/debugging.md +78 -0
  126. package/prompts/task-specific/fr/pr-description.md +69 -0
  127. package/prompts/task-specific/nl/changelog.md +83 -0
  128. package/prompts/task-specific/nl/debugging.md +78 -0
  129. package/prompts/task-specific/nl/pr-description.md +69 -0
  130. package/prompts/task-specific/pr-description.md +67 -0
  131. package/rules/common/coding-style.md +45 -0
  132. package/rules/common/de/coding-style.md +47 -0
  133. package/rules/common/de/git.md +48 -0
  134. package/rules/common/de/performance.md +40 -0
  135. package/rules/common/de/security.md +45 -0
  136. package/rules/common/de/testing.md +45 -0
  137. package/rules/common/es/coding-style.md +47 -0
  138. package/rules/common/es/git.md +48 -0
  139. package/rules/common/es/performance.md +40 -0
  140. package/rules/common/es/security.md +45 -0
  141. package/rules/common/es/testing.md +45 -0
  142. package/rules/common/fr/coding-style.md +47 -0
  143. package/rules/common/fr/git.md +48 -0
  144. package/rules/common/fr/performance.md +40 -0
  145. package/rules/common/fr/security.md +45 -0
  146. package/rules/common/fr/testing.md +45 -0
  147. package/rules/common/git.md +46 -0
  148. package/rules/common/nl/coding-style.md +47 -0
  149. package/rules/common/nl/git.md +48 -0
  150. package/rules/common/nl/performance.md +40 -0
  151. package/rules/common/nl/security.md +45 -0
  152. package/rules/common/nl/testing.md +45 -0
  153. package/rules/common/performance.md +38 -0
  154. package/rules/common/security.md +43 -0
  155. package/rules/common/testing.md +43 -0
  156. package/rules/language-specific/de/go.md +48 -0
  157. package/rules/language-specific/de/python.md +38 -0
  158. package/rules/language-specific/de/typescript.md +51 -0
  159. package/rules/language-specific/es/go.md +48 -0
  160. package/rules/language-specific/es/python.md +38 -0
  161. package/rules/language-specific/es/typescript.md +51 -0
  162. package/rules/language-specific/fr/go.md +48 -0
  163. package/rules/language-specific/fr/python.md +38 -0
  164. package/rules/language-specific/fr/typescript.md +51 -0
  165. package/rules/language-specific/go.md +46 -0
  166. package/rules/language-specific/nl/go.md +48 -0
  167. package/rules/language-specific/nl/python.md +38 -0
  168. package/rules/language-specific/nl/typescript.md +51 -0
  169. package/rules/language-specific/python.md +36 -0
  170. package/rules/language-specific/typescript.md +49 -0
  171. package/scripts/cli.js +161 -0
  172. package/scripts/link-skills.sh +35 -0
  173. package/scripts/list-skills.sh +34 -0
  174. package/skills/ai-engineering/agent-construction.md +285 -0
  175. package/skills/ai-engineering/claude-api.md +248 -0
  176. package/skills/ai-engineering/de/agent-construction.md +287 -0
  177. package/skills/ai-engineering/de/claude-api.md +250 -0
  178. package/skills/ai-engineering/es/agent-construction.md +287 -0
  179. package/skills/ai-engineering/es/claude-api.md +250 -0
  180. package/skills/ai-engineering/fr/agent-construction.md +287 -0
  181. package/skills/ai-engineering/fr/claude-api.md +250 -0
  182. package/skills/ai-engineering/nl/agent-construction.md +287 -0
  183. package/skills/ai-engineering/nl/claude-api.md +250 -0
  184. package/skills/backend/dotnet/csharp.md +304 -0
  185. package/skills/backend/dotnet/de/csharp.md +306 -0
  186. package/skills/backend/dotnet/es/csharp.md +306 -0
  187. package/skills/backend/dotnet/fr/csharp.md +306 -0
  188. package/skills/backend/dotnet/nl/csharp.md +306 -0
  189. package/skills/backend/go/de/go.md +307 -0
  190. package/skills/backend/go/es/go.md +307 -0
  191. package/skills/backend/go/fr/go.md +307 -0
  192. package/skills/backend/go/go.md +305 -0
  193. package/skills/backend/go/nl/go.md +307 -0
  194. package/skills/backend/nodejs/de/nestjs.md +274 -0
  195. package/skills/backend/nodejs/de/nextjs.md +222 -0
  196. package/skills/backend/nodejs/es/nestjs.md +274 -0
  197. package/skills/backend/nodejs/es/nextjs.md +222 -0
  198. package/skills/backend/nodejs/fr/nestjs.md +274 -0
  199. package/skills/backend/nodejs/fr/nextjs.md +222 -0
  200. package/skills/backend/nodejs/nestjs.md +272 -0
  201. package/skills/backend/nodejs/nextjs.md +220 -0
  202. package/skills/backend/nodejs/nl/nestjs.md +274 -0
  203. package/skills/backend/nodejs/nl/nextjs.md +222 -0
  204. package/skills/backend/python/de/django.md +285 -0
  205. package/skills/backend/python/de/fastapi.md +244 -0
  206. package/skills/backend/python/django.md +283 -0
  207. package/skills/backend/python/es/django.md +285 -0
  208. package/skills/backend/python/es/fastapi.md +244 -0
  209. package/skills/backend/python/fastapi.md +242 -0
  210. package/skills/backend/python/fr/django.md +285 -0
  211. package/skills/backend/python/fr/fastapi.md +244 -0
  212. package/skills/backend/python/nl/django.md +285 -0
  213. package/skills/backend/python/nl/fastapi.md +244 -0
  214. package/skills/data-ml/dbt-data-pipelines.md +155 -0
  215. package/skills/data-ml/de/dbt-data-pipelines.md +157 -0
  216. package/skills/data-ml/de/pandas-polars.md +147 -0
  217. package/skills/data-ml/de/pytorch-tensorflow.md +171 -0
  218. package/skills/data-ml/es/dbt-data-pipelines.md +157 -0
  219. package/skills/data-ml/es/pandas-polars.md +147 -0
  220. package/skills/data-ml/es/pytorch-tensorflow.md +171 -0
  221. package/skills/data-ml/fr/dbt-data-pipelines.md +157 -0
  222. package/skills/data-ml/fr/pandas-polars.md +147 -0
  223. package/skills/data-ml/fr/pytorch-tensorflow.md +171 -0
  224. package/skills/data-ml/nl/dbt-data-pipelines.md +157 -0
  225. package/skills/data-ml/nl/pandas-polars.md +147 -0
  226. package/skills/data-ml/nl/pytorch-tensorflow.md +171 -0
  227. package/skills/data-ml/pandas-polars.md +145 -0
  228. package/skills/data-ml/pytorch-tensorflow.md +169 -0
  229. package/skills/database/de/graphql.md +181 -0
  230. package/skills/database/es/graphql.md +181 -0
  231. package/skills/database/fr/graphql.md +181 -0
  232. package/skills/database/graphql.md +179 -0
  233. package/skills/database/nl/graphql.md +181 -0
  234. package/skills/devops-infra/de/docker.md +133 -0
  235. package/skills/devops-infra/de/github-actions.md +179 -0
  236. package/skills/devops-infra/de/kubernetes.md +129 -0
  237. package/skills/devops-infra/de/terraform.md +130 -0
  238. package/skills/devops-infra/docker.md +131 -0
  239. package/skills/devops-infra/es/docker.md +133 -0
  240. package/skills/devops-infra/es/github-actions.md +179 -0
  241. package/skills/devops-infra/es/kubernetes.md +129 -0
  242. package/skills/devops-infra/es/terraform.md +130 -0
  243. package/skills/devops-infra/fr/docker.md +133 -0
  244. package/skills/devops-infra/fr/github-actions.md +179 -0
  245. package/skills/devops-infra/fr/kubernetes.md +129 -0
  246. package/skills/devops-infra/fr/terraform.md +130 -0
  247. package/skills/devops-infra/github-actions.md +177 -0
  248. package/skills/devops-infra/kubernetes.md +127 -0
  249. package/skills/devops-infra/nl/docker.md +133 -0
  250. package/skills/devops-infra/nl/github-actions.md +179 -0
  251. package/skills/devops-infra/nl/kubernetes.md +129 -0
  252. package/skills/devops-infra/nl/terraform.md +130 -0
  253. package/skills/devops-infra/terraform.md +128 -0
  254. package/skills/finance-payments/de/stripe.md +187 -0
  255. package/skills/finance-payments/es/stripe.md +187 -0
  256. package/skills/finance-payments/fr/stripe.md +187 -0
  257. package/skills/finance-payments/nl/stripe.md +187 -0
  258. package/skills/finance-payments/stripe.md +185 -0
  259. package/workflows/code-review.md +151 -0
  260. package/workflows/de/code-review.md +153 -0
  261. package/workflows/de/debugging-session.md +146 -0
  262. package/workflows/de/feature-development.md +155 -0
  263. package/workflows/de/new-project-bootstrap.md +175 -0
  264. package/workflows/de/refactor-safely.md +150 -0
  265. package/workflows/debugging-session.md +144 -0
  266. package/workflows/es/code-review.md +153 -0
  267. package/workflows/es/debugging-session.md +146 -0
  268. package/workflows/es/feature-development.md +155 -0
  269. package/workflows/es/new-project-bootstrap.md +175 -0
  270. package/workflows/es/refactor-safely.md +150 -0
  271. package/workflows/feature-development.md +153 -0
  272. package/workflows/fr/code-review.md +153 -0
  273. package/workflows/fr/debugging-session.md +146 -0
  274. package/workflows/fr/feature-development.md +155 -0
  275. package/workflows/fr/new-project-bootstrap.md +175 -0
  276. package/workflows/fr/refactor-safely.md +150 -0
  277. package/workflows/new-project-bootstrap.md +173 -0
  278. package/workflows/nl/code-review.md +153 -0
  279. package/workflows/nl/debugging-session.md +146 -0
  280. package/workflows/nl/feature-development.md +155 -0
  281. package/workflows/nl/new-project-bootstrap.md +175 -0
  282. package/workflows/nl/refactor-safely.md +150 -0
  283. package/workflows/refactor-safely.md +148 -0
@@ -0,0 +1,250 @@
1
+ > 🇳🇱 Dit is de Nederlandse vertaling. [Engelse versie](../claude-api.md).
2
+
3
+ # Claude API Skill
4
+
5
+ ## Wanneer te activeren
6
+ - Code schrijven die de Anthropic Claude API aanroept (Python of TypeScript SDK)
7
+ - Prompt-caching, streaming of batchverwerking implementeren
8
+ - Beheer van gesprekken met meerdere beurten ontwerpen
9
+ - Het juiste Claude-model (Haiku, Sonnet, Opus) kiezen voor een taak
10
+ - Toolgebruik / function calling toevoegen aan een Claude-integratie
11
+ - Optimaliseren voor kosten of latentie in een productie-Claude-app
12
+
13
+ ## Wanneer NIET te gebruiken
14
+ - OpenAI of andere provider-API's — andere SDK, andere patronen
15
+ - Algemeen LLM-advies dat niet gerelateerd is aan de Anthropic API
16
+ - Projecten die al LangChain of LlamaIndex-abstracties gebruiken — adresseer de abstractielaag in plaats daarvan
17
+
18
+ ## Instructies
19
+
20
+ ### Modelselectiegids
21
+ | Model | Gebruik wanneer | Vermijd wanneer |
22
+ |-------|----------|------------|
23
+ | `claude-haiku-4-5-20251001` | Classificatie, extractie, routing, eenvoudige Q&A, hoog-volume goedkoop | Complexe redenering, meerstaps codegeneratie |
24
+ | `claude-sonnet-4-6` | Algemeen gebruik: code, analyse, schrijven, agentische workflows | Token-beperkte budgetten op massale schaal |
25
+ | `claude-opus-4-7` | Expertniveau-redenering, genuanceerd oordeel, complexe lange tekst | De meeste taken — Sonnet is meestal voldoende |
26
+
27
+ ### Basis berichtaanroep (Python)
28
+ ```python
29
+ import anthropic
30
+
31
+ client = anthropic.Anthropic() # leest ANTHROPIC_API_KEY uit omgeving
32
+
33
+ message = client.messages.create(
34
+ model="claude-sonnet-4-6",
35
+ max_tokens=1024,
36
+ system="You are a helpful assistant specialized in Python.",
37
+ messages=[
38
+ {"role": "user", "content": "Explain Python's GIL in 3 sentences."}
39
+ ]
40
+ )
41
+ print(message.content[0].text)
42
+ ```
43
+
44
+ ### Prompt-caching (kritisch voor kosten)
45
+ Prompt-caching kan kosten met maximaal 90% verlagen voor herhaalde context. Cache stabiele inhoud (systeemprompts, grote documenten, few-shot-voorbeelden).
46
+
47
+ ```python
48
+ message = client.messages.create(
49
+ model="claude-sonnet-4-6",
50
+ max_tokens=1024,
51
+ system=[
52
+ {
53
+ "type": "text",
54
+ "text": "You are a code review assistant. Here are our coding standards: ...",
55
+ "cache_control": {"type": "ephemeral"} # Cache dit blok
56
+ }
57
+ ],
58
+ messages=[
59
+ {
60
+ "role": "user",
61
+ "content": [
62
+ {
63
+ "type": "text",
64
+ "text": large_document,
65
+ "cache_control": {"type": "ephemeral"} # Cache ook het document
66
+ },
67
+ {
68
+ "type": "text",
69
+ "text": "Summarize the key points."
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ )
75
+ # Controleer cachegebruik in respons
76
+ print(message.usage.cache_read_input_tokens) # tokens gelezen uit cache
77
+ print(message.usage.cache_creation_input_tokens) # tokens geschreven naar cache
78
+ ```
79
+
80
+ Cacheregels:
81
+ - Minimaal cacheerbaar blok: 1024 tokens (Sonnet/Opus), 2048 tokens (Haiku)
82
+ - Cache-TTL: 5 minuten
83
+ - Alleen het laatste `cache_control`-blok in een berichtarray telt — cachepunten zijn cumulatief
84
+
85
+ ### Streaming
86
+ ```python
87
+ with client.messages.stream(
88
+ model="claude-sonnet-4-6",
89
+ max_tokens=1024,
90
+ messages=[{"role": "user", "content": prompt}]
91
+ ) as stream:
92
+ for text in stream.text_stream:
93
+ print(text, end="", flush=True)
94
+
95
+ # Of met events:
96
+ with client.messages.stream(...) as stream:
97
+ for event in stream:
98
+ if event.type == "content_block_delta":
99
+ print(event.delta.text, end="")
100
+ elif event.type == "message_stop":
101
+ print() # nieuwe regel wanneer klaar
102
+ ```
103
+
104
+ ### Toolgebruik
105
+ ```python
106
+ tools = [
107
+ {
108
+ "name": "get_weather",
109
+ "description": "Get current weather for a city",
110
+ "input_schema": {
111
+ "type": "object",
112
+ "properties": {
113
+ "city": {"type": "string", "description": "City name"},
114
+ "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
115
+ },
116
+ "required": ["city"]
117
+ }
118
+ }
119
+ ]
120
+
121
+ response = client.messages.create(
122
+ model="claude-sonnet-4-6",
123
+ max_tokens=1024,
124
+ tools=tools,
125
+ messages=[{"role": "user", "content": "What's the weather in Paris?"}]
126
+ )
127
+
128
+ # Controleer of Claude een tool wil gebruiken
129
+ if response.stop_reason == "tool_use":
130
+ tool_use = next(b for b in response.content if b.type == "tool_use")
131
+ tool_result = call_tool(tool_use.name, tool_use.input)
132
+
133
+ # Ga door met gesprek met toolresultaat
134
+ follow_up = client.messages.create(
135
+ model="claude-sonnet-4-6",
136
+ max_tokens=1024,
137
+ tools=tools,
138
+ messages=[
139
+ {"role": "user", "content": "What's the weather in Paris?"},
140
+ {"role": "assistant", "content": response.content},
141
+ {
142
+ "role": "user",
143
+ "content": [{
144
+ "type": "tool_result",
145
+ "tool_use_id": tool_use.id,
146
+ "content": json.dumps(tool_result)
147
+ }]
148
+ }
149
+ ]
150
+ )
151
+ ```
152
+
153
+ ### Gesprek met meerdere beurten
154
+ ```python
155
+ class Conversation:
156
+ def __init__(self, system: str, model: str = "claude-sonnet-4-6"):
157
+ self.client = anthropic.Anthropic()
158
+ self.model = model
159
+ self.system = system
160
+ self.messages: list[dict] = []
161
+
162
+ def chat(self, user_message: str, max_tokens: int = 1024) -> str:
163
+ self.messages.append({"role": "user", "content": user_message})
164
+ response = self.client.messages.create(
165
+ model=self.model,
166
+ max_tokens=max_tokens,
167
+ system=self.system,
168
+ messages=self.messages,
169
+ )
170
+ assistant_message = response.content[0].text
171
+ self.messages.append({"role": "assistant", "content": assistant_message})
172
+ return assistant_message
173
+ ```
174
+
175
+ ### Batchverwerking
176
+ ```python
177
+ from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
178
+ from anthropic.types.messages.batch_create_params import Request
179
+
180
+ requests = [
181
+ Request(
182
+ custom_id=f"review-{i}",
183
+ params=MessageCreateParamsNonStreaming(
184
+ model="claude-haiku-4-5-20251001",
185
+ max_tokens=256,
186
+ messages=[{"role": "user", "content": f"Classify: {review}"}],
187
+ )
188
+ )
189
+ for i, review in enumerate(reviews)
190
+ ]
191
+
192
+ batch = client.messages.batches.create(requests=requests)
193
+ print(f"Batch ID: {batch.id}")
194
+
195
+ # Poll voor resultaten (of gebruik webhooks)
196
+ import time
197
+ while True:
198
+ batch = client.messages.batches.retrieve(batch.id)
199
+ if batch.processing_status == "ended":
200
+ break
201
+ time.sleep(60)
202
+
203
+ for result in client.messages.batches.results(batch.id):
204
+ print(result.custom_id, result.result.message.content[0].text)
205
+ ```
206
+
207
+ ### Foutafhandeling en herhaalpogingen
208
+ ```python
209
+ from anthropic import APIStatusError, APITimeoutError, RateLimitError
210
+
211
+ def call_with_retry(client, **kwargs, max_retries=3):
212
+ for attempt in range(max_retries):
213
+ try:
214
+ return client.messages.create(**kwargs)
215
+ except RateLimitError:
216
+ wait = 2 ** attempt
217
+ time.sleep(wait)
218
+ except APITimeoutError:
219
+ if attempt == max_retries - 1:
220
+ raise
221
+ time.sleep(1)
222
+ except APIStatusError as e:
223
+ if e.status_code >= 500 and attempt < max_retries - 1:
224
+ time.sleep(2 ** attempt)
225
+ else:
226
+ raise
227
+ ```
228
+
229
+ ### Kostenoptimalisatie-checklist
230
+ - Gebruik Haiku voor classificatie, routing en eenvoudige extractietaken
231
+ - Schakel prompt-caching in voor elke systeemprompt > 1024 tokens
232
+ - Gebruik de batch API voor offline/async-workloads — 50% kostenvermindering
233
+ - Stel `max_tokens` in op het minimum dat nodig is — je betaalt voor gegenereerde output-tokens
234
+ - Cache grote documenten in het gebruikersbericht, niet alleen de systeemprompt
235
+ - Monitor de verhouding `cache_read_input_tokens` vs `input_tokens` — streef naar >80% voor stabiele contexten
236
+
237
+ ## Voorbeeld
238
+
239
+ **Gebruiker:** Bouw een Python-klasse die klantenservicetickets indeelt in categorieën met Claude, met prompt-caching voor de categorielijst en streaming voor de uitleg.
240
+
241
+ **Verwachte output:**
242
+ - `TicketClassifier`-klasse met `ANTHROPIC_API_KEY` uit omgeving
243
+ - Systeemprompt met alle categorieën gecacht via `cache_control: ephemeral`
244
+ - `classify(ticket_text)` → retourneert `{category: str, confidence: str}` geparseerd uit gestructureerde output
245
+ - `classify_and_explain(ticket_text)` → streamt de uitleg naar stdout
246
+ - Gebruikt `claude-haiku-4-5-20251001` voor classificatie (kostenefficiënt), `claude-sonnet-4-6` voor uitleg
247
+
248
+ ---
249
+
250
+ > **Werk met ons:** Claudient wordt ondersteund door [Uitbreiden](https://uitbreiden.com/) — we bouwen AI-producten en B2B-oplossingen met ontwikkelaarsgemeenschappen. [uitbreiden.com](https://uitbreiden.com/)
@@ -0,0 +1,304 @@
1
+ # C#/.NET Skill
2
+
3
+ ## When to activate
4
+ - Building a .NET Web API (minimal API or controller-based)
5
+ - Setting up Entity Framework Core with migrations
6
+ - Configuring the .NET dependency injection container
7
+ - Writing background services with `IHostedService` or `BackgroundService`
8
+ - Implementing middleware pipeline components
9
+ - Writing LINQ queries and understanding deferred execution
10
+ - Setting up async/await correctly in ASP.NET Core
11
+
12
+ ## When NOT to use
13
+ - Node.js or Python services
14
+ - .NET Framework (pre-.NET 5) legacy codebases — patterns differ
15
+ - Blazor or MAUI frontend — different concerns
16
+ - Unity game development — different runtime
17
+
18
+ ## Instructions
19
+
20
+ ### Project structure
21
+ ```
22
+ MyApi/
23
+ ├── MyApi.sln
24
+ ├── src/
25
+ │ └── MyApi/
26
+ │ ├── Program.cs # Entry point + DI container
27
+ │ ├── appsettings.json
28
+ │ ├── appsettings.Development.json
29
+ │ ├── Controllers/ # Controller-based API
30
+ │ ├── Endpoints/ # Minimal API extensions
31
+ │ ├── Models/ # EF Core entities
32
+ │ ├── DTOs/ # Request/response shapes
33
+ │ ├── Services/ # Business logic interfaces + implementations
34
+ │ ├── Data/
35
+ │ │ └── AppDbContext.cs
36
+ │ └── Middleware/
37
+ └── tests/
38
+ └── MyApi.Tests/
39
+ ```
40
+
41
+ ### Program.cs — minimal API setup
42
+ ```csharp
43
+ // Program.cs — .NET 6+ top-level statements + minimal API
44
+ var builder = WebApplication.CreateBuilder(args);
45
+
46
+ // Register services
47
+ builder.Services.AddDbContext<AppDbContext>(options =>
48
+ options.UseNpgsql(builder.Configuration.GetConnectionString("Default")));
49
+
50
+ builder.Services.AddScoped<IUserService, UserService>();
51
+ builder.Services.AddControllers();
52
+ builder.Services.AddEndpointsApiExplorer();
53
+ builder.Services.AddSwaggerGen();
54
+
55
+ var app = builder.Build();
56
+
57
+ if (app.Environment.IsDevelopment())
58
+ {
59
+ app.UseSwagger();
60
+ app.UseSwaggerUI();
61
+ }
62
+
63
+ app.UseHttpsRedirection();
64
+ app.UseAuthentication();
65
+ app.UseAuthorization();
66
+ app.MapControllers();
67
+
68
+ // Minimal API endpoints
69
+ app.MapGroup("/api/v1").MapUserEndpoints();
70
+
71
+ app.Run();
72
+ ```
73
+
74
+ ### EF Core entity + DbContext
75
+ ```csharp
76
+ // Models/User.cs
77
+ public class User
78
+ {
79
+ public Guid Id { get; set; } = Guid.NewGuid();
80
+ public required string Email { get; set; }
81
+ public required string PasswordHash { get; set; }
82
+ public bool IsActive { get; set; } = true;
83
+ public DateTimeOffset CreatedAt { get; set; } = DateTimeOffset.UtcNow;
84
+
85
+ public ICollection<Post> Posts { get; set; } = [];
86
+ }
87
+
88
+ // Data/AppDbContext.cs
89
+ public class AppDbContext(DbContextOptions<AppDbContext> options) : DbContext(options)
90
+ {
91
+ public DbSet<User> Users => Set<User>();
92
+ public DbSet<Post> Posts => Set<Post>();
93
+
94
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
95
+ {
96
+ modelBuilder.Entity<User>(e =>
97
+ {
98
+ e.HasIndex(u => u.Email).IsUnique();
99
+ e.Property(u => u.Email).HasMaxLength(320);
100
+ });
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### Dependency injection — services
106
+ ```csharp
107
+ // Services/IUserService.cs
108
+ public interface IUserService
109
+ {
110
+ Task<UserDto> GetByIdAsync(Guid id, CancellationToken ct = default);
111
+ Task<UserDto> CreateAsync(CreateUserRequest request, CancellationToken ct = default);
112
+ }
113
+
114
+ // Services/UserService.cs
115
+ public class UserService(AppDbContext db) : IUserService
116
+ {
117
+ public async Task<UserDto> GetByIdAsync(Guid id, CancellationToken ct = default)
118
+ {
119
+ var user = await db.Users
120
+ .AsNoTracking()
121
+ .FirstOrDefaultAsync(u => u.Id == id, ct)
122
+ ?? throw new NotFoundException($"User {id} not found");
123
+
124
+ return new UserDto(user.Id, user.Email, user.CreatedAt);
125
+ }
126
+
127
+ public async Task<UserDto> CreateAsync(CreateUserRequest request, CancellationToken ct = default)
128
+ {
129
+ if (await db.Users.AnyAsync(u => u.Email == request.Email, ct))
130
+ throw new ConflictException("Email already in use");
131
+
132
+ var user = new User
133
+ {
134
+ Email = request.Email,
135
+ PasswordHash = BCrypt.Net.BCrypt.HashPassword(request.Password)
136
+ };
137
+ db.Users.Add(user);
138
+ await db.SaveChangesAsync(ct);
139
+ return new UserDto(user.Id, user.Email, user.CreatedAt);
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### Controller-based API
145
+ ```csharp
146
+ [ApiController]
147
+ [Route("api/v1/[controller]")]
148
+ public class UsersController(IUserService userService) : ControllerBase
149
+ {
150
+ [HttpGet("{id:guid}")]
151
+ [ProducesResponseType<UserDto>(StatusCodes.Status200OK)]
152
+ [ProducesResponseType(StatusCodes.Status404NotFound)]
153
+ public async Task<IActionResult> GetUser(Guid id, CancellationToken ct)
154
+ {
155
+ var user = await userService.GetByIdAsync(id, ct);
156
+ return Ok(user);
157
+ }
158
+
159
+ [HttpPost]
160
+ [ProducesResponseType<UserDto>(StatusCodes.Status201Created)]
161
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
162
+ [ProducesResponseType(StatusCodes.Status409Conflict)]
163
+ public async Task<IActionResult> CreateUser(
164
+ [FromBody] CreateUserRequest request,
165
+ CancellationToken ct)
166
+ {
167
+ var user = await userService.CreateAsync(request, ct);
168
+ return CreatedAtAction(nameof(GetUser), new { id = user.Id }, user);
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Minimal API endpoints (extension method pattern)
174
+ ```csharp
175
+ // Endpoints/UserEndpoints.cs
176
+ public static class UserEndpoints
177
+ {
178
+ public static RouteGroupBuilder MapUserEndpoints(this RouteGroupBuilder group)
179
+ {
180
+ var users = group.MapGroup("/users").WithTags("Users");
181
+
182
+ users.MapGet("/{id:guid}", async (Guid id, IUserService svc, CancellationToken ct) =>
183
+ {
184
+ var user = await svc.GetByIdAsync(id, ct);
185
+ return Results.Ok(user);
186
+ })
187
+ .WithName("GetUser")
188
+ .Produces<UserDto>();
189
+
190
+ return group;
191
+ }
192
+ }
193
+ ```
194
+
195
+ ### Middleware
196
+ ```csharp
197
+ // Middleware/RequestLoggingMiddleware.cs
198
+ public class RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
199
+ {
200
+ public async Task InvokeAsync(HttpContext context)
201
+ {
202
+ var sw = Stopwatch.StartNew();
203
+ try
204
+ {
205
+ await next(context);
206
+ }
207
+ finally
208
+ {
209
+ sw.Stop();
210
+ logger.LogInformation(
211
+ "{Method} {Path} {StatusCode} in {Elapsed}ms",
212
+ context.Request.Method,
213
+ context.Request.Path,
214
+ context.Response.StatusCode,
215
+ sw.ElapsedMilliseconds);
216
+ }
217
+ }
218
+ }
219
+
220
+ // Register in Program.cs before other middleware:
221
+ app.UseMiddleware<RequestLoggingMiddleware>();
222
+ ```
223
+
224
+ ### Background services
225
+ ```csharp
226
+ // Services/CleanupService.cs
227
+ public class CleanupService(IServiceProvider services, ILogger<CleanupService> logger)
228
+ : BackgroundService
229
+ {
230
+ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
231
+ {
232
+ while (!stoppingToken.IsCancellationRequested)
233
+ {
234
+ await DoCleanupAsync(stoppingToken);
235
+ await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
236
+ }
237
+ }
238
+
239
+ private async Task DoCleanupAsync(CancellationToken ct)
240
+ {
241
+ // Use a new scope for each iteration — BackgroundService is singleton
242
+ using var scope = services.CreateScope();
243
+ var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
244
+ var cutoff = DateTimeOffset.UtcNow.AddDays(-30);
245
+ await db.Sessions.Where(s => s.ExpiresAt < cutoff).ExecuteDeleteAsync(ct);
246
+ }
247
+ }
248
+
249
+ // Register: builder.Services.AddHostedService<CleanupService>();
250
+ ```
251
+
252
+ ### LINQ best practices
253
+ ```csharp
254
+ // Always use AsNoTracking() for read-only queries
255
+ var users = await db.Users.AsNoTracking().Where(u => u.IsActive).ToListAsync(ct);
256
+
257
+ // Select only needed columns — avoid loading full entities for projections
258
+ var emails = await db.Users
259
+ .Where(u => u.IsActive)
260
+ .Select(u => u.Email)
261
+ .ToListAsync(ct);
262
+
263
+ // Use ExecuteUpdateAsync/ExecuteDeleteAsync for bulk ops — skips loading entities
264
+ await db.Users
265
+ .Where(u => !u.IsActive && u.CreatedAt < cutoff)
266
+ .ExecuteDeleteAsync(ct);
267
+
268
+ // Avoid N+1: use Include() for related data
269
+ var posts = await db.Posts
270
+ .Include(p => p.Author)
271
+ .Include(p => p.Tags)
272
+ .Where(p => p.Published)
273
+ .AsNoTracking()
274
+ .ToListAsync(ct);
275
+ ```
276
+
277
+ ### DTOs and records
278
+ ```csharp
279
+ // Use records for immutable DTOs
280
+ public record UserDto(Guid Id, string Email, DateTimeOffset CreatedAt);
281
+ public record CreateUserRequest(
282
+ [property: Required, EmailAddress] string Email,
283
+ [property: Required, MinLength(8)] string Password
284
+ );
285
+
286
+ // Response types with problem details (built-in .NET)
287
+ // Return Results.Problem() or throw exceptions caught by middleware
288
+ ```
289
+
290
+ ## Example
291
+
292
+ **User:** Add a `BlogPost` resource to a .NET Web API: CRUD endpoints, EF Core entity, migrations, and a background job that publishes scheduled posts.
293
+
294
+ **Expected output:**
295
+ - `Models/BlogPost.cs` — entity with `Id`, `Title`, `Body`, `AuthorId` (FK to User), `PublishedAt` (nullable), `ScheduledFor` (nullable)
296
+ - `DTOs/BlogPostDtos.cs` — `BlogPostDto` record, `CreateBlogPostRequest` record with `[Required]` validation
297
+ - `Services/IBlogPostService.cs` + `BlogPostService.cs` — CRUD methods, `GetPendingScheduledAsync` for background job
298
+ - `Controllers/BlogPostsController.cs` — all CRUD with proper status codes
299
+ - `Services/PostPublisherService.cs` — `BackgroundService` that checks every minute and publishes due posts
300
+ - EF Core migration: `dotnet ef migrations add AddBlogPosts`
301
+
302
+ ---
303
+
304
+ > **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/)