symkit/bundle-ai-kit
Symkit Bundle AI Kit is a Laravel/PHP package for adding AI features to applications. It offers ready-to-use services, configuration, and utilities that simplify model calls, prompt handling, and AI-powered workflows, helping developers reduce boilerplate in Laravel projects.
This is a Composer plugin that syncs AI rules, skills and agent prompts into your project so Cursor / Claude Code / Windsurf get Symfony‑bundle best‑practice context automatically. There is no Artisan command — the sync is driven by Composer lifecycle events.
composer require --dev symkit/bundle-ai-kit
symkit/bundle-ai-kit: true to config.allow-plugins in composer.json, then re-run composer install.AiRulesInstaller::sync and writes:
.cursor/rules/*.mdc.cursor/skills/<name>/SKILL.mdc (+ helper files/templates copied as‑is).cursor/agents/*.mdAGENTS.md at project rootAGENTS.md — the entry point for every editor.alwaysApply: true — the core project rule that loads on every interaction..cursor/rules/ — architecture, symfony-bundle, quality, tests, php-code guidance, most triggered by globs (e.g. src/**/*.php)..cursor/skills/ — workflow skills (quality-install, onboard, feature pipeline).First use case: open the repo in Cursor and ask the AI to scaffold a new bundle following AbstractBundle + Contract pattern. The always‑apply rule sets conventions; the globbed PHP rules activate as you edit src/. Then close the loop with make cs-fix && make phpstan (or make quality) as the rules instruct.
Let the frontmatter do the routing. Rules use globs (src/**/*.php, or CSV like Makefile, grumphp.yml, .github/**/*.yml) so context appears exactly when you touch matching files. Keep alwaysApply: true reserved for the single main rule — everything else is glob‑ or description‑driven.
Trigger skills with natural language. A skill activates when your prompt matches the keywords in its description. Instead of “set up CI”, say “install the quality tooling” / “onboard me to this bundle” so the quality-install / onboard skills fire. If a skill isn’t loading, its description is usually too vague — add trigger phrases.
Use the “quality-install” workflow as a one‑shot scaffold. It generates the Makefile, .php-cs-fixer.dist.php, phpstan.neon.dist, grumphp.yml, deptrac.yaml, Infection and GitHub Actions in one pass, matching the opinionated stack documented in the quality rule. Treat the generated files as a starting point, then tune thresholds.
Feature pipeline pattern. For new bundle features, follow: rule‑guided design → make cs-fix → make phpstan (level 9, no baselines) → make test → make infection (MSI ≥ 70%) → make quality. The rules deliberately forbid short‑cuts like calling vendor/bin/* directly: the Makefile is the contract.
Commit the synced artifacts. .cursor/, AGENTS.md and skill templates belong in VCS so the whole team gets identical AI context. The plugin’s own .gitignore only excludes build artifacts (vendor/, .phpstan-cache/, .php-cs-fixer.cache/, .deptrac.cache/, infection*.log, *.log) — mirror that.
Cross‑editor compatibility. Bodies render as plain Markdown after frontmatter is stripped, so the same files drive Claude Code and Windsurf. Keep bodies Cursor‑agnostic (no .mdc references, no Cursor‑only syntax) — that’s an explicit rule.
Extending / contributing. If you fork or add rules: kebab-case.mdc filenames, required description frontmatter, globs for scoping, skills use SKILL.mdc with name kebab‑case matching the folder. PHP changes follow the plugin conventions — final readonly value objects/resolvers, final for Plugin / AiRulesInstaller, declare(strict_types=1), prefixed native functions (\is_dir, \mkdir, \copy), no setters, no @phpstan-ignore without a comment.
Extension points to know: SyncContextResolverInterface (swap the resolver for a custom context), DefaultSyncContextResolver::forBundleAiKit() (package name + paths), SkillNamesDiscoverer::discover() (which skill folders get copied), AiRulesInstaller (actual copy logic). Plugin accepts optional resolver/installer injections for tests.
.cursor/, run composer diagnose and check config.allow-plugins first..mdc you hand‑edited won’t be overwritten. Keep your own rules under distinct filenames (e.g. team-conventions.mdc) and leave upstream files untouched.deptrac task loads it in the same process as GrumPHP → ComposerAutoloaderInit* clash. Redirect the GrumPHP task to make deptrac (keep the key for hook display); don’t call Deptrac inline.composer_audit is not a GrumPHP task. It doesn’t exist — use the make security-check target (composer audit --abandoned=report) separately in CI. Running bare composer audit fails builds on abandoned transitive dependencies.deptrac/deptrac, not the abandoned qossmic/deptrac..dist configs (phpstan.neon.dist, .php-cs-fixer.dist.php) so local overrides don’t leak; never add a baseline; fix pre‑existing errors while you’re in the file.description: with a colon or special character must be quoted; unquoted colons silently break Cursor’s parsing.AiRulesInstaller. Don’t expect a config knob to redirect output; if you need different locations, subclass the installer.composer.json, review release notes before bumping, and treat the rules as opinionated defaults — fork or extend when your team’s conventions diverge (e.g. mutation‑testing MSI threshold, PHP matrix 8.2–8.4 × Composer 2–3).Plugin → DefaultSyncContextResolver (package identity) → SkillNamesDiscoverer (which skill dirs are found) → AiRulesInstaller (copy). The SkillNamesDiscoverer::discover() unit test (sorted folder names, ignores files) is the fastest sanity check if skills are missing.git commit --trailer or add AI attribution. The quality rule explicitly forbids self‑attribution trailers — pre‑commit GrumPHP will otherwise fight your history hygiene.How can I help you explore Laravel packages today?