Skip to content

Commit bedb237

Browse files
committed
feat: add Claude Code skills and expand agent documentation
Add three Claude Code skills (generate-commit-message, prepare-for-pull-request, review-pr) for workflow automation. Create CLAUDE.md with core rules. Expand AGENTS.md with architecture, project layout, tools overview, configuration reference, and tech stack details.
1 parent e7956f3 commit bedb237

5 files changed

Lines changed: 507 additions & 8 deletions

File tree

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
name: generate-commit-message
3+
description: Use git diff to analyze changes and generate a conventional commit message following this project's conventions from AGENTS.md
4+
disable-model-invocation: true
5+
allowed-tools: Bash(git diff *) Bash(git status) Bash(git log *)
6+
---
7+
8+
Generate a commit message for the current changes by following these steps:
9+
10+
## 1. Parse arguments
11+
12+
`$ARGUMENTS` may contain additional context for the commit message.
13+
14+
## 2. Gather context
15+
16+
- Run `git status` to see what files are staged vs unstaged.
17+
- Run `git diff --cached` to see staged changes. If nothing is staged, inform the user that nothing is staged and stop — do not fall back to unstaged changes.
18+
- Run `git log --oneline -10` to see recent commit messages for style reference.
19+
20+
## 3. Analyze the changes
21+
22+
Identify the **type** based on the nature of the change. This project uses both standard Conventional Commit types and module-level types:
23+
24+
**Standard types:** `feat`, `fix`, `refactor`, `test`, `docs`, `ci`, `chore`, `perf`, `style`, `build`
25+
26+
**Module-level types** — used when the change is entirely within one of these subsystems:
27+
- `run_script` — changes scoped to `tools/run_script.py` or the run_script workflow
28+
- `eval` — changes to the gatekeeper evaluation/benchmark system
29+
30+
Identify the **scope** from the area of the codebase affected. Use these established scopes:
31+
32+
| Scope | When to use |
33+
|-------|------------|
34+
| `ssh` | `connection/ssh.py` or SSH-related logic |
35+
| `run_script` | `tools/run_script.py` (use as scope with `fix`/`feat`, or as standalone type) |
36+
| `deps` | dependency version bumps (`chore(deps)`) |
37+
| `ci` | CI/CD workflows in `.github/` |
38+
| `scripts` | utility scripts in `scripts/` |
39+
| `functional` | functional/integration tests in `tests/functional/` |
40+
| `storage` | `tools/storage.py` or storage-related tools |
41+
| `models` | `models.py` data model changes |
42+
| `validation` | `utils/validation.py` input validation |
43+
| `mcp-apps(ui)` | React UI in `mcp-app/` (nested scope) |
44+
45+
**Scope rules:**
46+
- Omit scope when the change spans multiple areas or no established scope fits.
47+
- When using a module-level type like `run_script:` or `eval:`, do not add a redundant scope.
48+
- For dependency updates, always use `chore(deps):`.
49+
50+
## 4. Generate the commit message
51+
52+
Follow the [Conventional Commits](https://www.conventionalcommits.org/) format:
53+
54+
```
55+
type(scope): short imperative description
56+
```
57+
58+
Or for module-level types:
59+
60+
```
61+
type: short imperative description
62+
```
63+
64+
**Subject line rules:**
65+
- Imperative mood, lowercase start, no period at the end.
66+
- Under 72 characters total.
67+
- Focus on **why** or **what changed**, not how.
68+
- If there is a `$ARGUMENTS` value, use it as additional context for the message.
69+
70+
**Body** (optional — only when the subject line alone doesn't capture the reasoning):
71+
```
72+
73+
Motivation and context behind the change.
74+
Wrap at 72 characters per line.
75+
```
76+
77+
## 5. Present the result
78+
79+
Show the generated commit message in a code block so the user can review it. Ask the user if they'd like to:
80+
1. Use the message as-is (run `git commit` with it)
81+
2. Edit it before committing
82+
3. Regenerate with different emphasis
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
---
2+
name: prepare-for-pull-request
3+
description: Run make verify, then summarize changes since a given commit SHA into a PR description
4+
disable-model-invocation: true
5+
allowed-tools: Bash(make *) Bash(git diff *) Bash(git log *) Bash(git status) Bash(git rev-parse *) Bash(git reflog *)
6+
argument-hint: "[base-commit-sha]"
7+
---
8+
9+
Prepare a pull request description by verifying the code and summarizing all changes since a base commit.
10+
11+
## Step 0: Determine the base ref
12+
13+
If `$ARGUMENTS` is provided (e.g. a SHA, `main`, `HEAD~3`), use it as the base ref.
14+
15+
If `$ARGUMENTS` is empty, auto-detect the branch point:
16+
17+
1. Get the current branch name: `git rev-parse --abbrev-ref HEAD`
18+
2. Find where this branch was created from using reflog: `git reflog show <current-branch> --format='%H %gs'`
19+
3. Look for the entry with `branch: Created from` in the reflog output — the SHA on that line is where the branch was born.
20+
4. Use that SHA as the base ref. Tell the user which base ref was auto-detected so they can confirm.
21+
22+
If the reflog doesn't contain a `Created from` entry (e.g. the reflog was pruned), fall back to asking the user for the base ref.
23+
24+
## Step 1: Run verification
25+
26+
Run `make verify` to sync dependencies and execute all CI checks (lint, format, types, tests).
27+
28+
- If it passes, proceed to step 2.
29+
- If it fails, stop and show the user the errors. Offer to help fix them before continuing. Do NOT proceed to PR description generation until verification passes.
30+
31+
## Step 2: Gather change information
32+
33+
Run these commands to understand the full scope of changes:
34+
35+
- `git log --oneline $ARGUMENTS..HEAD` — list all commits being included.
36+
- `git log --format="### %s%n%n%b" $ARGUMENTS..HEAD` — get full commit messages with bodies.
37+
- `git diff --stat $ARGUMENTS..HEAD` — file-level summary of what changed.
38+
- `git diff $ARGUMENTS..HEAD` — full diff for detailed analysis.
39+
40+
**Uncommitted changes:** By default, only include committed changes in the PR description. Ignore uncommitted (staged or unstaged) files unless the user explicitly mentions or asks to include them.
41+
42+
## Step 3: Analyze and categorize
43+
44+
Review all commits and the diff to understand:
45+
46+
- **The problem or gap that motivated this work** — what was missing, broken, or insufficient before this PR? Derive this from commit messages, code comments, and the nature of the changes themselves.
47+
- What features were added, bugs fixed, or refactors made.
48+
- Which project components were affected — map changes to the project architecture:
49+
- **Tools** (`tools/*.py`) — which MCP tools were added or modified?
50+
- **Parsers/Formatters** (`parsers.py`, `formatters.py`) — output parsing or display changes?
51+
- **Connection** (`connection/ssh.py`) — SSH or remote execution changes?
52+
- **Models** (`models.py`) — data model changes?
53+
- **Config** (`config.py`) — new env vars or configuration options?
54+
- **Gatekeeper** (`gatekeeper/`) — script validation changes?
55+
- **MCP App** (`mcp-app/`) — UI changes?
56+
- **Tests** (`tests/`) — new or modified test coverage?
57+
- **CI/Docs/Scripts** — infrastructure changes?
58+
- Any breaking changes, new dependencies, or new `LINUX_MCP_*` configuration variables.
59+
60+
## Step 4: Generate the PR description
61+
62+
Produce a PR description in this format:
63+
64+
```markdown
65+
## Motivation
66+
<!-- 1-3 sentences explaining the problem, gap, or motivation that drove this PR. Answer: what was the situation before, and why was it insufficient? Do NOT describe what the code does here — focus on the reason the work was needed. -->
67+
68+
## Summary
69+
<!-- 1-3 bullet points describing the high-level approach taken to address the problem above -->
70+
71+
## Changes
72+
<!-- Bulleted list of specific changes, grouped by affected project area (e.g. Tools, Parsers, Models, Config, Tests, CI, Docs). Use the project's component names, not generic categories. -->
73+
74+
## Test plan
75+
<!-- How the changes were verified — reference make verify passing, plus any manual testing or specific test cases added -->
76+
77+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
78+
```
79+
80+
Rules:
81+
- **"Motivation" comes first** and must answer "what problem does this solve?" — not "what does this PR do?"
82+
- Keep the summary concise — focus on the approach, not a line-by-line rehash.
83+
- In the Changes section, group by project component (Tools, Connection, Models, Config, Tests, etc.) rather than generic categories.
84+
- Call out breaking changes, migration steps, or new `LINUX_MCP_*` env vars prominently.
85+
- Mention new dependencies or changes to `pyproject.toml` if applicable.
86+
87+
## Step 5: Present the result
88+
89+
Show the generated PR description in a code block. Ask the user if they'd like to:
90+
1. Create the PR now using `gh pr create` with this description
91+
2. Edit the description first
92+
3. Regenerate with different emphasis

.claude/skills/review-pr/SKILL.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
---
2+
name: review-pr
3+
description: Review a pull request by URL for code format, types, semantic correctness, readability, redundant logic, bugs, and security concerns
4+
disable-model-invocation: true
5+
allowed-tools: Bash(gh pr *) Bash(gh api *) Bash(git diff *) Bash(git log *) Bash(git status) Bash(git fetch *) Bash(git checkout *) Bash(git rev-parse *) Bash(git merge-base *) Bash(make lint) Bash(make format) Bash(make types) Bash(make test) Read
6+
argument-hint: "<pr-url>"
7+
---
8+
9+
Review a pull request for code quality issues across six dimensions: format, types, semantic correctness, readability, redundant logic, and bugs/security.
10+
11+
## Step 0: Fetch PR information
12+
13+
`$ARGUMENTS` must be a GitHub PR URL (e.g. `https://github.com/owner/repo/pull/123`).
14+
15+
If `$ARGUMENTS` is empty, ask the user for the PR URL. Do not proceed without it.
16+
17+
1. Extract the PR number from the URL.
18+
2. Run `gh pr view <pr-url> --json number,title,baseRefName,headRefName,commits,files` to get PR metadata.
19+
3. Fetch the PR branch locally:
20+
- `git fetch origin pull/<number>/head:pr-<number>` to create a local ref for the PR.
21+
- Determine the merge base: `git merge-base origin/<baseRefName> pr-<number>`
22+
4. Use the merge base as the base ref for all diff commands.
23+
24+
Tell the user which PR you're reviewing (number, title, head branch, base branch).
25+
26+
## Step 1: Gather changes
27+
28+
Run these commands to understand the full scope of changes:
29+
30+
- `git log --oneline <merge-base>..pr-<number>` — list all commits in the PR.
31+
- `git diff --stat <merge-base>..pr-<number>` — file-level summary of what changed.
32+
- `git diff <merge-base>..pr-<number>` — full diff for detailed analysis.
33+
34+
Read every changed file in full (from the PR branch) so you can evaluate changes in their surrounding context, not just the diff hunks in isolation. Use `git show pr-<number>:<file-path>` to read files from the PR branch without switching branches.
35+
36+
## Step 2: Format check
37+
38+
Run `make lint` and `make format` against the PR branch to check for formatting and linting violations.
39+
40+
To do this without modifying the current working tree:
41+
- Check out the PR branch: `git checkout pr-<number>`
42+
- Run `make lint` and `make format`.
43+
- After the review is complete (Step 8), check out the original branch.
44+
45+
Report results:
46+
- **Pass** — no issues found.
47+
- **Fail** — list every violation with file path, line number, and the rule ID. Group by file.
48+
49+
Do NOT auto-fix. Only report.
50+
51+
## Step 3: Type check
52+
53+
Run `make types` to run pyright on the PR branch.
54+
55+
Report results:
56+
- **Pass** — no type errors.
57+
- **Fail** — list every error with file path, line number, and the pyright message. Group by file.
58+
59+
For the `mcp-app/` TypeScript code, if any `.ts` or `.tsx` files are in the diff, note that TypeScript type checking should be run separately inside `mcp-app/` if a tsconfig and type-check script exist there.
60+
61+
## Step 4: Semantic review
62+
63+
Analyze every changed file for semantic correctness. For each file, check:
64+
65+
1. **Behavioral changes** — Does the change alter existing behavior? Is that intentional or an accidental regression? Look for:
66+
- Changed return values, error handling, or control flow.
67+
- Modified default values or function signatures.
68+
- Altered query/filter logic.
69+
70+
2. **Edge cases** — Are there inputs or states the new code doesn't handle?
71+
- Empty/null/zero-length inputs.
72+
- Boundary values (off-by-one, max int, empty string vs None).
73+
- Concurrent or async race conditions.
74+
75+
3. **API contract consistency** — Do changes to models, tool signatures, or config stay consistent across:
76+
- `models.py``parsers.py``formatters.py`
77+
- `commands.py``tools/*.py`
78+
- `config.py` env var names ↔ documentation
79+
80+
4. **Test coverage** — Are new code paths covered by tests? Flag any added logic that lacks a corresponding test case.
81+
82+
Report each finding with:
83+
- File path and line number(s).
84+
- What the issue is.
85+
- Severity: **critical** (likely bug/regression), **warning** (potential issue), or **info** (suggestion).
86+
87+
## Step 5: Readability and redundancy review
88+
89+
Evaluate the changed code for maintainability:
90+
91+
1. **Readability issues:**
92+
- Overly complex expressions that should be broken up.
93+
- Unclear variable or function names.
94+
- Deeply nested logic (3+ levels) that could be flattened with early returns or guard clauses.
95+
- Magic numbers or strings that should be named constants.
96+
- Functions doing too many things (violating single responsibility).
97+
98+
2. **Redundant logic:**
99+
- Duplicate code across the diff or between the diff and existing code.
100+
- Conditions that are always true/false.
101+
- Unnecessary intermediate variables or re-assignments.
102+
- Dead code (unreachable branches, unused imports, unused variables).
103+
- Over-engineered abstractions for simple operations.
104+
105+
Report each finding with file path, line number(s), what the issue is, and a concrete suggestion for improvement.
106+
107+
## Step 6: Bug and security review
108+
109+
Scan changes for bugs and security concerns, with special attention to this project's security model (read-only tools, SSH key auth, input validation):
110+
111+
1. **Bugs:**
112+
- Incorrect exception handling (swallowing errors, catching too broadly).
113+
- Resource leaks (unclosed connections, file handles).
114+
- Async issues (missing `await`, unawaited coroutines).
115+
- Incorrect use of mutable default arguments.
116+
117+
2. **Security (OWASP + project-specific):**
118+
- **Command injection** — Any user input reaching shell commands without validation. Check against the project's `commands.py` allowlist pattern.
119+
- **Path traversal** — File path parameters that aren't validated against allowlists (see `ALLOWED_LOG_PATHS`, `MAX_FILE_READ_BYTES`).
120+
- **Information disclosure** — Sensitive data in logs, error messages, or tool outputs. Check that `audit.py` redaction covers new fields.
121+
- **SSH security** — Any weakening of host key verification, key-based auth, or connection pooling.
122+
- **Read-only violation** — Any tool missing `readOnlyHint=True` or performing writes without going through the gatekeeper.
123+
- **Input validation** — Missing or insufficient validation on tool parameters (see `utils/validation.py`).
124+
- **Dependency risks** — New dependencies that are unmaintained, have known CVEs, or pull in excessive transitive deps.
125+
126+
Rate each finding:
127+
- **critical** — Exploitable vulnerability or guaranteed bug. Must fix before merge.
128+
- **warning** — Potential issue depending on context. Should fix or explicitly justify.
129+
- **info** — Defense-in-depth suggestion or minor hardening opportunity.
130+
131+
## Step 7: Run tests
132+
133+
Run `make test` on the PR branch to verify all tests pass.
134+
135+
Report results:
136+
- **Pass** — all tests green, with coverage summary if printed.
137+
- **Fail** — list failing tests with their error messages. Note whether failures are related to the PR changes or pre-existing.
138+
139+
## Step 8: Restore original branch and present summary
140+
141+
Check out the original branch that was active before the review began.
142+
143+
Present the full review in this format:
144+
145+
```
146+
## PR Review: #<number> — <title>
147+
**Branch:** <head> → <base>
148+
149+
### Format & Lint
150+
<results from Step 2>
151+
152+
### Type Check
153+
<results from Step 3>
154+
155+
### Tests
156+
<results from Step 7>
157+
158+
### Semantic Issues
159+
<findings from Step 4, ordered by severity>
160+
161+
### Readability & Redundancy
162+
<findings from Step 5>
163+
164+
### Bugs & Security
165+
<findings from Step 6, ordered by severity>
166+
167+
### Verdict
168+
169+
**<APPROVE | REQUEST CHANGES | NEEDS DISCUSSION>**
170+
171+
<1-3 sentence summary of the overall state of the PR. Call out the most important finding if any.>
172+
```
173+
174+
Verdict criteria:
175+
- **APPROVE** — No critical or warning findings. All checks pass.
176+
- **REQUEST CHANGES** — Any critical finding, or 3+ warnings.
177+
- **NEEDS DISCUSSION** — Warnings that involve design decisions or tradeoffs the author should weigh in on.
178+
179+
After presenting the review, ask the user if they'd like to:
180+
1. Fix the reported issues (offer to help with specific fixes).
181+
2. Re-run the review after making changes.
182+
3. Discuss any specific finding in more detail.

0 commit comments

Comments
 (0)