Dotboost
Drop-in configuration that teaches Claude Code the conventions of any Dotkernel application - API, Admin, Frontend, Light, Queue, or a project derived from one of them. Every skill detects the variant first and applies the matching dialect, so generated code follows your architecture instead of guessing at it.
Not an application - a configuration payload
Dotboost is not itself a Dotkernel application. Its entire payload is the .claude/
directory: settings, hooks, a status line, a review subagent, ten /dk-* commands and
seventeen skills. You install it by copying that directory into the Dotkernel project you are
working on.
There is no routing table telling Claude which skill to pick - each one loads from its own description. Ask where a new Doctrine entity goes and it should reach for the module-structure skill rather than answering from general framework knowledge.
Detects the variant before it answers
Secrets never enter the context window
Guards catch compound commands globs miss
Copy it in - nothing to build or install
The reason to adopt the file
The permission rules in settings.json fall into four tiers. The first one is the
headline: these are Read denies, not write protection, so the contents never enter the
context window at all.
Your secrets
Not redacted - never loaded.
.env, every *.local.php,
config/autoload/local.php, local.test.php and
data/oauth/. Database credentials, OAuth signing keys and environment secrets stay
out of the transcript.
Generated & vendored
The files a diff should never touch by accident.
Dependency manifests - composer.json, composer.lock,
package.json, package-lock.json - plus vendor/,
node_modules/, data/, log/,
public/uploads/ and anything under Migration/.
Installs & destructive git
Commands that change your tree without a diff.
composer require, remove, update,
install, global; the npm, yarn and pnpm install verbs;
git push, reset --hard, clean,
submodule; and rm -rf.
Your call
Preference, not policy - override per machine.
Ask: migrations, bin/doctrine, database clients, git commits and
merges, pipeline and authorization config, the QA config files.
Allow: the Composer QA scripts, vendor/bin tools,
php -l, and read-only git. Layer changes in
settings.local.json, never the shared file.
Where globs cannot see
Path patterns miss what a shell can hide.
guard-bash.sh inspects the command itself, so
cd src && composer require foo is caught where a path-based rule would let
it through. guard-protected-paths.sh covers edits, and redirects a blocked
*.local.php edit to its .dist template.
Linters that do not rewrite
Deliberately no phpcbf, no --fix.
php-lint.sh and markdown-lint.sh report and stop, because
reformatting a file right after it is written invalidates the in-memory copy and breaks the next
targeted edit. Bulk formatting belongs at the end of a task. Both skip silently when their tool
is missing.
settings.json is a committed file carrying opinions, not only guardrails: sessions start in
plan mode, the terminal UI is full screen, the theme is dark, and Composer runs without
a memory ceiling. Know what you are adopting.
Where the hooks overrule the tiers
Some commands marked ask in settings.json are refused outright by
guard-bash.sh, because the hook sees compound commands the permission globs cannot. The
prompt you would expect never appears - you get a refusal. This is deliberate, and worth knowing
before it surprises you.
| Command | settings.json says | guard-bash.sh does |
|---|---|---|
| git rebase | ask | blocks |
| doctrine-migrations migrate / execute | ask | blocks |
| fixtures:execute, schema:drop, schema:update | ask, via bin/cli.php | blocks |
| composer development-enable / -disable | — | blocks |
| pip install, git checkout --, git filter-branch | — | blocks |
Everything else under ask - commits, database clients, the config and QA files - prompts as
documented. To get a blocked command back you edit the hook; relaxing
settings.local.json will not reach it.
Ten /dk-* commands
Each one runs only when you ask for it.
| Command | What it does |
|---|---|
| /dk-bootstrap | Fresh clone to a running install. |
| /dk-module | Plan a new module - dot-maker first. |
| /dk-route | Add a fully wired endpoint or page. |
| /dk-trace | Trace a request through pipeline, handler and response. |
| /dk-test | Write and run tests. |
| /dk-document | Write or update a feature doc. |
| /dk-check | Run and fix the QA gate. |
| /dk-deprecate | Make an evolution-pattern breaking change. |
| /dk-review | Pre-PR convention review - read-only by design. |
| /dk-hygiene | Encoding and line-ending audit. |
Seventeen skills, loaded on demand
Sixteen dotkernel-* skills plus dependency-policy. Each is a living
document - when a review turns up the same mistake twice, that is a missing line in a skill.
| Skill | Covers |
|---|---|
| application-variants | Detecting API vs Admin vs Frontend vs Light vs Queue. |
| module-structure | Where code goes: application module vs Core, and the wiring. |
| handler-naming | Both naming dialects, routes, authorization keys. |
| doctrine-entities | Entities, enums and DBAL types, repositories, migrations. |
| input-validation | InputFilters, Inputs, forms, CSRF, query whitelisting. |
| responses | HAL and collections, or templates and redirects; errors. |
| openapi | swagger-php attributes, for apps that publish OpenAPI. |
| feature-docs | Feature docs: template, where they live, staleness. |
| testing | Unit and functional patterns, test config, coverage matrix. |
| evolution-pattern | Sunset headers instead of versioning. |
| security | Auth, authorization, secrets, CORS, dependencies. |
| dot-maker | composer make … and the manual steps after it. |
| core-submodule | Core layering rules and git submodule mechanics. |
| psr-standards | PSR-1/3/4/6/7/11/12/15/16/17 as applied here. |
| qa-gate | cs-check, static analysis, tests, and forbidden "fixes". |
| troubleshooting | A symptom to cause table. |
| dependency-policy | The ladder from installed packages to hand-rolled code, and the proposal format. |
A review subagent, dotkernel-reviewer, runs the convention review in its own context so the
main one stays clean.
Never name a package from memory
The ladder is: already in composer.lock, then dotkernel/*, then
laminas/* and mezzio/*, then a vetted community package, and only then
hand-rolled code. Stop at the first hit.
A skill's description decides whether it can load, not whether Claude stops to think before
naming a package. The rule that makes it reach for the skill has to be always loaded - which means
it lives in your project's own CLAUDE.md, not in the skill.
Three things about how that behaves
- The
dotkernel/*manifest is generated on first use, not shipped - the first package question runs the sync script itself. It needscurl,jqand network; without them Claude is told to call a package name unverified rather than assert it. - Neither that script nor
composer show --availableis in the allow or deny list, so both prompt. That is deliberate - expect a prompt the first time. - "How do I send mail from here?" is a package question. Implicit ones count.
Copy one directory into your project
The payload has to sit at the root of your project. Two routes to the same files - pick whichever suits the machine you are on.
1 · Clone it inside the project
Shallow, because only the current state of main is any use in a target project. The
clone goes away right after the copy.
git clone --depth 1 \
https://github.com/dotkernel/dotboost.git .dotboost
cp -r .dotboost/.claude .claude
rm -rf .dotboost
1b · Or download the zip
No git needed, which is the point. The archive unpacks to dotboost-main/ and does
carry the dotfiles.
curl -L -o dotboost.zip https://github.com/\
dotkernel/dotboost/archive/refs/heads/main.zip
unzip -q dotboost.zip
cp -r dotboost-main/.claude .claude
2 · Restore the executable bits
Nothing is committed executable, and a zip extracted on Windows carries no permission bits at all. The sync script is the one called by its own name.
chmod +x .claude/hooks/*.sh .claude/statusline.sh \
.claude/skills/dependency-policy/scripts/*.sh
3 · Keep local overrides out of git
Then copy the example file if you want personal settings that survive an update.
echo '.claude/settings.local.json' \
>> .git/info/exclude
4 · Optional: markdown linting
Not bundled - install it yourself, globally or as a project devDependency. Until the binary resolves, the hook exits silently.
npm install -g markdownlint-cli2
5 · Paste the CLAUDE.md block
The dependency policy and, if you want feature docs actually read, the feature-docs block alongside it.
If the project already has its own .claude/settings.json or
.claude/commands/, merge by hand rather than running cp -r blind - same-named
files are overwritten. To update later, run the whole install again over the top; anything you changed
in the project's copy is lost, which is exactly why personal changes belong in
settings.local.json.
The parts you notice on day two
Feature documentation
The part a cleared session cannot reconstruct from src/.
One markdown file per feature - what it does, why, the routes and the roles that reach them, the
data added, how to exercise it. Where it lands is detected, not assumed:
documentation/features/ when that directory exists,
docs/features/ otherwise, never a second documentation root beside an existing one.
The frontmatter is load-bearing - /dk-review greps routes: and
handlers: to decide whether a new route in the diff is documented.
Real usage, not guesses
The same numbers /usage reports.
5h and 7d account usage in the status bar, read from the rate-limit payload Claude Code 2.1+
passes on stdin. Pure bash and awk - no jq, no python, no transcript scanning or
guessed token budgets, so it works in Git Bash on Windows.
A briefing, every time
What it detected, before you ask anything.
Which variant, the root namespace, the authorization style, the branch, which config files are still missing - and a CRLF warning when it finds one. The same hook prints the feature-docs directory and a doc count, so the files are discoverable even without the CLAUDE.md block.
CRLF, handled
Dotkernel repos ship * text eol=lf.
Belt and braces, configure the client so nothing converts:
core.autocrlf false, core.eol lf,
core.safecrlf warn. Already committed CRLF? Renormalise once with
git add --renormalize .. normalize-file.sh keeps new writes clean.
Every variant, one payload
The application-variants skill detects which Dotkernel application it is looking at - including a project derived from one - and every other skill applies the matching dialect. Handler naming, response shape and authorization keys all differ between them, which is the whole reason the detection runs first.
API Admin Frontend
Light Queue
Before adapting the skills to a new Dotkernel application, the advice from its maintainer is to spend an hour reading that repo and correcting them against what is actually there. A skill written from framework docs rather than the codebase produces confident wrong answers, which is worse than no skill.
API
Handlers, HAL collections, OpenAPI attributes.
A REST API on a PSR-15 middleware pipeline, with OAuth 2.0, RBAC, HAL payloads and an OpenAPI 3.0 specification wired up on install.
Admin
Forms, CSRF, route-name authorization keys.
Table-based record management with RBAC guards, CSRF-protected forms and 2FA, over the shared Core module.
Frontend
Action controllers and action-level guards.
A web starter skeleton - user accounts, a contact form, sessions and RBAC-guarded controller actions, rendered on the server.
Light
Minimal modules, config-declared template routes.
The smallest complete Mezzio application - routing, pipeline and Twig, six direct dependencies and no database layer.
Go deeper
Test article
This is a test article used for fixture and testing purposes.
Read more →Request Lifecycle for a Mezzio-Based Application
Seamlessly Interconnected Middleware for Enterprise-Level Solutions The request lifecycle is the sequence of steps that happen from the moment a user makes an HTTP request until the server sends back a response. The graph below shows how the request is handled by Dotkernel Light (GitHub, documentation), one of the applications in the Dotkernel Headless Platform suite.
Read more →Implementing Time-based One-Time Password (TOTP) in Dotkernel
What TOTP Does A Time-based One-Time Password (TOTP) is a security algorithm used as part of two-factor authentication (2FA) to protect against account attacks. The mechanism is integrated into dot-totp to enhance security by requiring both a password and an additional one-time code.
Read more →Context your AI tools do not have to guess at.
Dotboost is maintained by Borsan Sergiu and released as open source alongside the rest of the Dotkernel ecosystem. Treat the skills as living documents - the repository is where corrections belong.