oh-my-customcode 0.24.2 → 0.30.1
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/README.md +3 -3
- package/dist/cli/index.js +518 -245
- package/dist/index.js +327 -37
- package/package.json +1 -1
- package/templates/.claude/agents/be-django-expert.md +45 -0
- package/templates/.claude/hooks/hooks.json +10 -0
- package/templates/.claude/hooks/scripts/context-budget-advisor.sh +86 -0
- package/templates/.claude/hooks/scripts/session-env-check.sh +58 -0
- package/templates/.claude/rules/SHOULD-ecomode.md +39 -0
- package/templates/.claude/rules/SHOULD-memory-integration.md +99 -9
- package/templates/.claude/skills/dev-lead-routing/SKILL.md +2 -1
- package/templates/.claude/skills/django-best-practices/SKILL.md +440 -0
- package/templates/CLAUDE.md.en +5 -5
- package/templates/CLAUDE.md.ko +5 -5
- package/templates/guides/django-best-practices/README.md +476 -0
- package/templates/manifest.json +4 -4
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: django-best-practices
|
|
3
|
+
description: Django patterns for production-ready Python web applications
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Apply Django patterns for building production-ready, secure, and maintainable Python web applications.
|
|
10
|
+
|
|
11
|
+
## Rules
|
|
12
|
+
|
|
13
|
+
### 1. Project Structure
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
structure:
|
|
17
|
+
settings_split: true
|
|
18
|
+
layout: |
|
|
19
|
+
project/
|
|
20
|
+
├── config/
|
|
21
|
+
│ ├── settings/
|
|
22
|
+
│ │ ├── base.py
|
|
23
|
+
│ │ ├── development.py
|
|
24
|
+
│ │ └── production.py
|
|
25
|
+
│ ├── urls.py
|
|
26
|
+
│ └── wsgi.py
|
|
27
|
+
├── apps/
|
|
28
|
+
│ ├── core/ # Shared utilities, base models
|
|
29
|
+
│ ├── users/ # Custom User model (ALWAYS create)
|
|
30
|
+
│ └── {feature}/ # Feature-specific apps
|
|
31
|
+
├── templates/
|
|
32
|
+
├── static/
|
|
33
|
+
├── requirements/
|
|
34
|
+
│ ├── base.txt
|
|
35
|
+
│ ├── development.txt
|
|
36
|
+
│ └── production.txt
|
|
37
|
+
└── manage.py
|
|
38
|
+
|
|
39
|
+
app_module_contents:
|
|
40
|
+
models.py: Database models
|
|
41
|
+
views.py: Request handlers
|
|
42
|
+
urls.py: URL patterns (with app_name)
|
|
43
|
+
serializers.py: DRF serializers (if API)
|
|
44
|
+
forms.py: Django forms
|
|
45
|
+
admin.py: Admin customization
|
|
46
|
+
services.py: Business logic layer
|
|
47
|
+
managers.py: Custom model managers
|
|
48
|
+
signals.py: Django signals (use sparingly)
|
|
49
|
+
tests/: Test suite (mirror app structure)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Models Best Practices
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
custom_user_model:
|
|
56
|
+
rule: ALWAYS create a custom User model, even if identical to default
|
|
57
|
+
location: apps/users/models.py
|
|
58
|
+
reason: Impossible to swap default User model mid-project
|
|
59
|
+
example: |
|
|
60
|
+
# apps/users/models.py
|
|
61
|
+
from django.contrib.auth.models import AbstractUser
|
|
62
|
+
|
|
63
|
+
class User(AbstractUser):
|
|
64
|
+
pass # Can extend later without migrations
|
|
65
|
+
|
|
66
|
+
# config/settings/base.py
|
|
67
|
+
AUTH_USER_MODEL = 'users.User'
|
|
68
|
+
|
|
69
|
+
primary_key:
|
|
70
|
+
default: BigAutoField
|
|
71
|
+
settings: DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
72
|
+
|
|
73
|
+
model_meta:
|
|
74
|
+
required:
|
|
75
|
+
- __str__: human-readable representation
|
|
76
|
+
- Meta.ordering: consistent default ordering
|
|
77
|
+
- Meta.verbose_name: singular display name
|
|
78
|
+
- Meta.verbose_name_plural: plural display name
|
|
79
|
+
example: |
|
|
80
|
+
class Article(models.Model):
|
|
81
|
+
title = models.CharField(max_length=200)
|
|
82
|
+
created_at = models.DateTimeField(auto_now_add=True)
|
|
83
|
+
|
|
84
|
+
class Meta:
|
|
85
|
+
ordering = ['-created_at']
|
|
86
|
+
verbose_name = 'article'
|
|
87
|
+
verbose_name_plural = 'articles'
|
|
88
|
+
|
|
89
|
+
def __str__(self):
|
|
90
|
+
return self.title
|
|
91
|
+
|
|
92
|
+
query_optimization:
|
|
93
|
+
foreign_key: select_related() # Single SQL JOIN
|
|
94
|
+
many_to_many: prefetch_related() # Separate query + Python join
|
|
95
|
+
partial_fields: only() / defer() # Load subset of fields
|
|
96
|
+
aggregations: F() and Q() objects for complex expressions
|
|
97
|
+
bulk_ops:
|
|
98
|
+
create: bulk_create(objs, batch_size=1000)
|
|
99
|
+
update: bulk_update(objs, fields, batch_size=1000)
|
|
100
|
+
|
|
101
|
+
indexing:
|
|
102
|
+
- Frequently filtered fields: db_index=True
|
|
103
|
+
- Frequently ordered fields: Meta.ordering fields
|
|
104
|
+
- Multi-column: Meta.indexes with models.Index
|
|
105
|
+
- Unique together: Meta.unique_together or UniqueConstraint
|
|
106
|
+
|
|
107
|
+
constraints:
|
|
108
|
+
use: Meta.constraints for database-level enforcement
|
|
109
|
+
example: |
|
|
110
|
+
class Meta:
|
|
111
|
+
constraints = [
|
|
112
|
+
models.UniqueConstraint(
|
|
113
|
+
fields=['user', 'article'],
|
|
114
|
+
name='unique_user_article'
|
|
115
|
+
),
|
|
116
|
+
models.CheckConstraint(
|
|
117
|
+
check=models.Q(price__gte=0),
|
|
118
|
+
name='price_non_negative'
|
|
119
|
+
)
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
soft_delete:
|
|
123
|
+
pattern: is_active = models.BooleanField(default=True)
|
|
124
|
+
manager: Override default manager to filter is_active=True
|
|
125
|
+
|
|
126
|
+
custom_managers:
|
|
127
|
+
rule: Use managers for reusable querysets
|
|
128
|
+
example: |
|
|
129
|
+
class PublishedManager(models.Manager):
|
|
130
|
+
def get_queryset(self):
|
|
131
|
+
return super().get_queryset().filter(status='published')
|
|
132
|
+
|
|
133
|
+
class Article(models.Model):
|
|
134
|
+
objects = models.Manager() # Keep default
|
|
135
|
+
published = PublishedManager() # Add custom
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 3. Views Best Practices
|
|
139
|
+
|
|
140
|
+
```yaml
|
|
141
|
+
cbv_vs_fbv:
|
|
142
|
+
cbv: Standard CRUD, predictable patterns (ListView, DetailView, etc.)
|
|
143
|
+
fbv: Complex custom logic, non-standard workflows
|
|
144
|
+
|
|
145
|
+
thin_views:
|
|
146
|
+
rule: Keep views thin — delegate business logic to services/models
|
|
147
|
+
wrong: |
|
|
148
|
+
def create_order(request):
|
|
149
|
+
# 50 lines of business logic in view
|
|
150
|
+
correct: |
|
|
151
|
+
def create_order(request):
|
|
152
|
+
form = OrderForm(request.POST)
|
|
153
|
+
if form.is_valid():
|
|
154
|
+
order = order_service.create(request.user, form.cleaned_data)
|
|
155
|
+
return redirect('order-detail', pk=order.pk)
|
|
156
|
+
|
|
157
|
+
shortcuts:
|
|
158
|
+
- get_object_or_404(Model, pk=pk): Returns 404 instead of 500
|
|
159
|
+
- get_list_or_404(Model, **kwargs): 404 if empty list
|
|
160
|
+
|
|
161
|
+
mixins:
|
|
162
|
+
authentication: LoginRequiredMixin
|
|
163
|
+
permissions: PermissionRequiredMixin
|
|
164
|
+
user_pass: UserPassesTestMixin
|
|
165
|
+
|
|
166
|
+
status_codes:
|
|
167
|
+
200: OK (default for success)
|
|
168
|
+
201: Created (after successful creation)
|
|
169
|
+
302: Redirect (after POST success — PRG pattern)
|
|
170
|
+
400: Bad Request (validation error)
|
|
171
|
+
403: Forbidden (permission denied)
|
|
172
|
+
404: Not Found
|
|
173
|
+
405: Method Not Allowed
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 4. URL Patterns
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
namespacing:
|
|
180
|
+
app_name: Required in every app's urls.py
|
|
181
|
+
usage: reverse('app_name:url_name') or {% url 'app_name:url_name' %}
|
|
182
|
+
|
|
183
|
+
syntax:
|
|
184
|
+
prefer: path() over re_path() for clarity
|
|
185
|
+
use_re_path: Only for complex regex patterns
|
|
186
|
+
|
|
187
|
+
naming:
|
|
188
|
+
rule: Name ALL URL patterns
|
|
189
|
+
convention: "{resource}-{action}" (e.g., article-list, article-detail)
|
|
190
|
+
|
|
191
|
+
inclusion:
|
|
192
|
+
root_urls: Use include() for app-level URLs
|
|
193
|
+
example: |
|
|
194
|
+
# config/urls.py
|
|
195
|
+
urlpatterns = [
|
|
196
|
+
path('admin/', admin.site.urls),
|
|
197
|
+
path('api/', include('apps.api.urls', namespace='api')),
|
|
198
|
+
path('articles/', include('apps.articles.urls', namespace='articles')),
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
# apps/articles/urls.py
|
|
202
|
+
app_name = 'articles'
|
|
203
|
+
urlpatterns = [
|
|
204
|
+
path('', ArticleListView.as_view(), name='list'),
|
|
205
|
+
path('<int:pk>/', ArticleDetailView.as_view(), name='detail'),
|
|
206
|
+
]
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### 5. Forms & Validation
|
|
210
|
+
|
|
211
|
+
```yaml
|
|
212
|
+
model_forms:
|
|
213
|
+
rule: Use ModelForm when form maps to a model
|
|
214
|
+
fields: Explicitly list fields (never use fields = '__all__')
|
|
215
|
+
|
|
216
|
+
validation:
|
|
217
|
+
field_level: clean_<field>() method
|
|
218
|
+
cross_field: clean() method
|
|
219
|
+
built_in: Use Django validators (MaxValueValidator, RegexValidator, etc.)
|
|
220
|
+
|
|
221
|
+
example: |
|
|
222
|
+
class ArticleForm(forms.ModelForm):
|
|
223
|
+
class Meta:
|
|
224
|
+
model = Article
|
|
225
|
+
fields = ['title', 'body', 'status']
|
|
226
|
+
|
|
227
|
+
def clean_title(self):
|
|
228
|
+
title = self.cleaned_data['title']
|
|
229
|
+
if len(title) < 5:
|
|
230
|
+
raise forms.ValidationError('Title too short.')
|
|
231
|
+
return title
|
|
232
|
+
|
|
233
|
+
def clean(self):
|
|
234
|
+
cleaned = super().clean()
|
|
235
|
+
# Cross-field validation here
|
|
236
|
+
return cleaned
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### 6. Security
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
environment:
|
|
243
|
+
SECRET_KEY: Never hardcode — read from environment variable
|
|
244
|
+
DEBUG: False in production (MUST)
|
|
245
|
+
ALLOWED_HOSTS: Explicitly set in production (MUST)
|
|
246
|
+
|
|
247
|
+
https:
|
|
248
|
+
SECURE_SSL_REDIRECT: true
|
|
249
|
+
SESSION_COOKIE_SECURE: true
|
|
250
|
+
CSRF_COOKIE_SECURE: true
|
|
251
|
+
SECURE_HSTS_SECONDS: 3600 # Start small, increase to 31536000
|
|
252
|
+
SECURE_HSTS_INCLUDE_SUBDOMAINS: true
|
|
253
|
+
|
|
254
|
+
clickjacking:
|
|
255
|
+
X_FRAME_OPTIONS: DENY
|
|
256
|
+
|
|
257
|
+
content_type:
|
|
258
|
+
SECURE_CONTENT_TYPE_NOSNIFF: true
|
|
259
|
+
|
|
260
|
+
csrf:
|
|
261
|
+
rule: Enabled by default via CsrfViewMiddleware — do NOT disable
|
|
262
|
+
|
|
263
|
+
sql_injection:
|
|
264
|
+
rule: Use ORM, avoid raw SQL; if needed, use parameterized queries
|
|
265
|
+
|
|
266
|
+
xss:
|
|
267
|
+
rule: Templates auto-escape by default — never use |safe with user content
|
|
268
|
+
|
|
269
|
+
deployment_check:
|
|
270
|
+
command: python manage.py check --deploy
|
|
271
|
+
run: Before every production deployment
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 7. Testing
|
|
275
|
+
|
|
276
|
+
```yaml
|
|
277
|
+
framework:
|
|
278
|
+
preferred: pytest-django (over unittest)
|
|
279
|
+
config: pytest.ini or pyproject.toml with [tool.pytest.ini_options]
|
|
280
|
+
|
|
281
|
+
test_classes:
|
|
282
|
+
database: TestCase (wraps each test in transaction)
|
|
283
|
+
no_database: SimpleTestCase (faster)
|
|
284
|
+
live_server: LiveServerTestCase (for Selenium)
|
|
285
|
+
|
|
286
|
+
test_data:
|
|
287
|
+
preferred: factory_boy or model_bakery
|
|
288
|
+
avoid: fixtures (hard to maintain, slow)
|
|
289
|
+
example: |
|
|
290
|
+
import factory
|
|
291
|
+
from apps.users.models import User
|
|
292
|
+
|
|
293
|
+
class UserFactory(factory.django.DjangoModelFactory):
|
|
294
|
+
class Meta:
|
|
295
|
+
model = User
|
|
296
|
+
username = factory.Sequence(lambda n: f'user{n}')
|
|
297
|
+
email = factory.LazyAttribute(lambda o: f'{o.username}@example.com')
|
|
298
|
+
|
|
299
|
+
request_testing:
|
|
300
|
+
Client: Full request/response cycle (preferred for views)
|
|
301
|
+
RequestFactory: Faster, no middleware (for unit testing views)
|
|
302
|
+
|
|
303
|
+
settings_override:
|
|
304
|
+
decorator: '@override_settings(EMAIL_BACKEND="django.core.mail.backends.locmem.EmailBackend")'
|
|
305
|
+
|
|
306
|
+
coverage:
|
|
307
|
+
target: 80%+
|
|
308
|
+
exclude: migrations, admin, settings
|
|
309
|
+
|
|
310
|
+
structure:
|
|
311
|
+
mirror_app: tests/test_models.py, tests/test_views.py, tests/test_forms.py
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 8. Performance
|
|
315
|
+
|
|
316
|
+
```yaml
|
|
317
|
+
n_plus_1_prevention:
|
|
318
|
+
check: Use django-debug-toolbar in development
|
|
319
|
+
fix_fk: select_related('author', 'category')
|
|
320
|
+
fix_m2m: prefetch_related('tags', 'comments')
|
|
321
|
+
complex: Prefetch object with custom queryset
|
|
322
|
+
|
|
323
|
+
partial_loading:
|
|
324
|
+
only: only('id', 'title', 'created_at') # Load only these fields
|
|
325
|
+
defer: defer('body', 'metadata') # Load all except these
|
|
326
|
+
values: values('id', 'title') # Returns dicts (no ORM overhead)
|
|
327
|
+
values_list: values_list('id', flat=True) # Returns flat list
|
|
328
|
+
|
|
329
|
+
caching:
|
|
330
|
+
backend: Redis (preferred), Memcached
|
|
331
|
+
view_cache: '@cache_page(60 * 15)' decorator
|
|
332
|
+
template_cache: '{% cache 500 sidebar %}' template tag
|
|
333
|
+
low_level: cache.get/set/delete for fine-grained control
|
|
334
|
+
|
|
335
|
+
pagination:
|
|
336
|
+
list_views: Always paginate large querysets
|
|
337
|
+
page_size: Set reasonable default (20-50 items)
|
|
338
|
+
drf: PageNumberPagination or CursorPagination
|
|
339
|
+
|
|
340
|
+
bulk_operations:
|
|
341
|
+
create: Article.objects.bulk_create(articles, batch_size=1000)
|
|
342
|
+
update: Article.objects.bulk_update(articles, ['status'], batch_size=1000)
|
|
343
|
+
avoid: Loops calling .save() on many objects
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
### 9. Django REST Framework (DRF)
|
|
347
|
+
|
|
348
|
+
```yaml
|
|
349
|
+
serializers:
|
|
350
|
+
standard_crud: ModelSerializer
|
|
351
|
+
read_only: Use SerializerMethodField for computed values
|
|
352
|
+
write_validation: validate_<field>() and validate() methods
|
|
353
|
+
example: |
|
|
354
|
+
class ArticleSerializer(serializers.ModelSerializer):
|
|
355
|
+
author_name = serializers.SerializerMethodField()
|
|
356
|
+
|
|
357
|
+
class Meta:
|
|
358
|
+
model = Article
|
|
359
|
+
fields = ['id', 'title', 'body', 'author_name', 'created_at']
|
|
360
|
+
read_only_fields = ['id', 'created_at']
|
|
361
|
+
|
|
362
|
+
def get_author_name(self, obj):
|
|
363
|
+
return obj.author.get_full_name()
|
|
364
|
+
|
|
365
|
+
viewsets:
|
|
366
|
+
standard: ModelViewSet for full CRUD
|
|
367
|
+
custom: ViewSet with explicit action methods
|
|
368
|
+
routers: DefaultRouter or SimpleRouter for URL generation
|
|
369
|
+
|
|
370
|
+
authentication:
|
|
371
|
+
jwt: djangorestframework-simplejwt (recommended)
|
|
372
|
+
token: DRF built-in TokenAuthentication
|
|
373
|
+
session: SessionAuthentication (for browser clients)
|
|
374
|
+
|
|
375
|
+
permissions:
|
|
376
|
+
global: DEFAULT_PERMISSION_CLASSES in settings
|
|
377
|
+
per_view: permission_classes attribute on ViewSet
|
|
378
|
+
object_level: has_object_permission() in custom permission class
|
|
379
|
+
|
|
380
|
+
versioning:
|
|
381
|
+
method: NamespaceVersioning or URLPathVersioning
|
|
382
|
+
example: "/api/v1/articles/" vs "/api/v2/articles/"
|
|
383
|
+
|
|
384
|
+
throttling:
|
|
385
|
+
anonymous: AnonRateThrottle
|
|
386
|
+
authenticated: UserRateThrottle
|
|
387
|
+
custom: Extend BaseThrottle
|
|
388
|
+
|
|
389
|
+
pagination:
|
|
390
|
+
global: DEFAULT_PAGINATION_CLASS in settings
|
|
391
|
+
types: PageNumberPagination (simple), CursorPagination (large datasets)
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### 10. Deployment
|
|
395
|
+
|
|
396
|
+
```yaml
|
|
397
|
+
wsgi_asgi:
|
|
398
|
+
wsgi: gunicorn (4 workers per CPU core)
|
|
399
|
+
asgi: uvicorn with gunicorn workers (for async/WebSocket)
|
|
400
|
+
|
|
401
|
+
static_files:
|
|
402
|
+
development: Django's staticfiles
|
|
403
|
+
production: whitenoise middleware OR CDN (S3 + CloudFront)
|
|
404
|
+
command: python manage.py collectstatic --noinput
|
|
405
|
+
|
|
406
|
+
database:
|
|
407
|
+
development: SQLite (acceptable)
|
|
408
|
+
production: PostgreSQL (MUST — never SQLite in production)
|
|
409
|
+
connection_pooling: Use pgBouncer or django-db-connection-pool
|
|
410
|
+
|
|
411
|
+
migrations:
|
|
412
|
+
deploy: Run as part of CI/CD pipeline before server restart
|
|
413
|
+
zero_downtime: Use additive migrations (add nullable columns, backfill, then add constraint)
|
|
414
|
+
|
|
415
|
+
logging:
|
|
416
|
+
config: LOGGING dict in settings
|
|
417
|
+
handler: File handler in production, console in development
|
|
418
|
+
level: WARNING in production, DEBUG in development
|
|
419
|
+
|
|
420
|
+
environment_variables:
|
|
421
|
+
tool: python-decouple or django-environ
|
|
422
|
+
never: Hardcode secrets in settings files
|
|
423
|
+
|
|
424
|
+
health_check:
|
|
425
|
+
endpoint: /health/ returning 200 OK
|
|
426
|
+
checks: Database connection, cache connection, disk space
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Application
|
|
430
|
+
|
|
431
|
+
When writing Django code:
|
|
432
|
+
|
|
433
|
+
1. **Always** create a custom User model before any other models
|
|
434
|
+
2. **Always** split settings into base/development/production
|
|
435
|
+
3. **Prefer** CBVs for standard CRUD, FBVs for custom logic
|
|
436
|
+
4. **Use** select_related/prefetch_related to prevent N+1 queries
|
|
437
|
+
5. **Apply** the security checklist for every production deployment
|
|
438
|
+
6. **Test** with pytest-django and factory_boy
|
|
439
|
+
7. **Never** use `fields = '__all__'` in ModelForms or ModelSerializer
|
|
440
|
+
8. **Run** `python manage.py check --deploy` before shipping
|
package/templates/CLAUDE.md.en
CHANGED
|
@@ -174,12 +174,12 @@ Violation = immediate correction. No exception for "small changes".
|
|
|
174
174
|
project/
|
|
175
175
|
+-- CLAUDE.md # Entry point
|
|
176
176
|
+-- .claude/
|
|
177
|
-
| +-- agents/ # Subagent definitions (
|
|
178
|
-
| +-- skills/ # Skills (
|
|
177
|
+
| +-- agents/ # Subagent definitions (43 files)
|
|
178
|
+
| +-- skills/ # Skills (67 directories)
|
|
179
179
|
| +-- rules/ # Global rules (R000-R018)
|
|
180
180
|
| +-- hooks/ # Hook scripts (memory, HUD)
|
|
181
181
|
| +-- contexts/ # Context files (ecomode)
|
|
182
|
-
+-- guides/ # Reference docs (
|
|
182
|
+
+-- guides/ # Reference docs (23 topics)
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
## Orchestration
|
|
@@ -208,7 +208,7 @@ This is the core oh-my-customcode philosophy: **"No expert? CREATE one, connect
|
|
|
208
208
|
| Type | Count | Agents |
|
|
209
209
|
|------|-------|--------|
|
|
210
210
|
| SW Engineer/Language | 6 | lang-golang-expert, lang-python-expert, lang-rust-expert, lang-kotlin-expert, lang-typescript-expert, lang-java21-expert |
|
|
211
|
-
| SW Engineer/Backend |
|
|
211
|
+
| SW Engineer/Backend | 6 | be-fastapi-expert, be-springboot-expert, be-go-backend-expert, be-express-expert, be-nestjs-expert, be-django-expert |
|
|
212
212
|
| SW Engineer/Frontend | 3 | fe-vercel-agent, fe-vuejs-agent, fe-svelte-agent |
|
|
213
213
|
| SW Engineer/Tooling | 3 | tool-npm-expert, tool-optimizer, tool-bun-expert |
|
|
214
214
|
| DE Engineer | 6 | de-airflow-expert, de-dbt-expert, de-spark-expert, de-kafka-expert, de-snowflake-expert, de-pipeline-expert |
|
|
@@ -218,7 +218,7 @@ This is the core oh-my-customcode philosophy: **"No expert? CREATE one, connect
|
|
|
218
218
|
| QA Team | 3 | qa-planner, qa-writer, qa-engineer |
|
|
219
219
|
| Manager | 6 | mgr-creator, mgr-updater, mgr-supplier, mgr-gitnerd, mgr-sauron, mgr-claude-code-bible |
|
|
220
220
|
| System | 2 | sys-memory-keeper, sys-naggy |
|
|
221
|
-
| **Total** | **
|
|
221
|
+
| **Total** | **42** | |
|
|
222
222
|
|
|
223
223
|
## Agent Teams (MUST when enabled)
|
|
224
224
|
|
package/templates/CLAUDE.md.ko
CHANGED
|
@@ -174,12 +174,12 @@ oh-my-customcode로 구동됩니다.
|
|
|
174
174
|
project/
|
|
175
175
|
+-- CLAUDE.md # 진입점
|
|
176
176
|
+-- .claude/
|
|
177
|
-
| +-- agents/ # 서브에이전트 정의 (
|
|
178
|
-
| +-- skills/ # 스킬 (
|
|
177
|
+
| +-- agents/ # 서브에이전트 정의 (43 파일)
|
|
178
|
+
| +-- skills/ # 스킬 (67 디렉토리)
|
|
179
179
|
| +-- rules/ # 전역 규칙 (R000-R018)
|
|
180
180
|
| +-- hooks/ # 훅 스크립트 (메모리, HUD)
|
|
181
181
|
| +-- contexts/ # 컨텍스트 파일 (ecomode)
|
|
182
|
-
+-- guides/ # 레퍼런스 문서 (
|
|
182
|
+
+-- guides/ # 레퍼런스 문서 (23 토픽)
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
## 오케스트레이션
|
|
@@ -208,7 +208,7 @@ project/
|
|
|
208
208
|
| 타입 | 수량 | 에이전트 |
|
|
209
209
|
|------|------|----------|
|
|
210
210
|
| SW Engineer/Language | 6 | lang-golang-expert, lang-python-expert, lang-rust-expert, lang-kotlin-expert, lang-typescript-expert, lang-java21-expert |
|
|
211
|
-
| SW Engineer/Backend |
|
|
211
|
+
| SW Engineer/Backend | 6 | be-fastapi-expert, be-springboot-expert, be-go-backend-expert, be-express-expert, be-nestjs-expert, be-django-expert |
|
|
212
212
|
| SW Engineer/Frontend | 3 | fe-vercel-agent, fe-vuejs-agent, fe-svelte-agent |
|
|
213
213
|
| SW Engineer/Tooling | 3 | tool-npm-expert, tool-optimizer, tool-bun-expert |
|
|
214
214
|
| DE Engineer | 6 | de-airflow-expert, de-dbt-expert, de-spark-expert, de-kafka-expert, de-snowflake-expert, de-pipeline-expert |
|
|
@@ -218,7 +218,7 @@ project/
|
|
|
218
218
|
| QA Team | 3 | qa-planner, qa-writer, qa-engineer |
|
|
219
219
|
| Manager | 6 | mgr-creator, mgr-updater, mgr-supplier, mgr-gitnerd, mgr-sauron, mgr-claude-code-bible |
|
|
220
220
|
| System | 2 | sys-memory-keeper, sys-naggy |
|
|
221
|
-
| **총계** | **
|
|
221
|
+
| **총계** | **42** | |
|
|
222
222
|
|
|
223
223
|
## Agent Teams (MUST when enabled)
|
|
224
224
|
|