Shows the current branch's PR and the issue it closes above the prompt, with the build state (uses `bdt pr info`)

██████╗ ███╗ ███╗███████╗ ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗
██╔══██╗████╗ ████║██╔════╝ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝
██████╔╝██╔████╔██║███████╗ ███████╗█████╔╝ ██║██║ ██║ ███████╗
██╔══██╗██║╚██╔╝██║╚════██║ ╚════██║██╔═██╗ ██║██║ ██║ ╚════██║
██████╔╝██║ ╚═╝ ██║███████║ ███████║██║ ██╗██║███████╗███████╗███████║
╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝
Reusable AI agent skills for our engineering team — composable instructions that extend coding agents (Claude Code, Cursor, Codex CLI, etc.) with company-specific workflows and best practices.
Skills are a last resort. Anything that can be enforced deterministically — a lint rule, a formatter setting, a pre-commit hook, a CLI check — belongs in linters or tooling, not in a skill. Put it in bmsuisse/devtools (
bdt lint,bdt pr, …) so it is checked automatically instead of relying on an agent to remember it. Write a skill only for judgment, conventions and context that tooling cannot express, and link to the matching devtools check where one exists.
<!-- SKILLS_TABLE_START -->
| Skill | Description |
|---|---|
| aiochannel-python | Correct patterns for channel-based asyncio concurrency in Python using the aiochannel library. Use this skill wheneve… |
| autoresearch | Autonomous iterative optimization loop for Python, SQL, ML, and Spark/Databricks. Define a measurable goal; the skill… |
| azure-cost | Query, analyze, and reduce Azure spending via the Cost Management REST API and Azure CLI. Covers cost breakdowns by s… |
| bms | Master skill for the bmsuisse platform — routes to the relevant skills based on sub-command. Always enables caveman c… |
| bms-code-review | BMS code review that fans out one focused subagent per concern (architecture, duplication, security, correctness, age… |
| bms-frontend-design | The BMS visual identity for internal web apps, built on the shared @bmsuisse/ui (sidebar/nav, form, dialog, and oth… |
| bms-plan-review | Review an implementation plan before any code is written: checks it against BMS conventions and the existing skills (… |
| clockify | Query and log time entries in Clockify via its REST API — check a timesheet, look up the workspace/user/project, crea… |
| code-comments | Write and review code comments so they earn their place instead of adding noise. Use this whenever writing new code (… |
| codeunit-analyzer | Comprehensive C-AL performance analyzer for Classic Microsoft Dynamics NAV (Navision). Targets Classic NAV anti-patte… |
| coding-guidelines-python | Apply and enforce Python-specific coding standards. Use alongside coding-guidelines for any Python file — covers typi… |
| coding-guidelines-sql | SQL and data warehouse coding guidelines for the BME data platform. Use whenever writing, reviewing, or refactoring S… |
| coding-guidelines-typescript | Apply and enforce TypeScript-specific coding standards. Use alongside coding-guidelines for any TypeScript file — cov… |
| cross-repo-discovery | Find where a repo lives — locally or in the Azure DevOps org — before assuming a piece of functionality doesn't exist… |
| data-modeling-dimensional | Dimensional data modeling guide for the Fabricks platform — covers the full pipeline from staging through raw, transf… |
| databricks-cli | Databricks CLI operations: auth, profiles, data exploration, bundles, and notebook execution. Use this skill for ANY… |
| databricks-sql-autotuner | Databricks SQL query optimizer and error fixer: analyzes a slow or broken SQL query, rewrites it for speed using SQL-… |
| design-review | Review a web app or page for visual design quality — layout, spacing, typography, colour/contrast, visual hierarchy,… |
| deslop | Remove AI slop from code and pull requests. Use this skill whenever the user wants to clean up AI-generated code, rev… |
| dev-workflow | End-to-end workflow for non-trivial coding tasks: worktree, draft PR early, implement, review, test, publish. Trigger… |
| duckdb | Guide for working with DuckDB — CLI usage, SQL execution, reading files (CSV, Parquet, JSON, Excel), extensions (http… |
| ducklake | Guide for working with DuckLake — the open lakehouse format and DuckDB extension that pairs a SQL catalog (metadata,… |
| fabricks-devops-issues | Orchestrates Azure DevOps "Issue" work-item workflows in the Fabricks.Runtime repo — listing open issues so the user… |
| fabricks-devops-issues-resolver | End-to-end resolver for Fabricks.Runtime DevOps issues that have already been diagnosed and locally fixed by the fabr… |
| fabricks-glossary | Use this skill whenever company-specific jargon, acronyms, or domain terminology is needed to answer correctly. |
| fabricks-sql-analyzer | Analyzes all SQL files in the Fabricks.Runtime repository, builds a dependency DAG, runs performance heuristics, and… |
| fastapi-azure-auth | Azure Entra ID SSO for FastAPI using cookie-based sessions (MSAL, /login → /callback → session). Trigger on: Azure AD… |
| fastapi-guideline | Use this skill whenever working with FastAPI — building APIs, adding routes, structuring projects, streaming response… |
| init-app-stack | Use this skill whenever the user wants to bootstrap, scaffold, or initialize a new full-stack app with a Vite + React… |
| inter-without-ai-slop | Use Inter as a UI typeface in data-dense B2B apps (dashboards, tables, cockpits) without triggering the "generic AI d… |
| kendo-ui-angular | Use this skill whenever the user is working with Kendo UI for Angular — including the Data Grid, TreeList, TreeView,… |
| kendo-ui-react | KendoReact component library patterns and best practices for React developers. Trigger whenever the user works with K… |
| kendo-ui-vue | Use this skill whenever the user is working with Kendo UI for Vue — including the Data Grid, DropDownList, ComboBox,… |
| kull-generic-backend | Kull.GenericBackend — an ASP.NET Core middleware (Kull-AG/kull-generic-backend, NuGet package Kull.GenericBackend) th… |
| maintenance | Periodic repo upkeep for BMS Python (uv) and JS/TS (bun) repos, as one skill with a mode argument: dead-code (find/… |
| nicegui | Build Python web UIs with NiceGUI — covering layout, widgets, data binding, routing, and the AgGrid data grid. Use th… |
| playwright-python | Browser automation and visual verification with Playwright in Python. Use this whenever the user wants to drive a bro… |
| prek | Set up code formatting and pre-commit hooks using prek (fast Rust-based alternative to pre-commit) with prek.toml con… |
| procrastinate | PostgreSQL-based async task queue for Python using Procrastinate. Use this skill whenever the user is working with Pr… |
| python-autotuner | Python code optimizer and error fixer: analyzes a Python file or function, rewrites it for speed and quality one chan… |
| remove-ai-writing | "Detect and surgically fix AI writing patterns in English, German, French, or Italian text. Use this skill whenever t… |
| rich-data-tables | Use whenever building a UI table, list view, or dashboard panel showing records with amounts, dates, or statuses (inv… |
| scientific-revision | Use this skill whenever the user wants to verify, revise, or improve a scientific essay, academic paper, or any writt… |
| spark-connect | Guide for running PySpark code locally against a remote Databricks cluster via Spark Connect (databricks-connect). Us… |
| sql-optimization | "Universal SQL performance optimization assistant for comprehensive query tuning, indexing strategies, and database p… |
| tanstack-best-practices | Comprehensive best practices for TanStack libraries in React applications — covering TanStack Query (React Query) dat… |
| testing-strategy | Decide what kind of test to write and in what order for a backend feature: HTTP-level first, then Playwright e2e for… |
<!-- SKILLS_TABLE_END -->
Add to ~/.claude/settings.json to install all plugins:
{
"extraKnownMarketplaces": {
"bmsuisse-skills": {
"source": {
"source": "github",
"repo": "bmsuisse/skills"
}
}
},
"enabledPlugins": {
"coding@bmsuisse-skills": true,
"onetrade@bmsuisse-skills": true,
"databricks@bmsuisse-skills": true,
"fabricks-data@bmsuisse-skills": true,
"writing@bmsuisse-skills": true,
"ui@bmsuisse-skills": true,
"caveman@bmsuisse-skills": true,
"azure-deploy@bmsuisse-skills": true,
"azure-diagnostics@bmsuisse-skills": true
}
}
| Plugin | Contents |
|---|---|
coding@bmsuisse-skills | Python, TypeScript, FastAPI, Postgres, TanStack, and general coding skills |
ui@bmsuisse-skills | Data tables, visual design/QA review, and writing style |
onetrade@bmsuisse-skills | C-AL / Classic NAV codeunit analysis |
databricks@bmsuisse-skills | Databricks CLI + Spark Connect local execution |
fabricks-data@bmsuisse-skills | Fabricks / Databricks data skills |
writing@bmsuisse-skills | Scientific and academic writing revision |
bms@bmsuisse-skills | BMsuisse master skill (/bms, /bms sql, /bms python, /bms data) |
caveman@bmsuisse-skills | Ultra-compressed caveman communication mode (~75% token reduction) |
azure-deploy@bmsuisse-skills | Azure deployments via azd/terraform/az with validation and RBAC checks |
azure-diagnostics@bmsuisse-skills | Azure production diagnostics via AppLens, Monitor, and resource health |
Then run these commands in Claude Code to apply the configuration:
# Add the marketplace (one-time setup — alternative to editing settings.json manually)
/plugin marketplace add bmsuisse/skills
# Install the plugins you want (or install all of them, as below)
/plugin install coding@bmsuisse-skills
/plugin install ui@bmsuisse-skills
/plugin install onetrade@bmsuisse-skills
/plugin install databricks@bmsuisse-skills
/plugin install fabricks-data@bmsuisse-skills
/plugin install writing@bmsuisse-skills
/plugin install bms@bmsuisse-skills
/plugin install caveman@bmsuisse-skills
/plugin install azure-deploy@bmsuisse-skills
/plugin install azure-diagnostics@bmsuisse-skills
# After any config change, reload without restarting
/reload-plugins
| Command | Description |
|---|---|
/plugin | Open the interactive plugin manager (browse, install, enable/disable) |
/plugin install <name>@bmsuisse-skills | Install a specific plugin |
/plugin uninstall <name>@bmsuisse-skills | Remove a plugin |
/plugin enable <name>@bmsuisse-skills | Re-enable a disabled plugin |
/plugin disable <name>@bmsuisse-skills | Disable without uninstalling |
/reload-plugins | Reload all active plugins without restarting Claude Code |
Once installed, skills are available as slash commands in Claude Code. Type / to see all available commands, or invoke them directly:
/coding-guidelines-python # activate Python coding standards
/fastapi-guideline # load FastAPI best practices
/init-app-stack # scaffold a Vite+React+TanStack+shadcn / FastAPI+asyncpg app
/databricks-cli # Databricks CLI operations
/autoresearch # start an autonomous research loop
/deslop # clean AI slop from code or PRs
Skills also auto-trigger based on context — if a skill's description matches what you're doing, Claude Code may load it automatically without a slash command.
The plugin ships with PreToolUse hooks that automatically rewrite shell commands to use preferred tooling:
| You type | Gets remapped to |
|---|---|
python script.py | uv run python script.py |
python -m pytest | uv run -m pytest |
pip install foo | uv add foo |
pytest, ruff, ty | uv run pytest, uv run ruff, ... |
npm install | bun install |
npm install foo | bun add foo |
npx foo | bunx foo |
yarn add foo | bun add foo |
pnpm run dev | bun run dev |
This happens transparently — no config needed. The hooks activate for any plugin that includes them (coding, bms, etc.).
Each plugin bundles a curated set of skills:
| Plugin | Skills included | Use case |
|---|---|---|
coding | autoresearch, coding-guidelines-python, coding-guidelines-typescript, deslop, fastapi-guideline, init-app-stack, postgres-best-practices, postgres-test-setup, sql-optimization, tanstack-best-practices | General dev work |
ui | rich-data-tables, inter-without-ai-slop, design-review | Data tables, writing style, visual QA |
onetrade | codeunit-analyzer | Classic NAV / C-AL analysis |
databricks | databricks-cli, spark-connect | Databricks & Spark |
fabricks-data | fabricks-glossary, fabricks-sql-analyzer | Fabricks data platform |
writing | remove-ai-writing, scientific-revision | Writing & docs |
bms | bms (master), coding-guidelines-sql, coding-guidelines-python, coding-guidelines-typescript, sql-optimization, data-modeling-dimensional, fabricks-glossary | All BMSuisse standards via /bms |
caveman | caveman, caveman-review, caveman-commit, caveman-help (from JuliusBrussee/caveman) | Token-efficient communication |
azure-deploy | azure-deploy (from microsoft/azure-skills) | Azure deployments |
azure-diagnostics | azure-diagnostics (from microsoft/azure-skills) | Azure production diagnostics |
We highly recommend Caveman by Julius Brussee. It cuts token usage ~75% by having the agent respond in ultra-compressed style while keeping full technical accuracy. Less noise, faster, cheaper.
bun x skills add https://github.com/JuliusBrussee/caveman
Or via the marketplace:
"caveman@bmsuisse-skills": true
Full credit to Julius for creating and maintaining this — outstanding contribution to the community.
The skills CLI reads directly from GitHub — no registration needed.
# recommended
bun x skills add https://github.com/bmsuisse/skills --skill <skill-name>
# alternative
npx skills add https://github.com/bmsuisse/skills --skill <skill-name>
# recommended
bun x skills add https://github.com/bmsuisse/skills
# alternative
npx skills add https://github.com/bmsuisse/skills
The CLI auto-detects your agent platform and installs into the right directory:
| Platform | Directory |
|---|---|
| Claude Code | .claude/skills/ |
| Cursor | .cursor/rules/ |
| Codex CLI | ~/.codex/skills/ |
| Antigravity | .agents/skills/ or .agent/skills/ |
| Gemini CLI | auto-detected |
https://skills.sh/bmsuisse/skills/<skill-name>
Skills appear on the skills.sh leaderboard automatically based on install telemetry — no manual registration required.
Start a new session and ask your agent something that should trigger the skill.
/bms is a master skill that activates the full bmsuisse coding context in one command. It routes to the relevant sub-skills based on a sub-command and always enables caveman communication style.
| Command | Loads | Good for |
|---|---|---|
/bms | coding-guidelines-sql · coding-guidelines-python · coding-guidelines-typescript · fabricks-glossary | General session — all core standards active |
/bms sql | coding-guidelines-sql · sql-optimization · fabricks-glossary | SQL authoring, reviews, refactoring |
/bms python | coding-guidelines-python | Python development, PR reviews |
/bms data | data-modeling-dimensional · fabricks-glossary | Designing or reviewing fact/dim tables |
For deep optimization work, chain with the specialized skills:
/databricks-sql-autotuner/python-autotuner/bms sql
│
├─ reads bms/SKILL.md (master router, ~2.5k chars)
│
├─ runs load_skills.py sql (helper script)
│ └─ concatenates:
│ coding-guidelines-sql/SKILL.md
│ sql-optimization/SKILL.md
│ fabricks-glossary/SKILL.md
│
└─ applies all rules + caveman mode → "BMS SQL active."
The helper script at skills/bms/scripts/load_skills.py concatenates the relevant SKILL.md files and prints them as combined content. Each sub-skill remains the single source of truth — no duplication.
Plugin (recommended) — installs bms + all sub-skills as a self-contained plugin:
claude plugin marketplace add bmsuisse/skills
claude plugin install bms@bmsuisse-skills
skills CLI — installs the bms skill only (sub-skills must already be installed):
bun x skills add https://github.com/bmsuisse/skills --skill bms # recommended
npx skills add https://github.com/bmsuisse/skills --skill bms # alternative
When installed as a plugin, load_skills.py resolves sub-skill paths via the CLAUDE_PLUGIN_ROOT environment variable that Claude Code injects at runtime. In the repo, it falls back to the repo-relative path. This means the script works correctly in both contexts without configuration.
Use skill-creator to guide you through the full lifecycle — drafting, test cases, evaluation, and iteration:
bun x skills add https://github.com/anthropics/skills --skill skill-creator # recommended
# npx skills add https://github.com/anthropics/skills --skill skill-creator
Then ask your agent: "Help me create a skill for X" and it will walk you through intent capture, writing the SKILL.md, running test cases, reviewing results, and iterating until the skill is ready.
Also helpful is the playwright-cli skill, which you can install like this:
bun install -g @playwright/cli@latest
bunx playwright-cli install --skills
You can give a hint to the agent to use playwright cli to query complex web pages with javascript.
Each skill lives in its own directory under skills/:
skills/
└── your-skill-name/
├── SKILL.md ← required: instructions + YAML frontmatter
├── scripts/ ← optional: helper scripts
├── references/ ← optional: reference documentation
└── assets/ ← optional: templates, icons, etc.
---
name: your-skill-name
description: What the skill does and when to trigger it. Be specific — this is how the agent decides whether to use it.
---
# Your Skill
Instructions for the agent to follow...
git checkout -b skill/<skill-name>2.
hooks/register.js 116 lines1// Shows "PR #69 ✓ · closes #68" (clickable links) in the band above the prompt, from `bdt pr info --json`.
2// Needs `bdt` on PATH; with no PR for the current branch (or no bdt) the band is left alone.
3
4const REFRESH_MS = 30_000;
5
6// Single-width symbols, not emoji, so the band lines up in every terminal
7const BUILD = {
8 passing: { symbol: "✓", color: "green" },
9 failing: { symbol: "✗", color: "red" },
10 pending: { symbol: "…", color: "yellow" },
11 waiting: { symbol: "⏸", color: "yellow" },
12};
13
14// The last `bdt pr info --json` result, or null when the branch has no PR
15let info = null;
16let isRefreshing = false;
17let timer = null;
18
19const LINK = /^https:\/\/(github\.com|dev\.azure\.com)\/[^\s\x00-\x1f]*$/;
20
21// `bdt` output only if it has the shape `bdt pr info --json` produces, so a shadowing or outdated `bdt` on PATH
22// can't make the band render an arbitrary link
23function validated(i) {
24 const isLink = (x) =>
25 typeof x.number === "number" &&
26 typeof x.url === "string" &&
27 LINK.test(x.url);
28 return isLink(i) && Array.isArray(i.issues) && i.issues.every(isLink)
29 ? i
30 : undefined;
31}
32
33// `undefined`: couldn't ask (bdt missing or timed out, unusable output) -- keep showing the last answer.
34// `null`: bdt answered that there is no PR for this branch.
35async function readInfo($) {
36 try {
37 const r = await $.process.run(["bdt", "pr", "info", "--json"]);
38 return r.exitCode === 0 ? validated(JSON.parse(r.stdout)) : null;
39 } catch {
40 return undefined;
41 }
42}
43
44async function refresh($) {
45 // A slow `gh` call must not stack up behind the timer
46 if (isRefreshing) return;
47 isRefreshing = true;
48 try {
49 const next = await readInfo($);
50 if (next !== undefined && JSON.stringify(next) !== JSON.stringify(info)) {
51 info = next;
52 $.ui.invalidate("ui.render");
53 }
54 } catch {
55 // a failed redraw must not become an unhandled rejection in a timer callback
56 } finally {
57 isRefreshing = false;
58 }
59}
60
61export function register(on) {
62 on("session.start", async ($, e, next) => {
63 // once per module load, not per session.start
64 timer ??= $.clock.every(REFRESH_MS, () => refresh($));
65 // Not awaited: the session starts right away, and the band fills in when bdt answers
66 refresh($);
67 return next(e);
68 });
69
70 // A turn is when the branch is most likely to have been pushed or a PR opened
71 on("turn.complete", async ($, e, next) => {
72 refresh($);
73 return next(e);
74 });
75
76 on("ui.render", { component: "AbovePrompt" }, async ($, e, next) => {
77 // Keep whatever Claude Code or other mods draw in the band
78 const theirs = await next(e);
79 if (!info) return theirs;
80
81 const { Box, Text, Link } = $.ui.resolve(e);
82 const build = BUILD[info.build];
83 const state = info.draft
84 ? "draft"
85 : info.state === "open"
86 ? ""
87 : info.state;
88
89 const line = Box({
90 flexDirection: "row",
91 columnGap: 1,
92 children: [
93 Link({ href: info.url, label: "PR #" + info.number }),
94 ...(build
95 ? [
96 Text({
97 color: build.color,
98 children: [build.symbol + " " + info.build],
99 }),
100 ]
101 : []),
102 ...(state ? [Text({ dimColor: true, children: [state] })] : []),
103 ...info.issues.flatMap((issue) => [
104 Text({ dimColor: true, children: ["· closes"] }),
105 Link({ href: issue.url, label: "#" + issue.number }),
106 ]),
107 ],
108 });
109
110 return Box({
111 flexDirection: "column",
112 children: theirs ? [line, theirs] : [line],
113 });
114 });
115}
116