@malamute/ai-rules 1.0.0 → 1.2.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 (133) hide show
  1. package/README.md +270 -121
  2. package/bin/cli.js +5 -2
  3. package/configs/_shared/.claude/rules/conventions/documentation.md +324 -0
  4. package/configs/_shared/.claude/rules/conventions/git.md +265 -0
  5. package/configs/_shared/.claude/rules/{performance.md → conventions/performance.md} +1 -1
  6. package/configs/_shared/.claude/rules/conventions/principles.md +334 -0
  7. package/configs/_shared/.claude/rules/devops/ci-cd.md +262 -0
  8. package/configs/_shared/.claude/rules/devops/docker.md +275 -0
  9. package/configs/_shared/.claude/rules/devops/nx.md +194 -0
  10. package/configs/_shared/.claude/rules/domain/backend/api-design.md +203 -0
  11. package/configs/_shared/.claude/rules/lang/csharp/async.md +220 -0
  12. package/configs/_shared/.claude/rules/lang/csharp/csharp.md +314 -0
  13. package/configs/_shared/.claude/rules/lang/csharp/linq.md +210 -0
  14. package/configs/_shared/.claude/rules/lang/python/async.md +337 -0
  15. package/configs/_shared/.claude/rules/lang/python/celery.md +476 -0
  16. package/configs/_shared/.claude/rules/lang/python/config.md +339 -0
  17. package/configs/{python/.claude/rules → _shared/.claude/rules/lang/python}/database/sqlalchemy.md +6 -1
  18. package/configs/_shared/.claude/rules/lang/python/deployment.md +523 -0
  19. package/configs/_shared/.claude/rules/lang/python/error-handling.md +330 -0
  20. package/configs/_shared/.claude/rules/lang/python/migrations.md +421 -0
  21. package/configs/_shared/.claude/rules/lang/python/python.md +172 -0
  22. package/configs/_shared/.claude/rules/lang/python/repository.md +383 -0
  23. package/configs/{python/.claude/rules → _shared/.claude/rules/lang/python}/testing.md +2 -69
  24. package/configs/_shared/.claude/rules/lang/typescript/async.md +447 -0
  25. package/configs/_shared/.claude/rules/lang/typescript/generics.md +356 -0
  26. package/configs/_shared/.claude/rules/lang/typescript/typescript.md +212 -0
  27. package/configs/_shared/.claude/rules/quality/error-handling.md +48 -0
  28. package/configs/_shared/.claude/rules/quality/logging.md +45 -0
  29. package/configs/_shared/.claude/rules/quality/observability.md +240 -0
  30. package/configs/_shared/.claude/rules/quality/testing-patterns.md +65 -0
  31. package/configs/_shared/.claude/rules/security/secrets-management.md +222 -0
  32. package/configs/_shared/.claude/skills/analysis/explore/SKILL.md +257 -0
  33. package/configs/_shared/.claude/skills/analysis/security-audit/SKILL.md +184 -0
  34. package/configs/_shared/.claude/skills/dev/api-endpoint/SKILL.md +126 -0
  35. package/configs/_shared/.claude/{commands/generate-tests.md → skills/dev/generate-tests/SKILL.md} +6 -0
  36. package/configs/_shared/.claude/{commands/fix-issue.md → skills/git/fix-issue/SKILL.md} +6 -0
  37. package/configs/_shared/.claude/{commands/review-pr.md → skills/git/review-pr/SKILL.md} +6 -0
  38. package/configs/_shared/.claude/skills/infra/deploy/SKILL.md +139 -0
  39. package/configs/_shared/.claude/skills/infra/docker/SKILL.md +95 -0
  40. package/configs/_shared/.claude/skills/infra/migration/SKILL.md +158 -0
  41. package/configs/_shared/.claude/skills/nx/nx-affected/SKILL.md +72 -0
  42. package/configs/_shared/.claude/skills/nx/nx-lib/SKILL.md +375 -0
  43. package/configs/_shared/CLAUDE.md +52 -149
  44. package/configs/angular/.claude/rules/{components.md → core/components.md} +69 -15
  45. package/configs/angular/.claude/rules/core/resource.md +285 -0
  46. package/configs/angular/.claude/rules/core/signals.md +323 -0
  47. package/configs/angular/.claude/rules/http.md +338 -0
  48. package/configs/angular/.claude/rules/routing.md +291 -0
  49. package/configs/angular/.claude/rules/ssr.md +312 -0
  50. package/configs/angular/.claude/rules/state/signal-store.md +408 -0
  51. package/configs/angular/.claude/rules/{state.md → state/state.md} +2 -2
  52. package/configs/angular/.claude/rules/testing.md +7 -7
  53. package/configs/angular/.claude/rules/ui/aria.md +422 -0
  54. package/configs/angular/.claude/rules/ui/forms.md +424 -0
  55. package/configs/angular/.claude/rules/ui/pipes-directives.md +335 -0
  56. package/configs/angular/.claude/settings.json +1 -0
  57. package/configs/angular/.claude/skills/ngrx-slice/SKILL.md +362 -0
  58. package/configs/angular/.claude/skills/signal-store/SKILL.md +445 -0
  59. package/configs/angular/CLAUDE.md +24 -216
  60. package/configs/dotnet/.claude/rules/background-services.md +552 -0
  61. package/configs/dotnet/.claude/rules/configuration.md +426 -0
  62. package/configs/dotnet/.claude/rules/ddd.md +447 -0
  63. package/configs/dotnet/.claude/rules/dependency-injection.md +343 -0
  64. package/configs/dotnet/.claude/rules/mediatr.md +320 -0
  65. package/configs/dotnet/.claude/rules/middleware.md +489 -0
  66. package/configs/dotnet/.claude/rules/result-pattern.md +363 -0
  67. package/configs/dotnet/.claude/rules/validation.md +388 -0
  68. package/configs/dotnet/.claude/settings.json +21 -3
  69. package/configs/dotnet/CLAUDE.md +53 -286
  70. package/configs/fastapi/.claude/rules/background-tasks.md +254 -0
  71. package/configs/fastapi/.claude/rules/dependencies.md +170 -0
  72. package/configs/{python → fastapi}/.claude/rules/fastapi.md +61 -1
  73. package/configs/fastapi/.claude/rules/lifespan.md +274 -0
  74. package/configs/fastapi/.claude/rules/middleware.md +229 -0
  75. package/configs/fastapi/.claude/rules/pydantic.md +433 -0
  76. package/configs/fastapi/.claude/rules/responses.md +251 -0
  77. package/configs/fastapi/.claude/rules/routers.md +202 -0
  78. package/configs/fastapi/.claude/rules/security.md +222 -0
  79. package/configs/fastapi/.claude/rules/testing.md +251 -0
  80. package/configs/fastapi/.claude/rules/websockets.md +298 -0
  81. package/configs/fastapi/.claude/settings.json +33 -0
  82. package/configs/fastapi/CLAUDE.md +144 -0
  83. package/configs/flask/.claude/rules/blueprints.md +208 -0
  84. package/configs/flask/.claude/rules/cli.md +285 -0
  85. package/configs/flask/.claude/rules/configuration.md +281 -0
  86. package/configs/flask/.claude/rules/context.md +238 -0
  87. package/configs/flask/.claude/rules/error-handlers.md +278 -0
  88. package/configs/flask/.claude/rules/extensions.md +278 -0
  89. package/configs/flask/.claude/rules/flask.md +171 -0
  90. package/configs/flask/.claude/rules/marshmallow.md +206 -0
  91. package/configs/flask/.claude/rules/security.md +267 -0
  92. package/configs/flask/.claude/rules/testing.md +284 -0
  93. package/configs/flask/.claude/settings.json +33 -0
  94. package/configs/flask/CLAUDE.md +166 -0
  95. package/configs/nestjs/.claude/rules/common-patterns.md +300 -0
  96. package/configs/nestjs/.claude/rules/filters.md +376 -0
  97. package/configs/nestjs/.claude/rules/interceptors.md +317 -0
  98. package/configs/nestjs/.claude/rules/middleware.md +321 -0
  99. package/configs/nestjs/.claude/rules/modules.md +26 -0
  100. package/configs/nestjs/.claude/rules/pipes.md +351 -0
  101. package/configs/nestjs/.claude/rules/websockets.md +451 -0
  102. package/configs/nestjs/.claude/settings.json +16 -2
  103. package/configs/nestjs/CLAUDE.md +57 -215
  104. package/configs/nextjs/.claude/rules/api-routes.md +358 -0
  105. package/configs/nextjs/.claude/rules/authentication.md +355 -0
  106. package/configs/nextjs/.claude/rules/components.md +52 -0
  107. package/configs/nextjs/.claude/rules/data-fetching.md +249 -0
  108. package/configs/nextjs/.claude/rules/database.md +400 -0
  109. package/configs/nextjs/.claude/rules/middleware.md +303 -0
  110. package/configs/nextjs/.claude/rules/routing.md +324 -0
  111. package/configs/nextjs/.claude/rules/seo.md +350 -0
  112. package/configs/nextjs/.claude/rules/server-actions.md +353 -0
  113. package/configs/nextjs/.claude/rules/state/zustand.md +6 -6
  114. package/configs/nextjs/.claude/settings.json +5 -0
  115. package/configs/nextjs/CLAUDE.md +69 -331
  116. package/package.json +23 -9
  117. package/src/cli.js +220 -0
  118. package/src/config.js +29 -0
  119. package/src/index.js +13 -0
  120. package/src/installer.js +361 -0
  121. package/src/merge.js +116 -0
  122. package/src/tech-config.json +29 -0
  123. package/src/utils.js +96 -0
  124. package/configs/python/.claude/rules/flask.md +0 -332
  125. package/configs/python/.claude/settings.json +0 -18
  126. package/configs/python/CLAUDE.md +0 -273
  127. package/src/install.js +0 -315
  128. /package/configs/_shared/.claude/rules/{accessibility.md → domain/frontend/accessibility.md} +0 -0
  129. /package/configs/_shared/.claude/rules/{security.md → security/security.md} +0 -0
  130. /package/configs/_shared/.claude/skills/{debug → dev/debug}/SKILL.md +0 -0
  131. /package/configs/_shared/.claude/skills/{learning → dev/learning}/SKILL.md +0 -0
  132. /package/configs/_shared/.claude/skills/{spec → dev/spec}/SKILL.md +0 -0
  133. /package/configs/_shared/.claude/skills/{review → git/review}/SKILL.md +0 -0
@@ -0,0 +1,339 @@
1
+ ---
2
+ paths:
3
+ - "**/config.py"
4
+ - "**/settings.py"
5
+ - "**/config/**/*.py"
6
+ - "**/settings/**/*.py"
7
+ ---
8
+
9
+ # Python Configuration (pydantic-settings)
10
+
11
+ ## Basic Settings
12
+
13
+ ```python
14
+ # config.py
15
+ from pydantic import Field, PostgresDsn, RedisDsn
16
+ from pydantic_settings import BaseSettings, SettingsConfigDict
17
+
18
+
19
+ class Settings(BaseSettings):
20
+ """Application settings loaded from environment variables."""
21
+
22
+ model_config = SettingsConfigDict(
23
+ env_file=".env",
24
+ env_file_encoding="utf-8",
25
+ case_sensitive=False,
26
+ extra="ignore",
27
+ )
28
+
29
+ # Application
30
+ app_name: str = "MyApp"
31
+ debug: bool = False
32
+ environment: str = Field(default="development", pattern="^(development|staging|production)$")
33
+
34
+ # Server
35
+ host: str = "0.0.0.0"
36
+ port: int = 8000
37
+ workers: int = 4
38
+
39
+ # Database
40
+ database_url: PostgresDsn
41
+ database_pool_size: int = 5
42
+ database_max_overflow: int = 10
43
+
44
+ # Redis
45
+ redis_url: RedisDsn | None = None
46
+
47
+ # Security
48
+ secret_key: str
49
+ jwt_algorithm: str = "HS256"
50
+ access_token_expire_minutes: int = 30
51
+ refresh_token_expire_days: int = 7
52
+
53
+ # CORS
54
+ cors_origins: list[str] = ["http://localhost:3000"]
55
+
56
+ # External APIs
57
+ stripe_api_key: str | None = None
58
+ sendgrid_api_key: str | None = None
59
+
60
+
61
+ # Singleton instance
62
+ settings = Settings()
63
+ ```
64
+
65
+ ## Nested Settings
66
+
67
+ ```python
68
+ # config/settings.py
69
+ from pydantic import BaseModel
70
+ from pydantic_settings import BaseSettings, SettingsConfigDict
71
+
72
+
73
+ class DatabaseSettings(BaseModel):
74
+ """Database configuration."""
75
+
76
+ url: str
77
+ pool_size: int = 5
78
+ max_overflow: int = 10
79
+ echo: bool = False
80
+
81
+
82
+ class RedisSettings(BaseModel):
83
+ """Redis configuration."""
84
+
85
+ url: str
86
+ password: str | None = None
87
+ db: int = 0
88
+
89
+
90
+ class AuthSettings(BaseModel):
91
+ """Authentication configuration."""
92
+
93
+ secret_key: str
94
+ algorithm: str = "HS256"
95
+ access_token_expire_minutes: int = 30
96
+ refresh_token_expire_days: int = 7
97
+
98
+
99
+ class Settings(BaseSettings):
100
+ """Root settings with nested configuration."""
101
+
102
+ model_config = SettingsConfigDict(
103
+ env_file=".env",
104
+ env_nested_delimiter="__", # DATABASE__URL -> database.url
105
+ case_sensitive=False,
106
+ )
107
+
108
+ app_name: str = "MyApp"
109
+ debug: bool = False
110
+ environment: str = "development"
111
+
112
+ database: DatabaseSettings
113
+ redis: RedisSettings | None = None
114
+ auth: AuthSettings
115
+
116
+
117
+ settings = Settings()
118
+
119
+ # Access: settings.database.url, settings.auth.secret_key
120
+ ```
121
+
122
+ ## Environment-Specific Settings
123
+
124
+ ```python
125
+ # config/base.py
126
+ from pydantic_settings import BaseSettings
127
+
128
+
129
+ class BaseAppSettings(BaseSettings):
130
+ """Base settings shared across all environments."""
131
+
132
+ app_name: str = "MyApp"
133
+ api_prefix: str = "/api/v1"
134
+
135
+
136
+ # config/development.py
137
+ class DevelopmentSettings(BaseAppSettings):
138
+ debug: bool = True
139
+ database_url: str = "postgresql://localhost/myapp_dev"
140
+ log_level: str = "DEBUG"
141
+
142
+
143
+ # config/production.py
144
+ class ProductionSettings(BaseAppSettings):
145
+ debug: bool = False
146
+ database_url: str # Required in production
147
+ log_level: str = "INFO"
148
+
149
+ model_config = SettingsConfigDict(
150
+ env_file=None, # No .env in production
151
+ )
152
+
153
+
154
+ # config/__init__.py
155
+ import os
156
+ from functools import lru_cache
157
+
158
+ from .development import DevelopmentSettings
159
+ from .production import ProductionSettings
160
+
161
+
162
+ @lru_cache
163
+ def get_settings():
164
+ environment = os.getenv("ENVIRONMENT", "development")
165
+
166
+ settings_map = {
167
+ "development": DevelopmentSettings,
168
+ "production": ProductionSettings,
169
+ }
170
+
171
+ settings_class = settings_map.get(environment, DevelopmentSettings)
172
+ return settings_class()
173
+
174
+
175
+ settings = get_settings()
176
+ ```
177
+
178
+ ## Validation
179
+
180
+ ```python
181
+ from pydantic import field_validator, model_validator
182
+ from pydantic_settings import BaseSettings
183
+
184
+
185
+ class Settings(BaseSettings):
186
+ environment: str
187
+ debug: bool = False
188
+
189
+ database_url: str
190
+ database_pool_size: int = 5
191
+
192
+ @field_validator("environment")
193
+ @classmethod
194
+ def validate_environment(cls, v: str) -> str:
195
+ allowed = {"development", "staging", "production"}
196
+ if v not in allowed:
197
+ raise ValueError(f"environment must be one of {allowed}")
198
+ return v
199
+
200
+ @field_validator("database_pool_size")
201
+ @classmethod
202
+ def validate_pool_size(cls, v: int) -> int:
203
+ if v < 1 or v > 100:
204
+ raise ValueError("database_pool_size must be between 1 and 100")
205
+ return v
206
+
207
+ @model_validator(mode="after")
208
+ def validate_production(self) -> "Settings":
209
+ if self.environment == "production" and self.debug:
210
+ raise ValueError("debug must be False in production")
211
+ return self
212
+ ```
213
+
214
+ ## FastAPI Integration
215
+
216
+ ```python
217
+ # main.py
218
+ from functools import lru_cache
219
+ from typing import Annotated
220
+
221
+ from fastapi import Depends, FastAPI
222
+
223
+ from config import Settings
224
+
225
+
226
+ @lru_cache
227
+ def get_settings() -> Settings:
228
+ return Settings()
229
+
230
+
231
+ SettingsDep = Annotated[Settings, Depends(get_settings)]
232
+
233
+ app = FastAPI()
234
+
235
+
236
+ @app.get("/info")
237
+ async def info(settings: SettingsDep):
238
+ return {
239
+ "app_name": settings.app_name,
240
+ "environment": settings.environment,
241
+ }
242
+
243
+
244
+ # Override in tests
245
+ def get_test_settings() -> Settings:
246
+ return Settings(
247
+ database_url="postgresql://localhost/test",
248
+ secret_key="test-secret",
249
+ )
250
+
251
+
252
+ app.dependency_overrides[get_settings] = get_test_settings
253
+ ```
254
+
255
+ ## Secrets Management
256
+
257
+ ```python
258
+ from pydantic import SecretStr
259
+ from pydantic_settings import BaseSettings
260
+
261
+
262
+ class Settings(BaseSettings):
263
+ # SecretStr hides value in logs and repr
264
+ database_password: SecretStr
265
+ api_key: SecretStr
266
+
267
+ def get_database_url(self) -> str:
268
+ # Access secret value with .get_secret_value()
269
+ password = self.database_password.get_secret_value()
270
+ return f"postgresql://user:{password}@localhost/db"
271
+
272
+
273
+ # In code
274
+ settings = Settings()
275
+ print(settings.database_password) # SecretStr('**********')
276
+ print(settings.database_password.get_secret_value()) # actual password
277
+ ```
278
+
279
+ ## .env File
280
+
281
+ ```bash
282
+ # .env
283
+ APP_NAME=MyApp
284
+ ENVIRONMENT=development
285
+ DEBUG=true
286
+
287
+ # Database
288
+ DATABASE__URL=postgresql://user:pass@localhost/myapp
289
+ DATABASE__POOL_SIZE=10
290
+
291
+ # Redis
292
+ REDIS__URL=redis://localhost:6379
293
+ REDIS__DB=0
294
+
295
+ # Auth
296
+ AUTH__SECRET_KEY=your-super-secret-key-here
297
+ AUTH__ACCESS_TOKEN_EXPIRE_MINUTES=60
298
+
299
+ # External APIs
300
+ STRIPE_API_KEY=sk_test_xxx
301
+ SENDGRID_API_KEY=SG.xxx
302
+ ```
303
+
304
+ ## Anti-Patterns
305
+
306
+ ```python
307
+ # BAD: Hardcoded secrets
308
+ SECRET_KEY = "my-secret-key"
309
+
310
+
311
+ # GOOD: Load from environment
312
+ from pydantic_settings import BaseSettings
313
+
314
+ class Settings(BaseSettings):
315
+ secret_key: str # Required from env
316
+
317
+
318
+ # BAD: Global mutable config
319
+ config = {}
320
+
321
+ def load_config():
322
+ global config
323
+ config["db_url"] = os.getenv("DATABASE_URL")
324
+
325
+
326
+ # GOOD: Immutable settings with caching
327
+ @lru_cache
328
+ def get_settings() -> Settings:
329
+ return Settings()
330
+
331
+
332
+ # BAD: No validation
333
+ database_url = os.getenv("DATABASE_URL") # Could be None!
334
+
335
+
336
+ # GOOD: Required fields with validation
337
+ class Settings(BaseSettings):
338
+ database_url: PostgresDsn # Validated URL format, required
339
+ ```
@@ -1,6 +1,11 @@
1
1
  ---
2
2
  paths:
3
- - "**/*.py"
3
+ - "**/models/**/*.py"
4
+ - "**/repositories/**/*.py"
5
+ - "**/db/**/*.py"
6
+ - "**/database/**/*.py"
7
+ - "**/*_model.py"
8
+ - "**/*_repository.py"
4
9
  ---
5
10
 
6
11
  # SQLAlchemy 2.0 Rules