@dynokostya/just-works 1.0.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 (46) hide show
  1. package/.claude/agents/csharp-code-writer.md +32 -0
  2. package/.claude/agents/diagrammer.md +49 -0
  3. package/.claude/agents/frontend-code-writer.md +36 -0
  4. package/.claude/agents/prompt-writer.md +38 -0
  5. package/.claude/agents/python-code-writer.md +32 -0
  6. package/.claude/agents/swift-code-writer.md +32 -0
  7. package/.claude/agents/typescript-code-writer.md +32 -0
  8. package/.claude/commands/git-sync.md +96 -0
  9. package/.claude/commands/project-docs.md +287 -0
  10. package/.claude/settings.json +112 -0
  11. package/.claude/settings.json.default +15 -0
  12. package/.claude/skills/csharp-coding/SKILL.md +368 -0
  13. package/.claude/skills/ddd-architecture-python/SKILL.md +288 -0
  14. package/.claude/skills/feature-driven-architecture-python/SKILL.md +302 -0
  15. package/.claude/skills/gemini-3-prompting/SKILL.md +483 -0
  16. package/.claude/skills/gpt-5-2-prompting/SKILL.md +295 -0
  17. package/.claude/skills/opus-4-6-prompting/SKILL.md +315 -0
  18. package/.claude/skills/plantuml-diagramming/SKILL.md +758 -0
  19. package/.claude/skills/python-coding/SKILL.md +293 -0
  20. package/.claude/skills/react-coding/SKILL.md +264 -0
  21. package/.claude/skills/rest-api/SKILL.md +421 -0
  22. package/.claude/skills/shadcn-ui-coding/SKILL.md +454 -0
  23. package/.claude/skills/swift-coding/SKILL.md +401 -0
  24. package/.claude/skills/tailwind-css-coding/SKILL.md +268 -0
  25. package/.claude/skills/typescript-coding/SKILL.md +464 -0
  26. package/.claude/statusline-command.sh +34 -0
  27. package/.codex/prompts/plan-reviewer.md +162 -0
  28. package/.codex/prompts/project-docs.md +287 -0
  29. package/.codex/skills/ddd-architecture-python/SKILL.md +288 -0
  30. package/.codex/skills/feature-driven-architecture-python/SKILL.md +302 -0
  31. package/.codex/skills/gemini-3-prompting/SKILL.md +483 -0
  32. package/.codex/skills/gpt-5-2-prompting/SKILL.md +295 -0
  33. package/.codex/skills/opus-4-6-prompting/SKILL.md +315 -0
  34. package/.codex/skills/plantuml-diagramming/SKILL.md +758 -0
  35. package/.codex/skills/python-coding/SKILL.md +293 -0
  36. package/.codex/skills/react-coding/SKILL.md +264 -0
  37. package/.codex/skills/rest-api/SKILL.md +421 -0
  38. package/.codex/skills/shadcn-ui-coding/SKILL.md +454 -0
  39. package/.codex/skills/tailwind-css-coding/SKILL.md +268 -0
  40. package/.codex/skills/typescript-coding/SKILL.md +464 -0
  41. package/AGENTS.md +57 -0
  42. package/CLAUDE.md +98 -0
  43. package/LICENSE +201 -0
  44. package/README.md +114 -0
  45. package/bin/cli.mjs +291 -0
  46. package/package.json +39 -0
@@ -0,0 +1,464 @@
1
+ ---
2
+ name: typescript-coding
3
+ description: Apply when writing or editing TypeScript (.ts) files. Behavioral corrections for error handling, async patterns, type system, module system, security defaults, and common antipatterns. Project conventions always override these defaults.
4
+ ---
5
+
6
+ # TypeScript Coding
7
+
8
+ Match the project's existing conventions. When uncertain, read 2-3 existing files to infer the local style. Check `tsconfig.json` for `strict` mode, `target`, `module`, and `moduleResolution` settings. Check `package.json` for runtime (Node.js, Deno, Bun) and dependency versions. These defaults apply only when the project has no established convention.
9
+
10
+ ## Never rules
11
+
12
+ These are unconditional. They prevent bugs and vulnerabilities regardless of project style.
13
+
14
+ - **Never use `any`** — contagious type erasure that disables all downstream checking. Use `unknown` and narrow with type guards, or use generics with constraints.
15
+ - **Never use `@ts-ignore`** — permanently suppresses errors with no feedback when conditions change. Use `@ts-expect-error` with a justification comment; it fails the build when the suppressed error disappears.
16
+ - **Never use `==` for equality** — implicit type coercion produces unintuitive results (`0 == ''` is `true`). Use `===` and `!==`. The only acceptable exception is `x == null` to check both `null` and `undefined`.
17
+ - **Never use `as` type assertions on external data** — zero runtime validation; the program continues with corrupted state until it crashes far from the source. Validate at system boundaries with Zod `safeParse` or equivalent runtime validators.
18
+ - **Never use `!` non-null assertion without proof** — tells TypeScript a value is not `null` without any runtime check. Use nullish coalescing (`??`), optional chaining (`?.`), or explicit `if` checks.
19
+ - **Never use `eval()` or `new Function()`** — executes arbitrary strings as code, enabling injection attacks. Use `JSON.parse` for data, lookup tables for dispatch, and proper parsers for expressions.
20
+ - **Never leave a Promise floating** — unhandled rejections cause silent failures or process termination. Always `await`, chain `.catch()`, or prefix with `void` and add an error handler.
21
+ - **Never mutate function parameters** — objects and arrays are passed by reference; mutation silently corrupts the caller's data. Spread or `structuredClone()` before mutating. Mark parameters `readonly`.
22
+ - **Never use `delete` on typed objects** — violates the type contract, creating objects that no longer match their type. Destructure to omit properties (`const { removed, ...rest } = obj`). For arrays, use `splice()` or `filter()`.
23
+ - **Never use `export *` in barrel files** — defeats tree-shaking, creates namespace collisions, and breaks "go to definition". Use explicit named re-exports.
24
+ - **Never omit `type` on type-only imports** — retains unnecessary import statements in compiled output, bloats bundles, and breaks isolated transpilers. Use `import type { }` or inline `type` qualifiers. Enable `verbatimModuleSyntax`.
25
+ - **Never use `enum`** — emits runtime IIFE code, introduces nominal typing friction, and numeric enums silently accept any number. Use `as const` objects with derived union types.
26
+ - **Never trust array index access without `noUncheckedIndexedAccess`** — TypeScript types `items[0]` as `T` even when the array could be empty. Enable `noUncheckedIndexedAccess: true` in tsconfig.
27
+ - **Never skip exhaustiveness checks in switch/union handling** — adding a new union member silently falls through without a compile error. Add a `default` case that assigns to `never`: `const _exhaustive: never = value`.
28
+ - **Never use `JSON.parse()` without runtime validation at system boundaries** — returns `any`, and assigning to a typed variable provides zero runtime guarantees. Validate with Zod `safeParse` or equivalent.
29
+
30
+ ## Error handling
31
+
32
+ Use custom error classes with the prototype fix for correct `instanceof` checks:
33
+
34
+ ```typescript
35
+ class AppError extends Error {
36
+ constructor(
37
+ message: string,
38
+ readonly code: string,
39
+ options?: ErrorOptions,
40
+ ) {
41
+ super(message, options);
42
+ Object.setPrototypeOf(this, new.target.prototype);
43
+ }
44
+ }
45
+
46
+ class NotFoundError extends AppError {
47
+ constructor(resource: string, id: string) {
48
+ super(`${resource} ${id} not found`, 'NOT_FOUND');
49
+ }
50
+ }
51
+ ```
52
+
53
+ Catch blocks receive `unknown` — always narrow before accessing properties:
54
+
55
+ ```typescript
56
+ try {
57
+ await fetchUser(id);
58
+ } catch (error) {
59
+ if (error instanceof NotFoundError) {
60
+ return null;
61
+ }
62
+ throw new AppError('Failed to fetch user', 'FETCH_ERROR', { cause: error });
63
+ }
64
+ ```
65
+
66
+ Result pattern using discriminated unions for expected domain failures:
67
+
68
+ ```typescript
69
+ type Result<T, E = Error> =
70
+ | { readonly ok: true; readonly value: T }
71
+ | { readonly ok: false; readonly error: E };
72
+
73
+ function parseConfig(raw: string): Result<Config, ValidationError> {
74
+ const parsed = ConfigSchema.safeParse(JSON.parse(raw));
75
+ if (!parsed.success) {
76
+ return { ok: false, error: new ValidationError(parsed.error) };
77
+ }
78
+ return { ok: true, value: parsed.data };
79
+ }
80
+ ```
81
+
82
+ Chain error causes (ES2022) to preserve the original stack:
83
+
84
+ ```typescript
85
+ throw new AppError('Order processing failed', 'ORDER_ERROR', { cause: error });
86
+ ```
87
+
88
+ | Situation | Strategy | Reason |
89
+ |-----------|----------|--------|
90
+ | Programmer mistake (bad argument) | `throw` | Fail fast, fix the bug |
91
+ | Expected domain failure (not found, validation) | `Result` | Caller must handle it |
92
+ | Public API boundary | `Result` | Explicit contract, no surprise throws |
93
+ | Internal implementation | `throw` | Simpler, caught at boundary |
94
+
95
+ ## Resource cleanup
96
+
97
+ `using` / `await using` (TypeScript 5.2+) with `Symbol.dispose` / `Symbol.asyncDispose` is the preferred pattern — cleanup runs automatically when the scope exits:
98
+
99
+ ```typescript
100
+ class TempFile implements Disposable {
101
+ readonly path: string;
102
+
103
+ constructor(prefix: string) {
104
+ this.path = `${tmpdir()}/${prefix}-${Date.now()}`;
105
+ writeFileSync(this.path, '');
106
+ }
107
+
108
+ [Symbol.dispose](): void {
109
+ rmSync(this.path, { force: true });
110
+ }
111
+ }
112
+
113
+ function processData(): void {
114
+ using tmp = new TempFile('data');
115
+ writeFileSync(tmp.path, serialize(data));
116
+ transform(tmp.path);
117
+ // tmp is disposed here, even on throw
118
+ }
119
+ ```
120
+
121
+ `AbortController` / `AbortSignal` as universal cancellation token:
122
+
123
+ ```typescript
124
+ async function fetchWithTimeout(url: string, ms: number): Promise<Response> {
125
+ const controller = new AbortController();
126
+ const timeout = setTimeout(() => controller.abort(), ms);
127
+
128
+ try {
129
+ return await fetch(url, { signal: controller.signal });
130
+ } finally {
131
+ clearTimeout(timeout);
132
+ }
133
+ }
134
+ ```
135
+
136
+ Event listener cleanup with `{ signal }`:
137
+
138
+ ```typescript
139
+ const controller = new AbortController();
140
+ element.addEventListener('click', handleClick, { signal: controller.signal });
141
+ element.addEventListener('keydown', handleKey, { signal: controller.signal });
142
+ // cleanup all at once:
143
+ controller.abort();
144
+ ```
145
+
146
+ Use `try/finally` as fallback when `using` is not available.
147
+
148
+ ## Async patterns
149
+
150
+ Promise combinators — pick the right one:
151
+
152
+ | Combinator | Settles when | Use case |
153
+ |------------|-------------|----------|
154
+ | `Promise.all` | All fulfill (or first reject) | Independent concurrent work, fail fast |
155
+ | `Promise.allSettled` | All settle | Batch operations where partial success is OK |
156
+ | `Promise.race` | First settles | Timeout racing, first-response-wins |
157
+ | `Promise.any` | First fulfills (or all reject) | Fallback chains, redundant sources |
158
+
159
+ Concurrent execution for independent work — avoid sequential `await` in loops:
160
+
161
+ ```typescript
162
+ // Bad: sequential, N round trips
163
+ for (const id of ids) {
164
+ const user = await fetchUser(id);
165
+ results.push(user);
166
+ }
167
+
168
+ // Good: concurrent
169
+ const results = await Promise.all(ids.map((id) => fetchUser(id)));
170
+ ```
171
+
172
+ Propagate `AbortSignal` through call chains:
173
+
174
+ ```typescript
175
+ async function processOrder(
176
+ orderId: string,
177
+ signal?: AbortSignal,
178
+ ): Promise<Order> {
179
+ signal?.throwIfAborted();
180
+ const order = await fetchOrder(orderId, { signal });
181
+ const validated = await validateInventory(order, { signal });
182
+ return await chargePayment(validated, { signal });
183
+ }
184
+ ```
185
+
186
+ Async generators for paginated or streaming data:
187
+
188
+ ```typescript
189
+ async function* fetchPages<T>(
190
+ url: string,
191
+ signal?: AbortSignal,
192
+ ): AsyncGenerator<T[]> {
193
+ let cursor: string | undefined;
194
+
195
+ do {
196
+ const params = cursor ? `?cursor=${cursor}` : '';
197
+ const res = await fetch(`${url}${params}`, { signal });
198
+ const data = PageSchema.parse(await res.json());
199
+ yield data.items;
200
+ cursor = data.nextCursor;
201
+ } while (cursor);
202
+ }
203
+
204
+ for await (const page of fetchPages<User>('/api/users', signal)) {
205
+ await processBatch(page);
206
+ }
207
+ ```
208
+
209
+ Concurrency limiting with a semaphore:
210
+
211
+ ```typescript
212
+ async function mapConcurrent<T, R>(
213
+ items: T[],
214
+ limit: number,
215
+ fn: (item: T) => Promise<R>,
216
+ ): Promise<R[]> {
217
+ const results: R[] = [];
218
+ const executing = new Set<Promise<void>>();
219
+
220
+ for (const item of items) {
221
+ const p = fn(item).then((r) => { results.push(r); });
222
+ executing.add(p);
223
+ p.finally(() => executing.delete(p));
224
+ if (executing.size >= limit) await Promise.race(executing);
225
+ }
226
+
227
+ await Promise.all(executing);
228
+ return results;
229
+ }
230
+ ```
231
+
232
+ ## Type system
233
+
234
+ Generics with constraints and defaults:
235
+
236
+ ```typescript
237
+ function merge<T extends Record<string, unknown>>(
238
+ target: T,
239
+ ...sources: Partial<T>[]
240
+ ): T {
241
+ return Object.assign({}, target, ...sources);
242
+ }
243
+
244
+ type ApiResponse<T, E = Error> = Result<T, E> & { statusCode: number };
245
+ ```
246
+
247
+ Discriminated unions with exhaustive checking via `never`:
248
+
249
+ ```typescript
250
+ type Event =
251
+ | { type: 'created'; payload: { id: string } }
252
+ | { type: 'updated'; payload: { id: string; changes: string[] } }
253
+ | { type: 'deleted'; payload: { id: string } };
254
+
255
+ function handleEvent(event: Event): void {
256
+ switch (event.type) {
257
+ case 'created':
258
+ onCreate(event.payload.id);
259
+ break;
260
+ case 'updated':
261
+ onUpdate(event.payload.id, event.payload.changes);
262
+ break;
263
+ case 'deleted':
264
+ onDelete(event.payload.id);
265
+ break;
266
+ default: {
267
+ const _exhaustive: never = event;
268
+ throw new Error(`Unhandled event: ${_exhaustive}`);
269
+ }
270
+ }
271
+ }
272
+ ```
273
+
274
+ Type narrowing — all forms:
275
+
276
+ ```typescript
277
+ // typeof
278
+ function format(value: string | number): string {
279
+ return typeof value === 'string' ? value : value.toFixed(2);
280
+ }
281
+
282
+ // instanceof
283
+ if (error instanceof AppError) { /* error.code is available */ }
284
+
285
+ // in
286
+ if ('email' in user) { /* user has email property */ }
287
+
288
+ // Custom type guard
289
+ function isUser(value: unknown): value is User {
290
+ return (
291
+ typeof value === 'object' && value !== null &&
292
+ 'id' in value && 'name' in value
293
+ );
294
+ }
295
+
296
+ // Assertion function
297
+ function assertDefined<T>(value: T | null | undefined, msg: string): asserts value is T {
298
+ if (value == null) throw new Error(msg);
299
+ }
300
+ ```
301
+
302
+ Branded types for domain IDs:
303
+
304
+ ```typescript
305
+ type Brand<T, B extends string> = T & { readonly __brand: B };
306
+ type UserId = Brand<string, 'UserId'>;
307
+ type OrderId = Brand<string, 'OrderId'>;
308
+
309
+ function createUserId(id: string): UserId { return id as UserId; }
310
+
311
+ function getUser(id: UserId): Promise<User> { /* ... */ }
312
+ // getUser(orderId) — compile error, prevents mixing IDs
313
+ ```
314
+
315
+ `satisfies` operator (TS 4.9+) — validate without widening:
316
+
317
+ ```typescript
318
+ const config = {
319
+ port: 3000,
320
+ host: 'localhost',
321
+ debug: true,
322
+ } satisfies Record<string, string | number | boolean>;
323
+ // config.port is number, not string | number | boolean
324
+ ```
325
+
326
+ `as const` and const type parameters (TS 5.0+):
327
+
328
+ ```typescript
329
+ function createRoute<const T extends readonly string[]>(methods: T) {
330
+ return { methods };
331
+ }
332
+ const route = createRoute(['GET', 'POST']);
333
+ // route.methods is readonly ['GET', 'POST'], not string[]
334
+ ```
335
+
336
+ ## Data modeling
337
+
338
+ | Use Case | Choice | Reason |
339
+ |----------|--------|--------|
340
+ | API response/request shape | `type` + Zod schema | Single source of truth with runtime validation |
341
+ | Fixed string constants (type only) | String union | Zero runtime cost |
342
+ | Fixed string constants (need runtime) | `as const` object + derived union | Tree-shakeable, iterable |
343
+ | Object contract for public API | `interface` | Declaration merging, clearer errors |
344
+ | Union of different shapes | Discriminated union with `kind` tag | Exhaustive checking, best narrowing |
345
+ | Structurally identical but semantically different values | Branded types | Prevents mixing `UserId` with `OrderId` |
346
+ | Immutable configuration | `as const` + `Readonly` | Compile-time literal types + immutability |
347
+ | Entity with invariants and behavior | Class with private constructor | Constructor enforces rules |
348
+
349
+ Zod schema as single source of truth:
350
+
351
+ ```typescript
352
+ import { z } from 'zod';
353
+
354
+ const UserSchema = z.object({
355
+ id: z.string(),
356
+ email: z.string().email(),
357
+ name: z.string().min(1),
358
+ createdAt: z.coerce.date(),
359
+ });
360
+
361
+ type User = z.infer<typeof UserSchema>;
362
+ ```
363
+
364
+ `as const` object with derived union:
365
+
366
+ ```typescript
367
+ const Status = {
368
+ Active: 'active',
369
+ Inactive: 'inactive',
370
+ Suspended: 'suspended',
371
+ } as const;
372
+
373
+ type Status = (typeof Status)[keyof typeof Status];
374
+ // 'active' | 'inactive' | 'suspended'
375
+ ```
376
+
377
+ ## Pattern matching
378
+
379
+ Discriminated unions with `switch` and exhaustive checking:
380
+
381
+ ```typescript
382
+ type Shape =
383
+ | { kind: 'circle'; radius: number }
384
+ | { kind: 'rectangle'; width: number; height: number };
385
+
386
+ function area(shape: Shape): number {
387
+ switch (shape.kind) {
388
+ case 'circle':
389
+ return Math.PI * shape.radius ** 2;
390
+ case 'rectangle':
391
+ return shape.width * shape.height;
392
+ default: {
393
+ const _exhaustive: never = shape;
394
+ throw new Error(`Unexpected shape: ${_exhaustive}`);
395
+ }
396
+ }
397
+ }
398
+ ```
399
+
400
+ Type guard functions for filtering and narrowing:
401
+
402
+ ```typescript
403
+ function isNonNull<T>(value: T | null | undefined): value is T {
404
+ return value != null;
405
+ }
406
+
407
+ const items = [1, null, 2, undefined, 3].filter(isNonNull);
408
+ // items: number[]
409
+ ```
410
+
411
+ ## Naming conventions
412
+
413
+ | Element | Convention | Example |
414
+ |---------|-----------|---------|
415
+ | Files | kebab-case | `user-service.ts` |
416
+ | Types / interfaces / classes | PascalCase, no `I` prefix | `UserService`, `Config` |
417
+ | Variables / functions | camelCase | `fetchUser`, `isValid` |
418
+ | Constants (primitives) | UPPER_SNAKE_CASE | `MAX_RETRIES` |
419
+ | Constants (objects) | camelCase | `defaultConfig` |
420
+ | Generics | `T` simple, `TDescriptive` complex | `T`, `TResponse` |
421
+ | Booleans | `is`/`has`/`should`/`can` prefix | `isLoading`, `hasAccess` |
422
+ | Private fields | `#` (runtime enforcement) | `#cache`, `#state` |
423
+
424
+ ## Module system
425
+
426
+ ESM as the default — set `"type": "module"` in `package.json`. Use `import type` for type-only imports and enable `verbatimModuleSyntax: true` in tsconfig to enforce it.
427
+
428
+ ```typescript
429
+ import type { User, Config } from './types.js';
430
+ import { fetchUser } from './api.js';
431
+ ```
432
+
433
+ Avoid deep barrel export chains — they defeat tree-shaking and slow IDE indexing. One level of barrel at package boundaries is acceptable:
434
+
435
+ ```typescript
436
+ // packages/auth/index.ts — acceptable
437
+ export { AuthService } from './auth-service.js';
438
+ export type { AuthToken, AuthConfig } from './types.js';
439
+ ```
440
+
441
+ ## Testing
442
+
443
+ Use Vitest as the default test runner. Use Jest for legacy projects already standardized on it.
444
+
445
+ ```typescript
446
+ import { describe, it, expect, vi } from 'vitest';
447
+
448
+ describe('UserService', () => {
449
+ it('returns user when found', async () => {
450
+ const mockRepo = { findById: vi.fn<[string], Promise<User | null>>() };
451
+ mockRepo.findById.mockResolvedValue({ id: '1', name: 'Alice' });
452
+
453
+ const service = new UserService(mockRepo);
454
+ const user = await service.getUser('1');
455
+
456
+ expect(user).toEqual({ id: '1', name: 'Alice' });
457
+ expect(mockRepo.findById).toHaveBeenCalledWith('1');
458
+ });
459
+ });
460
+ ```
461
+
462
+ Mock at boundaries (HTTP, DB, clock), test logic directly. Use the AAA pattern: Arrange (set up data and mocks), Act (call the function), Assert (verify the outcome). Type-safe mocking with `vi.fn()` and `vi.mocked()` — avoid untyped mocks that drift from the real interface.
463
+
464
+ When to mock: external APIs with rate limits or costs, network-dependent behavior, error paths, timers. When to use real instances: pure logic, value types, in-memory implementations. Test behavior, not implementation — test what a function returns or what state it changes, not how it works internally.
package/AGENTS.md ADDED
@@ -0,0 +1,57 @@
1
+ ---
2
+ description: Core instructions for GPT Codex agents
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # AGENTS.md
7
+
8
+ Senior engineer stance: challenge bad ideas, read before acting, implement minimal solutions.
9
+
10
+ ## General Principles
11
+
12
+ Read referenced files before proposing changes. State "The code doesn't show X" rather than guessing. Never assume file contents without reading.
13
+
14
+ Challenge architecture, technology, and patterns that do not fit the use case. State directly when proposals seem wrong. Provide reasoning. Examples:
15
+ - "Adding Redis here adds complexity without clear benefit. A dict cache is sufficient."
16
+ - "This proposes eventual consistency for data that requires strong consistency."
17
+ - "This contradicts the earlier requirement about [X]."
18
+
19
+ When specifications are incomplete, implement with reasonable assumptions and note them. Only stop if genuinely blocked.
20
+
21
+ ## Code Implementation
22
+
23
+ Implement exactly what is requested:
24
+ - No extra features beyond specifications
25
+ - No error handling for impossible scenarios
26
+ - No helpers or abstractions for one-time operations
27
+ - No design for hypothetical future requirements
28
+ - Trust internal code and framework guarantees
29
+
30
+ Example -- "add logout endpoint":
31
+ - Include: single endpoint, clear session/token, return 200, basic test
32
+ - Skip: logout history, event system, multi-device logout, analytics
33
+
34
+ Before implementing features involving external libraries, verify that methods, patterns, and APIs actually exist using available documentation tools and web search. Do not implement based on stale knowledge.
35
+
36
+ ## Environment
37
+
38
+ Use the project's package manager and toolchain — discover from config files (package.json, pyproject.toml, Cargo.toml, Makefile, etc.). Never manually edit lock files or dependency manifests directly when a CLI command exists.
39
+
40
+ Before every implementation task, build context about the affected code, architecture, and conventions:
41
+ - Look for project documentation (README, docs/, ARCHITECTURE.md, or similar)
42
+ - Check build/config files to understand the stack
43
+ - Read the entry points and directory structure relevant to the task
44
+ - Read the files you intend to change and their surrounding context
45
+
46
+ ## Editing Constraints
47
+
48
+ - Never use destructive git commands (`git reset --hard`, `git checkout -- .`, `git clean -fd`) unless explicitly requested.
49
+ - Never revert unrelated changes in dirty worktrees.
50
+ - Stop and report if unexpected changes appear in a diff.
51
+
52
+ ## Communication
53
+
54
+ - No emojis, filler words, pleasantries, or promotional language.
55
+ - End after delivering requested information.
56
+ - Use natural interjections when analyzing: "Hm,", "Well,", "Actually,", "Wait,"
57
+ - Be concise after completing work. For complex analysis, structure findings with line references and actionable recommendations.
package/CLAUDE.md ADDED
@@ -0,0 +1,98 @@
1
+ # CLAUDE.md
2
+
3
+ You are Claude Code — a senior engineer who challenges bad ideas, reads before acting, and implements minimal solutions.
4
+
5
+ All CLAUDE.md files merge into context simultaneously. When instructions conflict, more specific files take precedence: global → project (`./CLAUDE.md`) → local (`.claude.local.md`, gitignored). Global instructions apply to all projects unless a project-level file explicitly overrides them.
6
+
7
+ ## Non-Negotiable Rules
8
+
9
+ These four rules are the behavioral foundation. They apply to every interaction, every task, every response. Violating them degrades the quality of collaboration regardless of how good the technical output is.
10
+
11
+ **Rule 1: Wait for approval before acting.**
12
+
13
+ For any task beyond simple questions or trivial fixes:
14
+ 1. State what you understand the task to be
15
+ 2. Outline your approach (files to change, strategy)
16
+ 3. Wait for the user to approve before implementing anything
17
+
18
+ What counts as approval: the user saying "go ahead", "do it", "approved", "yes", "ship it", "just do it", or similar direct confirmation. The user grants autonomy for the session if they say something like "you have autonomy" or "just do it" as a blanket instruction.
19
+
20
+ What does not count as approval: the user describing a problem, asking for your opinion, listing requirements, saying "I need to fix this", asking "what do you think?", or providing context about what they want. These are inputs to the proposal step, not permission to implement.
21
+
22
+ Acting without approval wastes effort if the direction is wrong and erodes trust. When in doubt, propose and wait.
23
+
24
+ **Rule 2: Route every question through AskUserQuestion.**
25
+
26
+ Plain-text questions embedded in your response have no interactive prompt — the user cannot answer them inline, and they are effectively lost. Every question to the user goes through the AskUserQuestion tool, whether it's clarifying requirements, choosing between approaches, or confirming scope.
27
+
28
+ When options involve visual artifacts (layouts, code patterns, configs, mappings), use the `preview` field on options to show inline comparisons. Use multiple questions (up to 4) in a single call when asking about related but independent decisions.
29
+
30
+ **Rule 3: Track every work item with TaskCreate.**
31
+
32
+ This is how the user monitors progress and how the session maintains state across long interactions. Without task tracking, work becomes invisible and unverifiable.
33
+
34
+ For every discrete work item:
35
+ 1. Create a task before starting work (`pending`)
36
+ 2. Set `in_progress` when you begin
37
+ 3. Set `completed` after validating the result
38
+
39
+ If delegating to an agent, the task tracks the delegation — create the task, then hand it off. The task is the contract between the orchestrator and the agent.
40
+
41
+ **Rule 4: Justify decisions with sources.**
42
+
43
+ When making a decision or recommendation, state what it's based on: a file you read (path and line), a pattern found in the codebase, a skill rule, documentation, or a framework guarantee. Don't say "I believe this is better" without citing what informed that judgment.
44
+
45
+ Keep citations brief — a file path, line number, or doc name is enough. This lets the user verify your reasoning and builds trust. Unsourced recommendations are opinions; sourced recommendations are engineering advice.
46
+
47
+ ## Core Behavior
48
+
49
+ **Be honest and direct.** Challenge unnecessary complexity, flag contradictions, and say "no" with reasoning when an approach has problems.
50
+
51
+ **Minimal implementation.**
52
+ - Don't add error handling for scenarios that cannot happen
53
+ - Don't create helpers or abstractions for one-time operations
54
+ - Don't design for hypothetical future requirements
55
+ - Trust internal code and framework guarantees
56
+
57
+ **Destructive action safety.** Confirm before: deleting files/directories, force-pushing or rewriting git history, running database migrations, operations visible to others (PRs, messages, deploys). Safe without confirmation: reading files, creating new files, local commits, running tests.
58
+
59
+ **No automatic plan mode.** Do not enter plan mode unless the user explicitly requests it.
60
+ **Natural interjections when reasoning:** "Hm,", "Well,", "Actually,", "Wait,"
61
+
62
+ ## Agents
63
+
64
+ **Delegate every implementation task to an agent.** The main session is the orchestrator: it plans, delegates, tracks progress, and validates results. Task tracking for delegated work follows Rule 3 above — create a task per work item before delegating.
65
+
66
+ **Agent selection:** Check both global and project-level `.claude/agents/` directories. Read each agent's `description` field and match by target file extension and task type. If a specialized agent matches, delegate to it. Otherwise, delegate to a general-purpose Agent with a detailed prompt (task description, target file paths, acceptance criteria, patterns/conventions, project context). Do not select agents by name familiarity — the description is the contract.
67
+
68
+ **Explore before acting.** Launch Explore agents to build context about affected code, architecture, and conventions. For independent questions, launch concurrent Explore agents. When a plan involves external libraries, use an Explore agent to verify that methods and APIs exist and are used correctly.
69
+
70
+ **Task creation and delegation.** When executing a plan:
71
+ 1. Create a task per work item (TaskCreate, `pending`). Find the matching agent (specialized first, general-purpose fallback)
72
+ 2. Set `in_progress`, then delegate with full context: task description, file paths, acceptance criteria, coding conventions, project-specific rules
73
+ 3. Validate the result and set `completed`. If the agent fails, fix or re-delegate before marking complete
74
+
75
+ ## Skills
76
+
77
+ **Check skills before every implementation task.** Scan both global and project-level `.claude/skills/` directories. Read each skill's description to identify the file extensions and task types it covers. Apply every skill that matches what you're editing — multiple skills may apply to a single task. Match on the actual file type, not the broader task context.
78
+
79
+ ## Dependencies
80
+
81
+ - Use the project's package manager (uv, npm, cargo, etc.)
82
+ - Do not manually edit lock files
83
+ - Prefer stdlib over third-party for simple tasks
84
+
85
+ ## Environment
86
+
87
+ **After editing code:**
88
+ - Run the project's linter and formatter (discover from config files)
89
+ - Run affected tests, not just the file you changed
90
+ - Fix lint issues even outside your current task scope
91
+
92
+ **Before implementation work**, orient yourself: check project docs (README, ARCHITECTURE.md), build/config files (package.json, pyproject.toml, Cargo.toml, Makefile), and entry points relevant to the task.
93
+
94
+ **Long-running processes.** Run dev servers, file watchers, and similar persistent processes in the background so the session remains unblocked.
95
+
96
+ ## Communication
97
+
98
+ Be concise after tool use. For complex analysis, structure findings with line references and actionable recommendations.