claudia-mentor 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +9 -0
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/commands/claudia-health.md +93 -0
- package/commands/claudia.md +27 -0
- package/config/defaults.json +25 -0
- package/hooks/hooks.json +77 -0
- package/hooks/scripts/check-accessibility.py +169 -0
- package/hooks/scripts/check-deps.py +119 -0
- package/hooks/scripts/check-dockerfile.py +176 -0
- package/hooks/scripts/check-git-hygiene.py +144 -0
- package/hooks/scripts/check-license.py +166 -0
- package/hooks/scripts/check-practices.py +169 -0
- package/hooks/scripts/check-secrets.sh +116 -0
- package/package.json +30 -0
- package/scripts/postinstall.js +29 -0
- package/skills/claudia-api/SKILL.md +96 -0
- package/skills/claudia-api/references/api-patterns.md +261 -0
- package/skills/claudia-api/references/graphql-grpc-trpc.md +161 -0
- package/skills/claudia-api/references/rest-design.md +234 -0
- package/skills/claudia-data/SKILL.md +85 -0
- package/skills/claudia-data/references/migrations-indexing.md +238 -0
- package/skills/claudia-data/references/schema-patterns.md +313 -0
- package/skills/claudia-databases/SKILL.md +77 -0
- package/skills/claudia-databases/references/sql-vs-nosql.md +72 -0
- package/skills/claudia-databases/references/time-series-graph.md +142 -0
- package/skills/claudia-databases/references/vector-databases.md +90 -0
- package/skills/claudia-devops/SKILL.md +111 -0
- package/skills/claudia-devops/references/cicd-pipelines.md +223 -0
- package/skills/claudia-devops/references/monitoring-incidents.md +217 -0
- package/skills/claudia-frontend/SKILL.md +99 -0
- package/skills/claudia-frontend/references/css-bundling.md +241 -0
- package/skills/claudia-frontend/references/frameworks-rendering.md +211 -0
- package/skills/claudia-frontend/references/state-management.md +195 -0
- package/skills/claudia-infrastructure/SKILL.md +108 -0
- package/skills/claudia-infrastructure/references/cloud-providers.md +136 -0
- package/skills/claudia-infrastructure/references/containers-orchestration.md +161 -0
- package/skills/claudia-infrastructure/references/serverless-edge.md +158 -0
- package/skills/claudia-mentor/SKILL.md +107 -0
- package/skills/claudia-mentor/references/personality.md +42 -0
- package/skills/claudia-mentor/references/prompt-coaching.md +60 -0
- package/skills/claudia-mentor/references/stack-detection.md +86 -0
- package/skills/claudia-performance/SKILL.md +111 -0
- package/skills/claudia-performance/references/backend-performance.md +306 -0
- package/skills/claudia-performance/references/frontend-performance.md +317 -0
- package/skills/claudia-security/SKILL.md +80 -0
- package/skills/claudia-security/references/auth-patterns.md +68 -0
- package/skills/claudia-security/references/secrets-management.md +58 -0
- package/skills/claudia-security/references/tees-sandboxing.md +75 -0
- package/skills/claudia-testing/SKILL.md +112 -0
- package/skills/claudia-testing/references/mocking-patterns.md +202 -0
- package/skills/claudia-testing/references/testing-approaches.md +144 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "claudia-mentor",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Proactive technology mentor, security advisor, and prompt coach for Claude Code. Catches bad practices, advises on architecture decisions, and coaches better prompting.",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Regan O'Malley",
|
|
7
|
+
"email": "regan@reganomalley.com"
|
|
8
|
+
}
|
|
9
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Regan O'Malley
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Claudia: Proactive Mentor Plugin for Claude Code
|
|
2
|
+
|
|
3
|
+
A Claude Code plugin that acts as your technology mentor, security advisor, and prompt coach. Claudia fills the gaps between writing code and making good technology decisions.
|
|
4
|
+
|
|
5
|
+
**10 knowledge domains. 7 automated hooks. Context-aware advice.**
|
|
6
|
+
|
|
7
|
+
## What Claudia Does
|
|
8
|
+
|
|
9
|
+
- **Technology advising** -- Helps you choose databases, frameworks, APIs, infrastructure, and architecture patterns with clear trade-offs
|
|
10
|
+
- **Security guidance** -- Catches hardcoded secrets before they ship, advises on auth patterns and secrets management
|
|
11
|
+
- **Anti-pattern detection** -- Warns about common mistakes across code, Docker, dependencies, accessibility, and git hygiene
|
|
12
|
+
- **Prompt coaching** -- Detects vague prompts and suggests improvements to get better results from Claude
|
|
13
|
+
- **Context-aware** -- Reads your package.json, configs, and stack to give specific advice, not generic recommendations
|
|
14
|
+
- **Project health audits** -- `/claudia-health` scans your project for security, testing, dependency, and architecture issues
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Clone the plugin
|
|
20
|
+
git clone https://github.com/reganomalley/claudia.git ~/.claude/plugins/claudia
|
|
21
|
+
|
|
22
|
+
# Or install from npm
|
|
23
|
+
npm install -g claudia-mentor
|
|
24
|
+
|
|
25
|
+
# Enable in Claude Code
|
|
26
|
+
claude plugin add ~/.claude/plugins/claudia
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
### Slash Commands
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
/claudia what database should I use for time-series IoT data?
|
|
35
|
+
/claudia is JWT or session-based auth better for my SPA?
|
|
36
|
+
/claudia should I use REST or GraphQL for my mobile app?
|
|
37
|
+
/claudia how should I structure my CI/CD pipeline?
|
|
38
|
+
/claudia-health # Run a full project health audit
|
|
39
|
+
/claudia-health security # Focus on security issues
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Automatic (Model-Invoked)
|
|
43
|
+
|
|
44
|
+
Claudia automatically activates when you:
|
|
45
|
+
- Make technology decisions ("should I use MongoDB or Postgres?")
|
|
46
|
+
- Discuss architecture ("how should I structure this microservice?")
|
|
47
|
+
- Choose between frameworks ("React or Svelte for this project?")
|
|
48
|
+
- Write suboptimal prompts ("make it better")
|
|
49
|
+
- Introduce security anti-patterns
|
|
50
|
+
|
|
51
|
+
### Hooks (Always Active)
|
|
52
|
+
|
|
53
|
+
**Secret detection** (blocks):
|
|
54
|
+
- AWS access keys, OpenAI/Stripe keys, GitHub tokens, GitLab PATs, Slack tokens
|
|
55
|
+
- Hardcoded passwords, secrets, and API keys
|
|
56
|
+
- Database connection strings with credentials
|
|
57
|
+
- Private keys
|
|
58
|
+
|
|
59
|
+
**Anti-pattern warnings** (advisory):
|
|
60
|
+
- `eval()` usage, `document.write()`, `innerHTML`
|
|
61
|
+
- `console.log` in production code
|
|
62
|
+
- Empty catch blocks
|
|
63
|
+
- HTTP URLs (non-HTTPS), disabled SSL verification
|
|
64
|
+
- SQL string concatenation
|
|
65
|
+
- `chmod 777`
|
|
66
|
+
- TODO/FIXME markers in new code
|
|
67
|
+
|
|
68
|
+
**Dependency audit** (advisory):
|
|
69
|
+
- Deprecated packages (moment, request, gulp)
|
|
70
|
+
- Compromised packages (colors, faker, event-stream)
|
|
71
|
+
- Trivial packages (is-odd, is-even, left-pad)
|
|
72
|
+
|
|
73
|
+
**Dockerfile lint** (advisory):
|
|
74
|
+
- Running as root, large base images, `:latest` tag
|
|
75
|
+
- Missing multi-stage builds, secrets in ENV
|
|
76
|
+
- npm install without --production
|
|
77
|
+
|
|
78
|
+
**Git hygiene** (blocks/advisory):
|
|
79
|
+
- Writing to .env files (blocks)
|
|
80
|
+
- Merge conflict markers in code (blocks)
|
|
81
|
+
- Large binary files (advisory)
|
|
82
|
+
|
|
83
|
+
**Accessibility** (advisory):
|
|
84
|
+
- Images without alt text
|
|
85
|
+
- Inputs without labels
|
|
86
|
+
- Icon-only buttons without aria-label
|
|
87
|
+
- Click handlers on non-interactive elements
|
|
88
|
+
- Positive tabIndex values
|
|
89
|
+
|
|
90
|
+
**License compliance** (advisory):
|
|
91
|
+
- Copyleft dependencies (GPL, AGPL, SSPL) in permissive-licensed projects
|
|
92
|
+
|
|
93
|
+
## Knowledge Domains
|
|
94
|
+
|
|
95
|
+
### Databases (`claudia-databases`)
|
|
96
|
+
- SQL vs NoSQL decision framework
|
|
97
|
+
- Vector databases for RAG/embeddings (pgvector, Pinecone, Qdrant)
|
|
98
|
+
- Time-series and graph database selection
|
|
99
|
+
- "Just use Postgres" rule (and when to break it)
|
|
100
|
+
|
|
101
|
+
### Security (`claudia-security`)
|
|
102
|
+
- Authentication patterns (session, JWT, OAuth, passkeys)
|
|
103
|
+
- Secrets management lifecycle
|
|
104
|
+
- TEEs and sandboxing
|
|
105
|
+
- Common security mistakes with fixes
|
|
106
|
+
|
|
107
|
+
### Infrastructure (`claudia-infrastructure`)
|
|
108
|
+
- AWS vs GCP vs Azure vs self-host
|
|
109
|
+
- Container orchestration (Docker, ECS, Cloud Run, k8s)
|
|
110
|
+
- Serverless decision framework
|
|
111
|
+
- Edge computing and cost estimation
|
|
112
|
+
|
|
113
|
+
### Frontend (`claudia-frontend`)
|
|
114
|
+
- Framework selection (React, Vue, Svelte, Solid, Angular)
|
|
115
|
+
- SSR vs SPA vs SSG vs islands architecture
|
|
116
|
+
- State management (when to use what)
|
|
117
|
+
- CSS approaches, bundlers, Core Web Vitals
|
|
118
|
+
|
|
119
|
+
### API Design (`claudia-api`)
|
|
120
|
+
- REST vs GraphQL vs gRPC vs tRPC
|
|
121
|
+
- API versioning, pagination, error handling
|
|
122
|
+
- Webhook design, rate limiting
|
|
123
|
+
- Real-time patterns (WebSockets, SSE, polling)
|
|
124
|
+
|
|
125
|
+
### Testing (`claudia-testing`)
|
|
126
|
+
- Test pyramid and what to test at each level
|
|
127
|
+
- Framework comparison (Jest, Vitest, Playwright)
|
|
128
|
+
- Mocking patterns (and when NOT to mock)
|
|
129
|
+
- Testing strategy by app type
|
|
130
|
+
|
|
131
|
+
### Performance (`claudia-performance`)
|
|
132
|
+
- "Measure before you optimize" framework
|
|
133
|
+
- Backend: N+1 queries, caching, connection pooling
|
|
134
|
+
- Frontend: Core Web Vitals, bundle optimization, image/font loading
|
|
135
|
+
- Profiling tools for Node.js and Python
|
|
136
|
+
|
|
137
|
+
### DevOps (`claudia-devops`)
|
|
138
|
+
- CI/CD pipeline design (GitHub Actions patterns)
|
|
139
|
+
- Deployment strategies (rolling, blue-green, canary)
|
|
140
|
+
- Monitoring hierarchy and the four golden signals
|
|
141
|
+
- Incident response and SLI/SLO framework
|
|
142
|
+
|
|
143
|
+
### Data Modeling (`claudia-data`)
|
|
144
|
+
- Schema design patterns (multi-tenancy, soft deletes, hierarchical data)
|
|
145
|
+
- Migration safety (zero-downtime patterns)
|
|
146
|
+
- Indexing strategy (B-tree, GIN, partial, composite)
|
|
147
|
+
- Normalization, denormalization, and anti-patterns
|
|
148
|
+
|
|
149
|
+
### Prompt Coaching (built into mentor)
|
|
150
|
+
- Detects vague or underspecified prompts
|
|
151
|
+
- Suggests improvements across 5 quality dimensions
|
|
152
|
+
- Offers rewritten versions
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
Override Claudia's personality and proactivity level:
|
|
157
|
+
|
|
158
|
+
### Global (`~/.claude/claudia.json`)
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"proactivity": "high",
|
|
163
|
+
"personality": {
|
|
164
|
+
"tone": "casual"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Per-project (`.claudia.json` in project root)
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"proactivity": "low",
|
|
174
|
+
"hooks": {
|
|
175
|
+
"check_practices": {
|
|
176
|
+
"enabled": false
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Proactivity Levels
|
|
183
|
+
|
|
184
|
+
| Level | Behavior |
|
|
185
|
+
|-------|----------|
|
|
186
|
+
| `low` | Only responds when you use `/claudia` |
|
|
187
|
+
| `moderate` | Proactive on security issues and major anti-patterns (default) |
|
|
188
|
+
| `high` | Flags any suboptimal pattern or technology decision |
|
|
189
|
+
|
|
190
|
+
## Contributing
|
|
191
|
+
|
|
192
|
+
Claudia is designed for community contributions. The easiest ways to contribute:
|
|
193
|
+
|
|
194
|
+
### Add Reference Files
|
|
195
|
+
Drop a new `.md` file in any `references/` directory. Follow the voice: opinionated, direct, explains why, uses concrete examples.
|
|
196
|
+
|
|
197
|
+
### Add Anti-Patterns
|
|
198
|
+
Add entries to any hook script in `hooks/scripts/`.
|
|
199
|
+
|
|
200
|
+
### New Knowledge Domains
|
|
201
|
+
|
|
202
|
+
Use the scaffolding tool:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
./scripts/create-domain.sh architecture
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This creates the directory structure and template files. Fill in the SKILL.md, add reference files, and update the mentor's routing table.
|
|
209
|
+
|
|
210
|
+
### Guidelines
|
|
211
|
+
- Be opinionated -- "it depends" without follow-up is not helpful
|
|
212
|
+
- Use decision trees and comparison tables
|
|
213
|
+
- Explain the "why" behind every recommendation
|
|
214
|
+
- Include "when NOT to use this" alongside recommendations
|
|
215
|
+
- Keep SKILL.md under ~2000 words, put depth in references
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
|
|
219
|
+
MIT
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run a health check on the current project -- security, testing, architecture, dependencies
|
|
3
|
+
argument-hint: [optional: focus area like "security" or "deps"]
|
|
4
|
+
allowed-tools: [Read, Glob, Grep, Bash, WebSearch]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Claudia Health Check
|
|
8
|
+
|
|
9
|
+
You are Claudia, running a project health audit. Scan the current project and report findings.
|
|
10
|
+
|
|
11
|
+
**Focus area (optional):** $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
## Audit Process
|
|
14
|
+
|
|
15
|
+
### 1. Discover the Stack
|
|
16
|
+
|
|
17
|
+
Read `package.json` (or `pyproject.toml`, `go.mod`, etc.) and scan for config files:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
Glob: **/package.json, **/tsconfig.json, **/Dockerfile, **/docker-compose.yml,
|
|
21
|
+
**/.env.example, **/prisma/schema.prisma, **/.github/workflows/*.yml,
|
|
22
|
+
**/vite.config.*, **/next.config.*, **/vitest.config.*, **/jest.config.*,
|
|
23
|
+
**/.eslintrc.*, **/tailwind.config.*
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Run Checks
|
|
27
|
+
|
|
28
|
+
**Security:**
|
|
29
|
+
- [ ] .env file is gitignored (check `.gitignore`)
|
|
30
|
+
- [ ] No hardcoded secrets in source (grep for `sk-`, `AKIA`, `password =`)
|
|
31
|
+
- [ ] Dependencies don't have known vulnerabilities (run `npm audit --json` if Node.js)
|
|
32
|
+
- [ ] HTTPS enforced in configs
|
|
33
|
+
- [ ] CORS configured (not `*` in production)
|
|
34
|
+
- [ ] Auth library used (not hand-rolled)
|
|
35
|
+
|
|
36
|
+
**Testing:**
|
|
37
|
+
- [ ] Test framework configured (jest.config, vitest.config, pytest.ini)
|
|
38
|
+
- [ ] Tests exist (glob for `**/*.test.*`, `**/*.spec.*`, `**/test_*.py`)
|
|
39
|
+
- [ ] CI runs tests (check `.github/workflows/`)
|
|
40
|
+
- [ ] Test coverage configured
|
|
41
|
+
|
|
42
|
+
**Dependencies:**
|
|
43
|
+
- [ ] Lock file exists and tracked (package-lock.json, yarn.lock, pnpm-lock.yaml)
|
|
44
|
+
- [ ] No deprecated packages (check against known list)
|
|
45
|
+
- [ ] Node/Python version pinned (engines in package.json, .python-version, .nvmrc)
|
|
46
|
+
- [ ] devDependencies not in production dependencies
|
|
47
|
+
|
|
48
|
+
**Architecture:**
|
|
49
|
+
- [ ] README exists
|
|
50
|
+
- [ ] Environment variables documented (.env.example)
|
|
51
|
+
- [ ] Dockerfile uses multi-stage builds (if containerized)
|
|
52
|
+
- [ ] TypeScript strict mode enabled (if using TS)
|
|
53
|
+
- [ ] Linting configured
|
|
54
|
+
|
|
55
|
+
**Performance:**
|
|
56
|
+
- [ ] Images optimized (next/image, responsive images)
|
|
57
|
+
- [ ] Bundle analysis available
|
|
58
|
+
- [ ] Caching configured (Redis, CDN, HTTP cache headers)
|
|
59
|
+
|
|
60
|
+
### 3. Report Format
|
|
61
|
+
|
|
62
|
+
Present findings as a health report:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
## Project Health: [project-name]
|
|
66
|
+
|
|
67
|
+
**Stack:** [detected framework, DB, hosting]
|
|
68
|
+
**Overall:** [Good / Needs Attention / Critical Issues]
|
|
69
|
+
|
|
70
|
+
### Security [score/5]
|
|
71
|
+
- [finding]
|
|
72
|
+
- [finding]
|
|
73
|
+
|
|
74
|
+
### Testing [score/5]
|
|
75
|
+
- [finding]
|
|
76
|
+
|
|
77
|
+
### Dependencies [score/5]
|
|
78
|
+
- [finding]
|
|
79
|
+
|
|
80
|
+
### Architecture [score/5]
|
|
81
|
+
- [finding]
|
|
82
|
+
|
|
83
|
+
### Top 3 Actions
|
|
84
|
+
1. [most impactful fix]
|
|
85
|
+
2. [second most impactful]
|
|
86
|
+
3. [third]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 4. Personality
|
|
90
|
+
|
|
91
|
+
Be direct. Don't soften findings. If something is bad, say it's bad and say how to fix it. But also acknowledge what's done well -- a clean security setup deserves a note.
|
|
92
|
+
|
|
93
|
+
If the user specified a focus area ($ARGUMENTS), go deeper on that area and lighter on others.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Ask Claudia for technology advice, architecture guidance, or prompt coaching
|
|
3
|
+
argument-hint: <question about databases, security, architecture, or prompts>
|
|
4
|
+
allowed-tools: [Read, Glob, Grep, WebSearch, WebFetch]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Claudia: Technology Mentor
|
|
8
|
+
|
|
9
|
+
You are Claudia, a proactive technology mentor. The user is asking you a direct question.
|
|
10
|
+
|
|
11
|
+
**User's question:** $ARGUMENTS
|
|
12
|
+
|
|
13
|
+
## How to Respond
|
|
14
|
+
|
|
15
|
+
1. Read `${CLAUDE_PLUGIN_ROOT}/skills/claudia-mentor/SKILL.md` for your personality and routing logic.
|
|
16
|
+
|
|
17
|
+
2. Determine the domain:
|
|
18
|
+
- **Database question** → Read `${CLAUDE_PLUGIN_ROOT}/skills/claudia-databases/SKILL.md` and relevant references
|
|
19
|
+
- **Security question** → Read `${CLAUDE_PLUGIN_ROOT}/skills/claudia-security/SKILL.md` and relevant references
|
|
20
|
+
- **Prompt quality** → Read `${CLAUDE_PLUGIN_ROOT}/skills/claudia-mentor/references/prompt-coaching.md`
|
|
21
|
+
- **General architecture/infra** → Use your knowledge + WebSearch for current information
|
|
22
|
+
|
|
23
|
+
3. Check for personality overrides at `~/.claude/claudia.json` or `.claudia.json` in the current project.
|
|
24
|
+
|
|
25
|
+
4. Respond following Claudia's personality: direct, explains why, uses analogies, admits uncertainty. Keep it focused -- direct answer, reasoning, trade-offs, next step.
|
|
26
|
+
|
|
27
|
+
5. If the question is outside your knowledge base, use WebSearch to find current authoritative information. Clearly distinguish between what you know and what you looked up.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"personality": {
|
|
3
|
+
"name": "Claudia",
|
|
4
|
+
"tone": "direct",
|
|
5
|
+
"style": "explains-why",
|
|
6
|
+
"uses_analogies": true,
|
|
7
|
+
"admits_uncertainty": true
|
|
8
|
+
},
|
|
9
|
+
"proactivity": "moderate",
|
|
10
|
+
"proactivity_levels": {
|
|
11
|
+
"low": "Only responds when invoked via /claudia",
|
|
12
|
+
"moderate": "Proactive on security issues and major anti-patterns",
|
|
13
|
+
"high": "Proactive on any suboptimal pattern or decision"
|
|
14
|
+
},
|
|
15
|
+
"hooks": {
|
|
16
|
+
"check_secrets": {
|
|
17
|
+
"enabled": true,
|
|
18
|
+
"action": "block"
|
|
19
|
+
},
|
|
20
|
+
"check_practices": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"action": "advisory"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/hooks/hooks.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "Claudia mentor hooks: security, anti-patterns, dependencies, Docker, git hygiene, accessibility, and license compliance",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-secrets.sh",
|
|
10
|
+
"timeout": 10
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"hooks": [
|
|
17
|
+
{
|
|
18
|
+
"type": "command",
|
|
19
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-practices.py",
|
|
20
|
+
"timeout": 10
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"hooks": [
|
|
27
|
+
{
|
|
28
|
+
"type": "command",
|
|
29
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-deps.py",
|
|
30
|
+
"timeout": 10
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"hooks": [
|
|
37
|
+
{
|
|
38
|
+
"type": "command",
|
|
39
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-dockerfile.py",
|
|
40
|
+
"timeout": 10
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"hooks": [
|
|
47
|
+
{
|
|
48
|
+
"type": "command",
|
|
49
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-git-hygiene.py",
|
|
50
|
+
"timeout": 10
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"hooks": [
|
|
57
|
+
{
|
|
58
|
+
"type": "command",
|
|
59
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-accessibility.py",
|
|
60
|
+
"timeout": 10
|
|
61
|
+
}
|
|
62
|
+
],
|
|
63
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"hooks": [
|
|
67
|
+
{
|
|
68
|
+
"type": "command",
|
|
69
|
+
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/check-license.py",
|
|
70
|
+
"timeout": 10
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"matcher": "Edit|Write|MultiEdit"
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Claudia: check-accessibility.py
|
|
4
|
+
PreToolUse hook that warns on accessibility issues in HTML/JSX writes.
|
|
5
|
+
Advisory only (exit 0 with systemMessage), never blocks.
|
|
6
|
+
Session-aware dedup.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
import re
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
# Accessibility patterns to check
|
|
15
|
+
# (pattern_regex, negative_pattern, description, advice, pattern_id)
|
|
16
|
+
# negative_pattern: if this matches, skip the warning (false positive prevention)
|
|
17
|
+
A11Y_PATTERNS = [
|
|
18
|
+
(
|
|
19
|
+
r'<img\b(?![^>]*\balt\b)',
|
|
20
|
+
None,
|
|
21
|
+
"Image without alt attribute",
|
|
22
|
+
"All `<img>` elements need an `alt` attribute. Use descriptive text, or `alt=\"\"` for decorative images.",
|
|
23
|
+
"a11y_img_alt",
|
|
24
|
+
),
|
|
25
|
+
(
|
|
26
|
+
r'<input\b(?![^>]*\b(?:aria-label|aria-labelledby|id\s*=\s*["\'][^"\']+["\'])\b)(?![^>]*\btype\s*=\s*["\'](?:hidden|submit|button|reset)["\'])',
|
|
27
|
+
r'<label\b',
|
|
28
|
+
"Form input without label or aria-label",
|
|
29
|
+
"Inputs need associated labels. Use `<label htmlFor>`, `aria-label`, or `aria-labelledby`.",
|
|
30
|
+
"a11y_input_label",
|
|
31
|
+
),
|
|
32
|
+
(
|
|
33
|
+
r'<button\b(?![^>]*\b(?:aria-label|aria-labelledby)\b)[^>]*>\s*<(?:img|svg|i|span\s+class)',
|
|
34
|
+
None,
|
|
35
|
+
"Icon-only button without accessible label",
|
|
36
|
+
"Buttons with only icons need `aria-label` to describe their action (e.g., `aria-label=\"Close\"`).",
|
|
37
|
+
"a11y_icon_button",
|
|
38
|
+
),
|
|
39
|
+
(
|
|
40
|
+
r'onClick\s*=\s*\{[^}]+\}\s*(?:className|style)',
|
|
41
|
+
r'<(?:button|a|input|select|textarea)\b',
|
|
42
|
+
"Click handler on non-interactive element",
|
|
43
|
+
"Use `<button>` for clickable elements, not `<div onClick>`. Buttons are keyboard-accessible and announced by screen readers.",
|
|
44
|
+
"a11y_div_click",
|
|
45
|
+
),
|
|
46
|
+
(
|
|
47
|
+
r'tabIndex\s*=\s*["\']?[1-9]',
|
|
48
|
+
None,
|
|
49
|
+
"Positive tabIndex value",
|
|
50
|
+
"Avoid positive `tabIndex` values. They override natural tab order and confuse keyboard users. Use `tabIndex={0}` or `-1`.",
|
|
51
|
+
"a11y_tabindex",
|
|
52
|
+
),
|
|
53
|
+
(
|
|
54
|
+
r'<a\b(?![^>]*\bhref\b)',
|
|
55
|
+
None,
|
|
56
|
+
"Anchor tag without href",
|
|
57
|
+
"Use `<button>` for actions, `<a href>` for navigation. An `<a>` without `href` is not keyboard-accessible.",
|
|
58
|
+
"a11y_anchor_href",
|
|
59
|
+
),
|
|
60
|
+
(
|
|
61
|
+
r'autoFocus|autofocus',
|
|
62
|
+
None,
|
|
63
|
+
"autoFocus attribute used",
|
|
64
|
+
"Avoid `autoFocus` -- it can disorient screen reader users and disrupt keyboard navigation. Let users control focus.",
|
|
65
|
+
"a11y_autofocus",
|
|
66
|
+
),
|
|
67
|
+
(
|
|
68
|
+
r'<(?:h[1-6])\b[^>]*>\s*</(?:h[1-6])>',
|
|
69
|
+
None,
|
|
70
|
+
"Empty heading element",
|
|
71
|
+
"Headings should contain text content. Empty headings confuse screen readers navigating by heading structure.",
|
|
72
|
+
"a11y_empty_heading",
|
|
73
|
+
),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
# File extensions to check
|
|
77
|
+
A11Y_EXTENSIONS = {'.html', '.htm', '.jsx', '.tsx', '.vue', '.svelte', '.astro'}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def get_state_file(session_id):
|
|
81
|
+
return os.path.expanduser(f"~/.claude/claudia_a11y_state_{session_id}.json")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def load_state(session_id):
|
|
85
|
+
state_file = get_state_file(session_id)
|
|
86
|
+
if os.path.exists(state_file):
|
|
87
|
+
try:
|
|
88
|
+
with open(state_file) as f:
|
|
89
|
+
return set(json.load(f))
|
|
90
|
+
except (json.JSONDecodeError, IOError):
|
|
91
|
+
return set()
|
|
92
|
+
return set()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def save_state(session_id, shown):
|
|
96
|
+
state_file = get_state_file(session_id)
|
|
97
|
+
try:
|
|
98
|
+
os.makedirs(os.path.dirname(state_file), exist_ok=True)
|
|
99
|
+
with open(state_file, "w") as f:
|
|
100
|
+
json.dump(list(shown), f)
|
|
101
|
+
except IOError:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def extract_content(tool_name, tool_input):
|
|
106
|
+
if tool_name == "Write":
|
|
107
|
+
return tool_input.get("content", "")
|
|
108
|
+
elif tool_name == "Edit":
|
|
109
|
+
return tool_input.get("new_string", "")
|
|
110
|
+
elif tool_name == "MultiEdit":
|
|
111
|
+
edits = tool_input.get("edits", [])
|
|
112
|
+
return " ".join(e.get("new_string", "") for e in edits)
|
|
113
|
+
return ""
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def main():
|
|
117
|
+
try:
|
|
118
|
+
input_data = json.loads(sys.stdin.read())
|
|
119
|
+
except json.JSONDecodeError:
|
|
120
|
+
sys.exit(0)
|
|
121
|
+
|
|
122
|
+
session_id = input_data.get("session_id", "default")
|
|
123
|
+
tool_name = input_data.get("tool_name", "")
|
|
124
|
+
tool_input = input_data.get("tool_input", {})
|
|
125
|
+
file_path = tool_input.get("file_path", "")
|
|
126
|
+
|
|
127
|
+
if tool_name not in ("Edit", "Write", "MultiEdit"):
|
|
128
|
+
sys.exit(0)
|
|
129
|
+
|
|
130
|
+
# Only check HTML/JSX/Vue/Svelte files
|
|
131
|
+
_, ext = os.path.splitext(file_path)
|
|
132
|
+
if ext.lower() not in A11Y_EXTENSIONS:
|
|
133
|
+
sys.exit(0)
|
|
134
|
+
|
|
135
|
+
content = extract_content(tool_name, tool_input)
|
|
136
|
+
if not content:
|
|
137
|
+
sys.exit(0)
|
|
138
|
+
|
|
139
|
+
# Skip test files
|
|
140
|
+
if any(x in file_path for x in ['.test.', '.spec.', '/test/', '/tests/', 'fixture', 'mock', '__test__']):
|
|
141
|
+
sys.exit(0)
|
|
142
|
+
|
|
143
|
+
shown = load_state(session_id)
|
|
144
|
+
warnings = []
|
|
145
|
+
|
|
146
|
+
for entry in A11Y_PATTERNS:
|
|
147
|
+
pattern, negative, description, advice, pattern_id = entry
|
|
148
|
+
|
|
149
|
+
if re.search(pattern, content, re.IGNORECASE):
|
|
150
|
+
# If there's a negative pattern and it matches, skip
|
|
151
|
+
if negative and re.search(negative, content, re.IGNORECASE):
|
|
152
|
+
continue
|
|
153
|
+
|
|
154
|
+
warning_key = f"{file_path}-{pattern_id}"
|
|
155
|
+
if warning_key not in shown:
|
|
156
|
+
shown.add(warning_key)
|
|
157
|
+
warnings.append(f"- {description}: {advice}")
|
|
158
|
+
|
|
159
|
+
if warnings:
|
|
160
|
+
save_state(session_id, shown)
|
|
161
|
+
message = "Claudia noticed some accessibility concerns:\n" + "\n".join(warnings)
|
|
162
|
+
output = json.dumps({"systemMessage": message})
|
|
163
|
+
print(output)
|
|
164
|
+
|
|
165
|
+
sys.exit(0)
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
if __name__ == "__main__":
|
|
169
|
+
main()
|