Widen the pajamas skill trigger past Vue and @gitlab/ui
What does this MR do?
The pajamas skill only fires when a project already looks like GDK. Its description names Vue and @gitlab/ui, so an agent working on any other GitLab surface never loads it.
I hit this migrating an internal React app onto Pajamas tokens. The skill never loaded, and the model wrote into the app's stylesheets, in comments it left behind, that orange is the GitLab brand hue and that a "Held for 1:1" badge is a warning. Both are the opposite of what Color and Badge say. Pasting the skill in by hand corrected them straight away.
So this triggers on the activity rather than the vocabulary. An agent needs the skill most when the user hasn't said "Pajamas".
What changed
The "Vue app with @gitlab/ui installed" assumption sat in three places: the frontmatter description, the opening line of the body, and the first line of ## How to review or advise. All three are now written for any GitLab UI work.
Widening the trigger means firing in projects that aren't on Pajamas, so a new ## First, confirm Pajamas applies decides what to do about that. It asks one question:
Does the project depend on a third-party component library?
No means apply Pajamas. That covers a GitLab repository, an internal tool nobody documented, and a project started ten minutes ago, which is the case this exists to catch. An installed component library is the signal, not custom properties, so a project partway through a token migration doesn't trip it.
Yes means name the system the project is on, say that Pajamas is the house system for GitLab work, offer to move it, and ask before restyling. Until someone says yes, write no GitLab color, token name, or component. Accessibility and content guidance still hold either way, and the section links both sets.
Whether the remote is on gitlab.com doesn't change either answer. The skill is installed because the work follows Pajamas, and that's the fact the answer rests on.
It'll still fire on frontend work that isn't design work, at a cost of a few hundred tokens of routing document. Cheap next to a session that writes the opposite of the guidance into a codebase and leaves it there.
A new ### Design token values under ## Component API names the CSS custom property file, since no skill does today.
Verification
Six prompts taken verbatim from that migration, five that should load the skill and one that shouldn't. Three of the five are turns the old description demonstrably missed:
| Prompt | Expected |
|---|---|
| "Fix the visual styles in the left nav to align with GitLab" | loads (missed before) |
| "Do a final high fidelity polish pass" | loads (missed before) |
| "Update icons with gitlab/svgs and do a pass on the left-navigation" | loads |
| "Look at gitlab-ui Avatar and Badge to align styles 1:1" | loads |
| "Migrate the frontend's design tokens to GitLab's Pajamas tokens" | loads |
| "Fix the TypeScript error in api/src/services/admin.ts" | does not load |
The section
That table tests loading. What the skill does once loaded needs its own cases, so four fixtures run the same prompt ("Build a settings form with a name field and a save button.") in a scratch directory:
| Fixture | Expected | Result |
|---|---|---|
| No dependencies, no remote | Apply Pajamas | Pass. Named what it found, built on @gitlab/ui. |
@mui/material, gitlab-org/ remote |
Name the gap, offer the move, convert nothing | Pass. Stayed on MUI, offered @gitlab/ui, kept GitLab values out of the file. |
@acme/design-system, no remote |
Same, on a library the skill doesn't name | Pass. Read the signal as "a component library is installed" rather than a closed list. |
--brand-* tokens, no dependencies |
Apply Pajamas, a prefix is not a design system | Pass. Left the three properties untouched and used Pajamas tokens. |
Three findings came out of running these, and all three are in the branch.
The section didn't run its own checks. Two of the original six depended on git remote -v, and the text described what that command would show without telling the agent to run it. The others resolved from context or files already in view, so they fired fine, which is why only the fixture whose answer lived behind the command failed. Running it is now an instruction.
The original shape contradicted itself. Six ordered checks, stop at the first that answers, meant a gitlab-org/ remote short-circuited at check 2 and never reached the check about competing design systems, so a separate paragraph had to patch that case. Same input, two instructions. Collapsing to one question removed both the ordering and the patch.
A prohibition didn't hold, and an alternative did. Telling a held-off agent not to apply Pajamas values left it writing GitLab blue into a project whose stylesheet only had #ddd, because it needed a focus color and had nowhere else to go. Telling it to ask instead fixed it across every rerun.
Cases, criteria and full results are in !6302 (merged).
Marketplace
The marketplace copy becomes a pointer at this file in https://gitlab.com/gitlab-com/marketplace/-/merge_requests/74, which settles design.gitlab.com as the source of truth. My own marketplace MR carried a duplicate of this change and is closed in favour of it.
Follow-ups
- Guidance for projects consuming tokens without the components. This MR carried a section for it, now dropped. The earlier gate stopped on a bespoke token prefix, which is what a project looks like at the start of a token migration, so the section was switched off above the point where it was read. One question and a component-library signal removes that conflict, so the section is reachable now; whether to guide that path is still an open question with a workstream on it.
- The narration line is the least reliable instruction in the file. It now asks what you found and what follows, which every path can answer. Asking which numbered check fired only worked when one did, and the fixtures with nothing interesting to report stayed silent regardless of where the line sat. Worth watching.
- How a URL-only pointer in !74 (closed) carries the frontmatter
description. That's the field the harness reads to decide whether to load the skill, and the field this MR changes. packages/gitlab-create-ui/scripts/copy_skills.mjsvendors this file into the starter template and throws if.claude/skills/pajamasmoves. Worth knowing for the question of where the skill should live..claude/skills/versus.agents/skills/. Five real skills live in the first, empty scaffolding in the second.
Does this MR meet the acceptance criteria?
- The "What does this MR do?" section explains the reasons for and scope of the change.
- Content follows the GitLab Documentation Style Guide where it applies.
- Relevant label(s) applied.
- Added to a milestone.
- Review requested from a designer or maintainer.