Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/skills
4 changes: 2 additions & 2 deletions .github/workflows/skill-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
pull_request:
types: [opened, synchronize]
paths:
- '.claude/skills/**'
- 'skills/**'

jobs:
review:
Expand Down Expand Up @@ -35,7 +35,7 @@ jobs:

STEP 1: Run `gh pr diff ${{ github.event.pull_request.number }}` to see exactly what changed.
STEP 2: Read docs/SKILL_GUIDELINES.md to understand validation criteria.
STEP 3: Read .claude/skills/README.md to check for overlap with existing skills.
STEP 3: Read skills/README.md to check for overlap with existing skills.
STEP 4: Validate ONLY the changed files against these criteria:

Structure and spec conformance are already checked by
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ jobs:
- name: Validate every skill
run: |
fail=0
for d in .claude/skills/*/; do
for d in skills/*/; do
if ! out=$(agentskills validate "$d" 2>&1); then
fail=1
echo "::error file=${d}SKILL.md::$(echo "$out" | tr '\n' ' ')"
echo "FAIL $d"
echo "$out" | sed 's/^/ /'
fi
done
echo "Validated $(ls -d .claude/skills/*/ | wc -l) skills."
echo "Validated $(ls -d skills/*/ | wc -l) skills."
exit $fail
16 changes: 15 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- [#8]: `plugin.json`, declaring this repository as an [Agent Plugin](https://agent-plugins.org/).
- [#8]: `validate-skills.sh` checks that the `.claude/skills` compatibility path still
resolves to `skills/`, and that `plugin.json` and `CHANGELOG.md` agree on the version.

### Changed

- [#8]: Skills moved from `.claude/skills/` to `skills/`, which is where the Agent Plugins
standard expects them. `.claude/skills` remains as a symlink, so existing links and the
paths in our own documentation keep working. On a checkout without symlink support,
Windows without developer mode being the usual case, use `skills/` directly.

## [1.0.0] - 2026-08-28

First tagged release. Within a major version, skill names and directory layout stay
Expand All @@ -15,7 +28,7 @@ put, which is what copying or symlinking a skill folder depends on.
### Added

- 18 skills covering workflow, code quality, architecture and frameworks. The
[skills README](.claude/skills/README.md) lists them.
[skills README](skills/README.md) lists them.
- Setup scripts: `setup-project.sh`, `link-skills.sh`, `generate-claude-md.sh`,
`configure-mcp.sh`, `configure-settings.sh`, `test-all.sh`.
- Templates for `CLAUDE.md`, MCP configuration and Claude Code settings.
Expand All @@ -41,5 +54,6 @@ put, which is what copying or symlinking a skill folder depends on.
it produced a test that always reported the wrong result.

[#5]: https://github.com/decebals/claude-code-java/issues/5
[#8]: https://github.com/decebals/claude-code-java/issues/8
[Unreleased]: https://github.com/decebals/claude-code-java/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/decebals/claude-code-java/releases/tag/v1.0.0
42 changes: 21 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ This creates `.claude/` with symlinked skills, generates `CLAUDE.md`, and config
mkdir -p your-project/.claude/skills

# Copy specific skills
cp -r ~/projects/claude-code-java/.claude/skills/java-code-review your-project/.claude/skills/
cp -r ~/projects/claude-code-java/skills/java-code-review your-project/.claude/skills/

# Or symlink all skills
ln -s ~/projects/claude-code-java/.claude/skills/* your-project/.claude/skills/
ln -s ~/projects/claude-code-java/skills/* your-project/.claude/skills/
```

### 3. Use with Claude Code
Expand All @@ -69,38 +69,38 @@ Skills are automatically loaded by Claude Code based on context.
### Workflow
| Skill | Trigger Examples |
|-------|------------------|
| [**git-commit**](.claude/skills/git-commit/) | "commit these changes", "create commit" |
| [**changelog-generator**](.claude/skills/changelog-generator/) | "generate changelog", "what changed since release" |
| [**issue-triage**](.claude/skills/issue-triage/) | "triage issues", "check open issues" |
| [**git-commit**](skills/git-commit/) | "commit these changes", "create commit" |
| [**changelog-generator**](skills/changelog-generator/) | "generate changelog", "what changed since release" |
| [**issue-triage**](skills/issue-triage/) | "triage issues", "check open issues" |

### Code Quality
| Skill | Trigger Examples |
|-------|------------------|
| [**java-code-review**](.claude/skills/java-code-review/) | "review this code", "check this PR" |
| [**api-contract-review**](.claude/skills/api-contract-review/) | "review API", "check REST endpoints" |
| [**concurrency-review**](.claude/skills/concurrency-review/) | "check thread safety", "review async code" |
| [**performance-smell-detection**](.claude/skills/performance-smell-detection/) | "check performance", "find slow code" |
| [**test-quality**](.claude/skills/test-quality/) | "add tests", "improve coverage" |
| [**maven-dependency-audit**](.claude/skills/maven-dependency-audit/) | "check dependencies", "audit deps" |
| [**security-audit**](.claude/skills/security-audit/) | "security review", "check OWASP", "vulnerabilities" |
| [**java-code-review**](skills/java-code-review/) | "review this code", "check this PR" |
| [**api-contract-review**](skills/api-contract-review/) | "review API", "check REST endpoints" |
| [**concurrency-review**](skills/concurrency-review/) | "check thread safety", "review async code" |
| [**performance-smell-detection**](skills/performance-smell-detection/) | "check performance", "find slow code" |
| [**test-quality**](skills/test-quality/) | "add tests", "improve coverage" |
| [**maven-dependency-audit**](skills/maven-dependency-audit/) | "check dependencies", "audit deps" |
| [**security-audit**](skills/security-audit/) | "security review", "check OWASP", "vulnerabilities" |

### Architecture & Design
| Skill | Trigger Examples |
|-------|------------------|
| [**architecture-review**](.claude/skills/architecture-review/) | "review architecture", "check package structure" |
| [**solid-principles**](.claude/skills/solid-principles/) | "check SOLID", "single responsibility" |
| [**design-patterns**](.claude/skills/design-patterns/) | "use factory pattern", "implement strategy" |
| [**clean-code**](.claude/skills/clean-code/) | "clean this code", "refactor" |
| [**architecture-review**](skills/architecture-review/) | "review architecture", "check package structure" |
| [**solid-principles**](skills/solid-principles/) | "check SOLID", "single responsibility" |
| [**design-patterns**](skills/design-patterns/) | "use factory pattern", "implement strategy" |
| [**clean-code**](skills/clean-code/) | "clean this code", "refactor" |

### Framework & Data
| Skill | Trigger Examples |
|-------|------------------|
| [**spring-boot-patterns**](.claude/skills/spring-boot-patterns/) | "create controller", "Spring Boot help" |
| [**java-migration**](.claude/skills/java-migration/) | "upgrade to Java 21", "migrate from Java 8" |
| [**jpa-patterns**](.claude/skills/jpa-patterns/) | "N+1 problem", "LazyInitializationException" |
| [**logging-patterns**](.claude/skills/logging-patterns/) | "add logging", "debug this flow", "analyze logs" |
| [**spring-boot-patterns**](skills/spring-boot-patterns/) | "create controller", "Spring Boot help" |
| [**java-migration**](skills/java-migration/) | "upgrade to Java 21", "migrate from Java 8" |
| [**jpa-patterns**](skills/jpa-patterns/) | "N+1 problem", "LazyInitializationException" |
| [**logging-patterns**](skills/logging-patterns/) | "add logging", "debug this flow", "analyze logs" |

See [.claude/skills/README.md](.claude/skills/README.md) for full documentation and [docs/SCRIPTS.md](docs/SCRIPTS.md) for setup script options.
See [skills/README.md](skills/README.md) for full documentation and [docs/SCRIPTS.md](docs/SCRIPTS.md) for setup script options.

## Project Structure

Expand Down
20 changes: 9 additions & 11 deletions docs/RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,21 @@ minor release; renaming or moving one waits for a major.

## Where the version lives

In `CHANGELOG.md`. The top `## [x.y.z]` heading is the released version:
In `plugin.json`, the Agent Plugins manifest. Clients read the version from there, so it
has to be right, which makes it the anchor.

```bash
grep -m1 -oP '^## \[\K[0-9]+\.[0-9]+\.[0-9]+' CHANGELOG.md
```

There is no build here, so a separate version file would exist only to be bumped and would
eventually drift from the changelog. The changelog has to be edited at release time anyway,
which makes it the one place that cannot fall behind.
`CHANGELOG.md` carries the same version in its top `## [x.y.z]` heading, because a release
note without a version is useless. Two files holding one number would normally drift, so
`validate-skills.sh` fails the build when they disagree. Bump both, or neither.

## Cutting a release

1. `./scripts/test-all.sh` passes and CI is green on `main`.
2. Move the entries under `[Unreleased]` into a new `## [x.y.z] - YYYY-MM-DD` section and
update the link definitions at the bottom of the file.
3. Commit, tag `vx.y.z`, push the tag.
4. Create the GitHub release from the tag, using that changelog section as the body.
3. Set the same version in `plugin.json` and run `./scripts/validate-skills.sh`.
4. Commit, tag `vx.y.z`, push the tag.
5. Create the GitHub release from the tag, using that changelog section as the body.

Steps 3 and 4 are deliberately manual. Automating them can wait until doing it by hand
Steps 4 and 5 are deliberately manual. Automating them can wait until doing it by hand
starts to feel like a chore.
4 changes: 4 additions & 0 deletions docs/SCRIPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ cd /path/to/claude-code-java

Errors fail the run, recommendations are reported as warnings.

Beyond the spec, it checks two things specific to this repository: that the `.claude/skills`
compatibility symlink still resolves to `skills/`, which a checkout without symlink support
silently breaks, and that `plugin.json` and `CHANGELOG.md` carry the same version.

#### Why two validators

CI runs this script alongside [`skills-ref`](https://pypi.org/project/skills-ref/), the
Expand Down
6 changes: 3 additions & 3 deletions docs/SKILL_GUIDELINES.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ A skill should be completable in one session. Signs it's too broad:
Every skill has two files:

```
.claude/skills/<skill-name>/
skills/<skill-name>/
├── SKILL.md # Instructions for the agent (the AI reads this)
└── README.md # Documentation for humans
```
Expand Down Expand Up @@ -252,7 +252,7 @@ Before committing:

### Automated Review

PRs that modify `.claude/skills/` are automatically reviewed against these guidelines.
PRs that modify `skills/` are automatically reviewed against these guidelines.
The review checks:
- **Structure**: frontmatter, required files, folder convention
- **Overlap**: comparison with existing skills
Expand Down Expand Up @@ -373,7 +373,7 @@ A skill is mature when:
Consider adding to your skill folder:

```
.claude/skills/<skill-name>/
skills/<skill-name>/
├── SKILL.md
├── README.md
└── CHANGELOG.md # Optional: track refinements
Expand Down
14 changes: 14 additions & 0 deletions plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
"name": "java-agent-skills",
"version": "1.0.0",
"description": "Agent Skills for Java development: code review, testing, architecture, Spring Boot, JPA, concurrency, security and release workflows.",
"author": {
"name": "Decebal Suiu",
"url": "https://github.com/decebals"
},
"homepage": "https://github.com/decebals/claude-code-java",
"repository": "https://github.com/decebals/claude-code-java",
"license": "MIT",
"keywords": ["agent-skills", "java", "maven", "spring-boot", "jpa", "code-review", "testing"]
}
4 changes: 2 additions & 2 deletions scripts/link-skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ success() { echo -e "${GREEN}✅ $1${NC}"; }
info() { echo -e "${BLUE}ℹ️ $1${NC}"; }

# Check dirs
[ ! -d "$WORKSPACE_DIR/.claude/skills" ] && error "Skills not found at $WORKSPACE_DIR/.claude/skills"
[ ! -d "$WORKSPACE_DIR/skills" ] && error "Skills not found at $WORKSPACE_DIR/skills"
[ ! -d "$PROJECT_DIR" ] && error "Project dir not found: $PROJECT_DIR"

# Create .claude if missing
Expand All @@ -33,7 +33,7 @@ if [ -L "$PROJECT_DIR/.claude/skills" ]; then
elif [ -d "$PROJECT_DIR/.claude/skills" ]; then
echo -e "${YELLOW}⚠️ .claude/skills exists but is not a symlink. Backup/remove manually.${NC}"
else
ln -sf "$WORKSPACE_DIR/.claude/skills" "$PROJECT_DIR/.claude/skills"
ln -sf "$WORKSPACE_DIR/skills" "$PROJECT_DIR/.claude/skills"
success "Linked skills to project"
fi

Expand Down
2 changes: 1 addition & 1 deletion scripts/test-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ echo "Testing link-skills.sh..."
check ".claude directory created" [ -d "$TEST_DIR/.claude" ]
check "skills symlink created" [ -L "$TEST_DIR/.claude/skills" ]
LINK_TARGET=$(readlink "$TEST_DIR/.claude/skills" 2>/dev/null || echo "")
check "symlink points to workspace" [ "$LINK_TARGET" = "$WORKSPACE_DIR/.claude/skills" ]
check "symlink points to workspace" [ "$LINK_TARGET" = "$WORKSPACE_DIR/skills" ]
echo ""

# Test 2: generate-claude-md.sh
Expand Down
26 changes: 25 additions & 1 deletion scripts/validate-skills.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORKSPACE_DIR="$(dirname "$SCRIPT_DIR")"

SKILLS_DIR="$(cd "${1:-$WORKSPACE_DIR/.claude/skills}" && pwd)"
SKILLS_DIR="$(cd "${1:-$WORKSPACE_DIR/skills}" && pwd)"

# Frontmatter fields the spec allows. Anything else is rejected.
ALLOWED_FIELDS="name description license compatibility metadata allowed-tools"
Expand All @@ -30,6 +30,18 @@ warn() { echo "⚠️ $1"; WARNINGS=$((WARNINGS + 1)); }

[ ! -d "$SKILLS_DIR" ] && echo "❌ Skills directory not found: $SKILLS_DIR" && exit 1

# The canonical location is skills/. .claude/skills is a symlink kept for anyone who
# linked or copied the old path. A checkout without symlink support turns it into a text
# file, and the failure is silent, so check that it still resolves to the same place.
COMPAT_LINK="$WORKSPACE_DIR/.claude/skills"
if [ -e "$COMPAT_LINK" ] || [ -L "$COMPAT_LINK" ]; then
if [ ! -d "$COMPAT_LINK" ]; then
fail "compatibility path .claude/skills does not resolve to a directory"
elif [ "$(cd "$COMPAT_LINK" && pwd -P)" != "$(cd "$WORKSPACE_DIR/skills" && pwd -P)" ]; then
fail "compatibility path .claude/skills resolves somewhere other than skills/"
fi
fi

# Prints the frontmatter block of $1, without the --- delimiters.
# Requires the closing --- on a line of its own.
frontmatter() {
Expand Down Expand Up @@ -125,6 +137,18 @@ for dir in "$SKILLS_DIR"/*/; do
[ "$lines" -le 500 ] || warn "$name: SKILL.md is $lines lines, the spec recommends under 500"
done

# One version, two files that must agree. plugin.json is the anchor; the changelog's
# top released heading has to match it, so a release cannot half-happen.
MANIFEST="$WORKSPACE_DIR/plugin.json"
CHANGELOG="$WORKSPACE_DIR/CHANGELOG.md"
if [ -f "$MANIFEST" ] && [ -f "$CHANGELOG" ]; then
manifest_version="$(grep -oE '"version"[ ]*:[ ]*"[^"]+"' "$MANIFEST" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
changelog_version="$(grep -m1 -oE '^## \[[0-9]+\.[0-9]+\.[0-9]+\]' "$CHANGELOG" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"
if [ "$manifest_version" != "$changelog_version" ]; then
fail "plugin.json says $manifest_version, CHANGELOG.md says $changelog_version"
fi
fi

echo ""
echo "Checked $CHECKED skills in $SKILLS_DIR"
echo "$ERRORS error(s), $WARNINGS warning(s)"
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/README.md → skills/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Validate your skill idea against existing skills:

### Implementation Steps

1. Create folder: `.claude/skills/<skill-name>/`. The folder name must be lowercase alphanumeric with single hyphens, and the `name` in the frontmatter must match it.
1. Create folder: `skills/<skill-name>/`. The folder name must be lowercase alphanumeric with single hyphens, and the `name` in the frontmatter must match it.
2. Create `SKILL.md` with instructions for the agent. Required frontmatter is `name` and `description`; `license`, `compatibility`, `metadata` and `allowed-tools` are optional and no other top-level field is allowed.
3. Create `README.md` with human documentation (use existing READMEs as template)
4. Update this table
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading