The hooks
The hooks run on every edit and every Gradle run, in bash (hooks/elasticore-hook.sh), and answer
Claude Code in JSON. They watch the edit tools (Edit, Write, MultiEdit) and commands through
Bash and PowerShell, including failed commands, and the moment Claude is about to stop.
| When | What happens |
|---|---|
Claude uses the edit tools on a generated file - first line //ecd:, no // Initially generated by ElastiCORE; line, no preserved block | The edit is refused, with where the change belongs instead. Adding one whole preserved block (// !---------- ... // ------------!) goes through |
Claude edits a file ElastiCORE rewrites on every generation - blueprint/schema.yml, the copied guides, the default i18n/<domain>-messages.properties, a generated orm.xml | Refused |
| Claude edits a generated file that has a preserved block | Allowed, with a reminder that only the block survives regeneration |
Claude runs Gradle with -Pforce, or sets the property another way (-P force, ORG_GRADLE_PROJECT_force, ...) | Refused: it overwrites hand edits. You decide |
Claude changes the model under src/main/resources/blueprint/<domain>/ | Told to run ./gradlew compileJava and fix the warnings before finishing; on a build without the elasticore { } block, also told that the 2.x generator ignores access rules, lifecycles and derived values |
| A Gradle build - successful or failed - prints DSL validation warnings, a YAML file it could not read, or hand-edited generated files | Told what that means and what to do |
| Claude is about to finish while no successful build has generated and compiled its DSL change | Sent back once to build. A build in the background, cut short or filtered, or one that only generated, does not count |
Details that matter
-Pforceis recognised as"-Pforce",-P force,--project-prop force,-Dorg.gradle.project.forceandORG_GRADLE_PROJECT_force=, through& ".\gradlew.bat",cmd /c,bash -c,envortime. The command is read as a shell reads it, so a commit message that mentions-Pforceis not refused.- "Compiled" means compiled: generation alone (
elcore3,elcore3ts, a build with-xon the compiling tasks) does not end a DSL change, nor does a command in which one Gradle run failed and another passed. - The model files are always editable, even when the ElastiCORE wizard wrote
# Generated by ElastiCORE Frameworkat their top. - Long output: a successful command's full output is read from the file Claude Code saves it to; of a failed one Claude Code passes on only the first 10,000 characters, so in a very large project the warnings may be past what the hook sees.
- An edit made another way - a script through a shell - is not stopped; the skill tells Claude not to make one.
- In opencode the kit's plugin runs the same script: refusals become tool errors, notes are added to the tool's output, and an idle session with an uncompiled DSL change is sent back once.
Switching them off for a project
.claude/settings.local.json
{ "env": { "ELASTICORE_ALLOW_GENERATED_EDITS": "1" } }
ELASTICORE_ALLOW_FORCE=1 allows -Pforce. On Windows the hooks need Git for Windows (Git Bash);
without it, install it or disable the plugin.
The hook script is tested on Linux, macOS (also its own /bin/bash 3.2) and Windows on every change,
with the JSON Claude Code really sends (tests/hooks/test-hooks.sh).