fluentui-design 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/LICENSE +21 -0
- package/README.md +129 -0
- package/dist/bin.d.ts +18 -0
- package/dist/bin.js +71 -0
- package/dist/bin.js.map +1 -0
- package/dist/skill/install-skill.d.ts +256 -0
- package/dist/skill/install-skill.js +546 -0
- package/dist/skill/install-skill.js.map +1 -0
- package/package.json +90 -0
- package/skills/fluentui-design/SKILL.md +184 -0
- package/skills/fluentui-design/references/checklists/accessibility-review.md +51 -0
- package/skills/fluentui-design/references/checklists/design-before-code.md +53 -0
- package/skills/fluentui-design/references/checklists/visual-review.md +45 -0
- package/skills/fluentui-design/references/foundation/accessibility.md +70 -0
- package/skills/fluentui-design/references/foundation/composition-and-state.md +92 -0
- package/skills/fluentui-design/references/foundation/responsive-and-localization.md +63 -0
- package/skills/fluentui-design/references/foundation/styling-and-tokens.md +71 -0
- package/skills/fluentui-design/references/index.md +42 -0
- package/skills/fluentui-design/references/maintenance/refresh-and-repin.md +68 -0
- package/skills/fluentui-design/references/patterns/PAT-001-application-shell.md +77 -0
- package/skills/fluentui-design/references/patterns/PAT-002-list-page.md +85 -0
- package/skills/fluentui-design/references/patterns/PAT-003-record-detail.md +74 -0
- package/skills/fluentui-design/references/patterns/PAT-004-form-page.md +78 -0
- package/skills/fluentui-design/references/patterns/PAT-005-contextual-edit.md +75 -0
- package/skills/fluentui-design/references/patterns/PAT-006-settings-page.md +78 -0
- package/skills/fluentui-design/references/patterns/PAT-007-multi-step-task.md +79 -0
- package/skills/fluentui-design/references/patterns/PAT-008-dashboard.md +78 -0
- package/skills/fluentui-design/references/rules/index.md +97 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `fluentui-design` skill are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the skill uses
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Each release records three things: the skill version, the baseline
|
|
8
|
+
`@fluentui/react-components` package version, and the pinned `fluentui-mcp` facts commit. See
|
|
9
|
+
[MAINTENANCE.md](MAINTENANCE.md) for the re-pin procedure.
|
|
10
|
+
|
|
11
|
+
## [0.1.0] - 2026-09-20
|
|
12
|
+
|
|
13
|
+
### Baseline
|
|
14
|
+
|
|
15
|
+
| Item | Value |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `@fluentui/react-components` | 9.74.7 |
|
|
18
|
+
| React peer range | `>=16.14.0 <20.0.0` |
|
|
19
|
+
| `fluentui-mcp` facts commit | d595d79 |
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- Sourced evidence pipeline: a 45-entry source catalog (`SRC-001`..`SRC-045`), an analyzed coverage
|
|
24
|
+
matrix, and a findings/conflicts record.
|
|
25
|
+
- Rules catalog with 30 stable rules (`RULE-001`..`RULE-030`), each traced to its evidence.
|
|
26
|
+
- Eight application patterns (`PAT-001`..`PAT-008`) with decision routes and a generated reference
|
|
27
|
+
index.
|
|
28
|
+
- The `fluentui-design` skill package (`SKILL.md` plus `references/`), mirrored byte-for-byte to
|
|
29
|
+
`.agents/skills/fluentui-design/`.
|
|
30
|
+
- Verification tooling: example snippets are type-checked but never executed, secrets are scanned,
|
|
31
|
+
freshness is pinned, and generated output is drift-checked.
|
|
32
|
+
- A runnable Vite + React fixture application with Playwright and axe coverage of the list, editor,
|
|
33
|
+
overlays, states, theming, and narrow viewports.
|
|
34
|
+
- An evaluation set: 12 fixed tasks, a 7-dimension rubric, and deterministic recorded results, with
|
|
35
|
+
a reproduction gate (`npm run check:evaluation`).
|
|
36
|
+
|
|
37
|
+
### Replaced guidance history
|
|
38
|
+
|
|
39
|
+
No guidance has been replaced in the initial release, so this section is empty. It exists now so
|
|
40
|
+
that later replacements are appended here rather than edited into history.
|
|
41
|
+
|
|
42
|
+
When guidance is superseded, add one entry per replaced item in this shape:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
- RULE-0XX: <what changed>. Reason: <why>. Superseded by: RULE-0YY.
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The replaced rule keeps its id, and the successor lists it in the successor's `supersedes` array.
|
|
49
|
+
The old rule's text also gains a "Superseded by `RULE-0YY`" sentence, so the forward pointer is
|
|
50
|
+
visible. Ids are never reused or renumbered. See [MAINTENANCE.md](MAINTENANCE.md) section 6.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 blendsdk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Fluent UI Design Skill
|
|
2
|
+
|
|
3
|
+
An evidence-backed Agent Skill that helps a coding agent design, implement, and review coherent
|
|
4
|
+
standalone web applications with **Fluent UI React v9**. It focuses on *application composition*:
|
|
5
|
+
which surface to use, where it belongs, and how the parts work together — not on repeated component
|
|
6
|
+
API recall.
|
|
7
|
+
|
|
8
|
+
## Scope
|
|
9
|
+
|
|
10
|
+
The skill answers composition questions:
|
|
11
|
+
|
|
12
|
+
- Choosing a surface: a page, a drawer, a dialog, or an inline editor.
|
|
13
|
+
- Arranging navigation, page chrome, commands, and content regions.
|
|
14
|
+
- Deciding state ownership, the save model, and how submission reports back.
|
|
15
|
+
- Laying out forms, data grids, tabs, and multi-step task flows.
|
|
16
|
+
- Reviewing accessibility, responsive behavior, and visual coherence.
|
|
17
|
+
|
|
18
|
+
It does **not** restate component props, imports, or slots. Every rule and pattern is derived from a
|
|
19
|
+
reviewed set of sources and cites the evidence it came from.
|
|
20
|
+
|
|
21
|
+
## Division of labor with the sibling `fluentui` skill
|
|
22
|
+
|
|
23
|
+
This project is deliberately complementary to the API-focused `fluentui` skill produced by the
|
|
24
|
+
sibling `fluentui-mcp` repository.
|
|
25
|
+
|
|
26
|
+
| Skill | Owns | Use it for |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `fluentui-design` (this project) | Composition rules and patterns, with sourced design evidence | "Where should this go, and how should the parts work together?" |
|
|
29
|
+
| `fluentui` (sibling) | Pinned API facts: exact props, types, imports, slots | "What is the exact prop or import for this component?" |
|
|
30
|
+
|
|
31
|
+
The two skills are meant to be co-installed. `fluentui-design` links to `fluentui` for API facts
|
|
32
|
+
instead of copying them, so API drift cannot silently desynchronize the two.
|
|
33
|
+
|
|
34
|
+
## Install
|
|
35
|
+
|
|
36
|
+
Install the skill into the agent clients detected on your machine with one command:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
npx -y fluentui-design skill install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The installer copies the bundled skill into each detected client's skill directory. Use the options
|
|
43
|
+
below to change what it targets:
|
|
44
|
+
|
|
45
|
+
| Option | Purpose |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `--all` | Install into every detected client instead of asking. |
|
|
48
|
+
| `--target <dir>` | Install into a specific skill directory; repeat the flag for more than one. |
|
|
49
|
+
| `--project` | Prefer the current project's skill directory over the global one. |
|
|
50
|
+
| `--link` | Symlink the bundled skill instead of copying it. |
|
|
51
|
+
| `--dry-run` | Report what would change without writing anything. |
|
|
52
|
+
|
|
53
|
+
Inspect or remove an installation with the `status` and `uninstall` subcommands:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
npx -y fluentui-design skill status
|
|
57
|
+
npx -y fluentui-design skill uninstall --target <dir>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Usage
|
|
61
|
+
|
|
62
|
+
The skill is authored under [`skill/`](skill/SKILL.md) and mirrored byte-for-byte to
|
|
63
|
+
[`.agents/skills/fluentui-design/`](.agents/skills/fluentui-design/SKILL.md). Install it the way an
|
|
64
|
+
agent discovers skills:
|
|
65
|
+
|
|
66
|
+
1. Copy `.agents/skills/fluentui-design/` into your agent's skill directory, or point the agent at
|
|
67
|
+
this repository's `.agents/skills/` folder.
|
|
68
|
+
2. Install the sibling `fluentui` skill from `fluentui-mcp` next to it.
|
|
69
|
+
3. Start from [`skill/SKILL.md`](skill/SKILL.md). It routes each task to the pattern or reference
|
|
70
|
+
that resolves the decision.
|
|
71
|
+
|
|
72
|
+
The entry point lists the skill's triggers and non-triggers, and the generated
|
|
73
|
+
[reference index](skill/references/index.md) maps every decision to the patterns and rules that
|
|
74
|
+
resolve it.
|
|
75
|
+
|
|
76
|
+
## Version baseline
|
|
77
|
+
|
|
78
|
+
The bundled facts are pinned to one reviewed baseline. Update the table below deliberately (see
|
|
79
|
+
[MAINTENANCE.md](MAINTENANCE.md)); never edit generated output by hand.
|
|
80
|
+
|
|
81
|
+
| Item | Value |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| UI library | `@fluentui/react-components` **9.74.7** |
|
|
84
|
+
| React peer range | `>=16.14.0 <20.0.0` |
|
|
85
|
+
| API-fact source | `fluentui-mcp` enhanced schema pinned at commit **d595d79** |
|
|
86
|
+
|
|
87
|
+
If an application uses a different package version, the skill tells the agent to say so and
|
|
88
|
+
re-verify the rules it uses.
|
|
89
|
+
|
|
90
|
+
## Repository layout
|
|
91
|
+
|
|
92
|
+
| Path | Contents |
|
|
93
|
+
| --- | --- |
|
|
94
|
+
| `skill/` | The authored skill (`SKILL.md` + `references/`), mirrored to `.agents/skills/`. |
|
|
95
|
+
| `sources/`, `rules/`, `research/`, `facts/` | Source catalog, rules catalog, and analysis artifacts. |
|
|
96
|
+
| `scripts/` | Validators, generator, gates, and their tests. |
|
|
97
|
+
| `fixture/` | A Vite + React application that demonstrates one coherent composition, with Playwright + axe tests. |
|
|
98
|
+
| `evaluation/` | Fixed tasks, a rubric, and recorded deterministic evidence. |
|
|
99
|
+
|
|
100
|
+
## Commands
|
|
101
|
+
|
|
102
|
+
| Command | Purpose |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `npm run verify` | Full check: typecheck, lint, unit tests, catalog and skill gates, then Playwright + axe. |
|
|
105
|
+
| `npm run verify:static` | The browser-free subset; fast inner loop. |
|
|
106
|
+
| `npm run test` | Unit tests under `scripts/__tests__/`. |
|
|
107
|
+
| `npm run test:e2e` | Playwright tests under `fixture/e2e/`. |
|
|
108
|
+
|
|
109
|
+
## Known limitations
|
|
110
|
+
|
|
111
|
+
- **No model-provider evaluation.** Agent-answer quality and the skill-versus-baseline comparison in
|
|
112
|
+
[`evaluation/results.md`](evaluation/results.md) are marked `untested`. The recorded evidence is
|
|
113
|
+
deterministic: committed artifacts, gates, and accessibility findings, not generated answers.
|
|
114
|
+
- **Design assets are not fully analyzed.** The official Figma kits and Teams UI templates
|
|
115
|
+
(`SRC-045`) are recorded as a discovered expansion target; `SRC-002` covers only the public
|
|
116
|
+
getting-started page. Rules therefore lean on published guidance and the component library, not on
|
|
117
|
+
Figma files.
|
|
118
|
+
- **The dedicated v9 DataGrid usage page was not analyzed.** Grid rules lean on the accessibility
|
|
119
|
+
practices guide (APG) and the pinned package source (`SRC-027`).
|
|
120
|
+
- **Automated accessibility output is findings, not conformance.** The fixture is scanned with axe
|
|
121
|
+
and the results are reported as defects that were fixed; the project makes no WCAG conformance
|
|
122
|
+
claim.
|
|
123
|
+
|
|
124
|
+
## Maintenance
|
|
125
|
+
|
|
126
|
+
[MAINTENANCE.md](MAINTENANCE.md) documents how to recheck sources, detect redirects and content
|
|
127
|
+
changes, re-pin the baseline, find the rules affected by a fact change, rerun the fixture, and retain
|
|
128
|
+
a history of replaced guidance. [CHANGELOG.md](CHANGELOG.md) records each skill version with its
|
|
129
|
+
baseline. [COMPLETION-REPORT.md](COMPLETION-REPORT.md) closes the initial build honestly.
|
package/dist/bin.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `fluentui-design` command-line entry point.
|
|
4
|
+
*
|
|
5
|
+
* Only one command group is exposed today: `fluentui-design skill …`, which
|
|
6
|
+
* installs, inspects, and removes the Fluent UI design Agent Skill. The
|
|
7
|
+
* dispatcher keeps the top-level surface small so future command groups can be
|
|
8
|
+
* added without changing the skill installer.
|
|
9
|
+
*
|
|
10
|
+
* @module bin
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Runs the dispatcher for a full argument list.
|
|
14
|
+
*
|
|
15
|
+
* @param argv - Arguments after the `fluentui-design` program name.
|
|
16
|
+
* @returns Process exit code.
|
|
17
|
+
*/
|
|
18
|
+
export declare function main(argv: string[]): Promise<number>;
|
package/dist/bin.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* The `fluentui-design` command-line entry point.
|
|
4
|
+
*
|
|
5
|
+
* Only one command group is exposed today: `fluentui-design skill …`, which
|
|
6
|
+
* installs, inspects, and removes the Fluent UI design Agent Skill. The
|
|
7
|
+
* dispatcher keeps the top-level surface small so future command groups can be
|
|
8
|
+
* added without changing the skill installer.
|
|
9
|
+
*
|
|
10
|
+
* @module bin
|
|
11
|
+
*/
|
|
12
|
+
import fs from "node:fs";
|
|
13
|
+
import { fileURLToPath } from "node:url";
|
|
14
|
+
import { main as runSkillCommand } from "./skill/install-skill.js";
|
|
15
|
+
/** Prints the top-level help text. */
|
|
16
|
+
function printUsage() {
|
|
17
|
+
console.log(`The Fluent UI design Agent Skill command-line tool.
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
fluentui-design skill install [options] Install or update the skill
|
|
21
|
+
fluentui-design skill status [options] Show the installed version
|
|
22
|
+
fluentui-design skill uninstall [options] Remove the installed skill
|
|
23
|
+
fluentui-design --help Show this help
|
|
24
|
+
|
|
25
|
+
Run 'fluentui-design skill --help' for the installer options.`);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Runs the dispatcher for a full argument list.
|
|
29
|
+
*
|
|
30
|
+
* @param argv - Arguments after the `fluentui-design` program name.
|
|
31
|
+
* @returns Process exit code.
|
|
32
|
+
*/
|
|
33
|
+
export async function main(argv) {
|
|
34
|
+
const [command, ...rest] = argv;
|
|
35
|
+
if (command === undefined || command === "-h" || command === "--help") {
|
|
36
|
+
printUsage();
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
if (command === "skill") {
|
|
40
|
+
return runSkillCommand(rest);
|
|
41
|
+
}
|
|
42
|
+
console.error(`error: unknown command '${command}'`);
|
|
43
|
+
printUsage();
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* True when this module is the process entry point, resolving symlinks so the
|
|
48
|
+
* guard also works through npm's `.bin` shims.
|
|
49
|
+
*
|
|
50
|
+
* @returns True when this file is the entry point.
|
|
51
|
+
*/
|
|
52
|
+
function isEntryPoint() {
|
|
53
|
+
if (!process.argv[1]) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
return fs.realpathSync(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (isEntryPoint()) {
|
|
64
|
+
main(process.argv.slice(2)).then((code) => {
|
|
65
|
+
process.exitCode = code;
|
|
66
|
+
}, (error) => {
|
|
67
|
+
console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
process.exitCode = 1;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=bin.js.map
|
package/dist/bin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,IAAI,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEnE,sCAAsC;AACtC,SAAS,UAAU;IACjB,OAAO,CAAC,GAAG,CAAC;;;;;;;;8DAQgD,CAAC,CAAC;AAChE,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAEhC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACtE,UAAU,EAAE,CAAC;QACb,OAAO,CAAC,CAAC;IACX,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACxB,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,2BAA2B,OAAO,GAAG,CAAC,CAAC;IACrD,UAAU,EAAE,CAAC;IACb,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY;IACnB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,IAAI,YAAY,EAAE,EAAE,CAAC;IACnB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC9B,CAAC,IAAI,EAAE,EAAE;QACP,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC1B,CAAC,EACD,CAAC,KAAc,EAAE,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install and update the Fluent UI design Agent Skill into coding agents.
|
|
3
|
+
*
|
|
4
|
+
* The skill ships inside the `fluentui-design` package at
|
|
5
|
+
* `skills/fluentui-design/`. This installer copies it into the skill
|
|
6
|
+
* directories of the supported clients (OpenCode, Claude Code, Codex, and the
|
|
7
|
+
* shared `.agents/skills` convention), globally or per project. It replaces
|
|
8
|
+
* only the namespaced `fluentui-design/` directory and never touches any other
|
|
9
|
+
* skill.
|
|
10
|
+
*
|
|
11
|
+
* @module skill/install-skill
|
|
12
|
+
*/
|
|
13
|
+
/** The skill directory name installed into every client. */
|
|
14
|
+
export declare const SKILL_DIR_NAME = "fluentui-design";
|
|
15
|
+
/** The marker file written inside an installed skill directory. */
|
|
16
|
+
export declare const MARKER_FILE = ".fluentui-design-skill.json";
|
|
17
|
+
/** The value recorded in the marker's `source` field. */
|
|
18
|
+
export declare const SOURCE_NAME = "fluentui-design";
|
|
19
|
+
/** Prefix of the temporary sibling directory used during an atomic install. */
|
|
20
|
+
export declare const TEMP_PREFIX = ".fluentui-design-skill.tmp-";
|
|
21
|
+
/** Prefix of the backup directory kept while an install is in flight. */
|
|
22
|
+
export declare const BACKUP_PREFIX = ".fluentui-design-skill.bak-";
|
|
23
|
+
/**
|
|
24
|
+
* The shape of the marker file written into an installed skill directory.
|
|
25
|
+
*/
|
|
26
|
+
export interface SkillMarker {
|
|
27
|
+
/** The package version that was installed. */
|
|
28
|
+
version: string;
|
|
29
|
+
/** Fixed provenance string identifying the installer. */
|
|
30
|
+
source: string;
|
|
31
|
+
/** ISO-8601 timestamp of when the install happened. */
|
|
32
|
+
installedAt: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A skill directory layout for one supported coding agent.
|
|
36
|
+
*
|
|
37
|
+
* `global` and `project` are path segments relative to the home directory and
|
|
38
|
+
* the project root respectively.
|
|
39
|
+
*/
|
|
40
|
+
export interface ClientDefinition {
|
|
41
|
+
/** Stable identifier shown to the user, e.g. `opencode`. */
|
|
42
|
+
id: string;
|
|
43
|
+
/** Path segments for the global skills directory. */
|
|
44
|
+
global: string[];
|
|
45
|
+
/** Path segments for the project skills directory. */
|
|
46
|
+
project: string[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Supported clients and the directories in which each looks for skills.
|
|
50
|
+
*/
|
|
51
|
+
export declare const CLIENTS: ClientDefinition[];
|
|
52
|
+
/**
|
|
53
|
+
* A detected client with both of its skill directories resolved to absolute
|
|
54
|
+
* paths.
|
|
55
|
+
*/
|
|
56
|
+
export interface DetectedClient {
|
|
57
|
+
/** The client identifier. */
|
|
58
|
+
id: string;
|
|
59
|
+
/** Absolute global skills directory. */
|
|
60
|
+
globalDir: string;
|
|
61
|
+
/** Absolute project skills directory. */
|
|
62
|
+
projectDir: string;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Inputs for installing the skill into one skills directory.
|
|
66
|
+
*/
|
|
67
|
+
export interface InstallOptions {
|
|
68
|
+
/** Directory holding the skill tree to copy or link. */
|
|
69
|
+
sourceDir: string;
|
|
70
|
+
/** Skills directory to install into. */
|
|
71
|
+
targetDir: string;
|
|
72
|
+
/** Package version recorded in the marker. */
|
|
73
|
+
version: string;
|
|
74
|
+
/** Create a symlink instead of copying. */
|
|
75
|
+
link?: boolean;
|
|
76
|
+
/** Report the action without writing anything. */
|
|
77
|
+
dryRun?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The outcome of one install attempt.
|
|
81
|
+
*/
|
|
82
|
+
export interface InstallResult {
|
|
83
|
+
/** The skills directory that was targeted. */
|
|
84
|
+
targetDir: string;
|
|
85
|
+
/** The resolved destination path, `<targetDir>/fluentui-design`. */
|
|
86
|
+
dest: string;
|
|
87
|
+
/** True when the skill was copied. */
|
|
88
|
+
installed?: boolean;
|
|
89
|
+
/** True when the skill was symlinked. */
|
|
90
|
+
linked?: boolean;
|
|
91
|
+
/** True when the call ran in dry-run mode and wrote nothing. */
|
|
92
|
+
dryRun?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The outcome of one uninstall attempt.
|
|
96
|
+
*/
|
|
97
|
+
export interface UninstallResult {
|
|
98
|
+
/** The skills directory that was targeted. */
|
|
99
|
+
targetDir: string;
|
|
100
|
+
/** The resolved destination path, `<targetDir>/fluentui-design`. */
|
|
101
|
+
dest: string;
|
|
102
|
+
/** True when the destination existed and was removed. */
|
|
103
|
+
removed: boolean;
|
|
104
|
+
/** True when the call ran in dry-run mode and wrote nothing. */
|
|
105
|
+
dryRun: boolean;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Options parsed from the command line.
|
|
109
|
+
*/
|
|
110
|
+
export interface InstallerOptions {
|
|
111
|
+
/** Explicit `--target` directories. */
|
|
112
|
+
targets: string[];
|
|
113
|
+
/** Use project-level skill directories. */
|
|
114
|
+
project: boolean;
|
|
115
|
+
/** Create a symlink instead of copying. */
|
|
116
|
+
link: boolean;
|
|
117
|
+
/** Report only; write nothing. */
|
|
118
|
+
dryRun: boolean;
|
|
119
|
+
/** Install into every detected client. */
|
|
120
|
+
all: boolean;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The installer sub-commands.
|
|
124
|
+
*/
|
|
125
|
+
export type InstallerCommand = "install" | "status" | "uninstall" | "help";
|
|
126
|
+
/**
|
|
127
|
+
* The result of parsing an installer command line.
|
|
128
|
+
*/
|
|
129
|
+
export interface ParsedArgs {
|
|
130
|
+
/** The chosen sub-command, or `help`. */
|
|
131
|
+
command: InstallerCommand;
|
|
132
|
+
/** Parsed options. */
|
|
133
|
+
options: InstallerOptions;
|
|
134
|
+
/** A parse error message, when the input was invalid. */
|
|
135
|
+
error?: string;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Environment values the CLI depends on, injected so tests can run without
|
|
139
|
+
* touching the real machine.
|
|
140
|
+
*/
|
|
141
|
+
export interface InstallerIo {
|
|
142
|
+
/** Home directory used for global client detection. */
|
|
143
|
+
home?: string;
|
|
144
|
+
/** Project root used for project client detection. */
|
|
145
|
+
cwd?: string;
|
|
146
|
+
/** Whether interactive prompting is allowed. */
|
|
147
|
+
isTTY?: boolean;
|
|
148
|
+
/** Package version recorded in the marker; read from `package.json` when omitted. */
|
|
149
|
+
version?: string;
|
|
150
|
+
/** Override the packaged skill source directory. */
|
|
151
|
+
sourceDir?: string;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Resolves the packaged skill directory.
|
|
155
|
+
*
|
|
156
|
+
* Works in both layouts: shipped (`<package>/dist/skill` ->
|
|
157
|
+
* `<package>/skills`) and repository (`<repo>/src/skill` ->
|
|
158
|
+
* `<repo>/.agents/skills`). The packaged copy is preferred when both exist.
|
|
159
|
+
*
|
|
160
|
+
* @param moduleUrl - `import.meta.url` of this module.
|
|
161
|
+
* @param override - Optional explicit source directory.
|
|
162
|
+
* @returns Absolute path to the skill directory.
|
|
163
|
+
*/
|
|
164
|
+
export declare function resolveSourceDir(moduleUrl: string, override?: string): string;
|
|
165
|
+
/**
|
|
166
|
+
* Detects which clients are present on the machine.
|
|
167
|
+
*
|
|
168
|
+
* A client is present when its global directory, the global directory's
|
|
169
|
+
* parent, or its project directory exists.
|
|
170
|
+
*
|
|
171
|
+
* @param options - Detection inputs.
|
|
172
|
+
* @param options.home - Home directory.
|
|
173
|
+
* @param options.cwd - Project root.
|
|
174
|
+
* @param options.exists - Existence predicate (injectable for tests).
|
|
175
|
+
* @returns Detected clients with resolved global and project directories.
|
|
176
|
+
*/
|
|
177
|
+
export declare function detectClients(options: {
|
|
178
|
+
home: string;
|
|
179
|
+
cwd: string;
|
|
180
|
+
exists: (target: string) => boolean;
|
|
181
|
+
}): DetectedClient[];
|
|
182
|
+
/**
|
|
183
|
+
* Resolves the skills directories to operate on.
|
|
184
|
+
*
|
|
185
|
+
* Explicit `--target` directories win, then `--project`, otherwise every
|
|
186
|
+
* detected client's global directory is used.
|
|
187
|
+
*
|
|
188
|
+
* @param options - Selection options.
|
|
189
|
+
* @param options.targets - Explicit target directories.
|
|
190
|
+
* @param options.project - Use project directories instead of global ones.
|
|
191
|
+
* @param detected - Detected clients.
|
|
192
|
+
* @returns Absolute target skills directories.
|
|
193
|
+
*/
|
|
194
|
+
export declare function resolveTargets(options: InstallerOptions, detected: DetectedClient[]): string[];
|
|
195
|
+
/**
|
|
196
|
+
* Reads the installed marker, if present and parseable.
|
|
197
|
+
*
|
|
198
|
+
* @param targetDir - Installed skill directory.
|
|
199
|
+
* @returns The parsed marker, or undefined.
|
|
200
|
+
*/
|
|
201
|
+
export declare function readMarker(targetDir: string): SkillMarker | undefined;
|
|
202
|
+
/**
|
|
203
|
+
* Removes control and display-formatting characters from a value before
|
|
204
|
+
* printing it.
|
|
205
|
+
*
|
|
206
|
+
* The installed version is read back from disk, so it is untrusted input; the
|
|
207
|
+
* raw value could otherwise carry terminal escape sequences or bidirectional
|
|
208
|
+
* override characters into the output.
|
|
209
|
+
*
|
|
210
|
+
* @param value - Text to sanitize.
|
|
211
|
+
* @returns The text without control or display-formatting characters.
|
|
212
|
+
*/
|
|
213
|
+
export declare function sanitizeForDisplay(value: string): string;
|
|
214
|
+
/**
|
|
215
|
+
* Installs the skill into one skills directory by atomically replacing
|
|
216
|
+
* `fluentui-design/`.
|
|
217
|
+
*
|
|
218
|
+
* The tree is first copied into a temp sibling, then renamed over the
|
|
219
|
+
* destination. An existing destination is moved aside as a backup and restored
|
|
220
|
+
* if the rename fails, so a failed install never leaves a partial skill.
|
|
221
|
+
*
|
|
222
|
+
* @param options - Install inputs.
|
|
223
|
+
* @returns A summary of the action.
|
|
224
|
+
* @throws When the source is not a skill or the destination is unrelated.
|
|
225
|
+
*/
|
|
226
|
+
export declare function installSkill(options: InstallOptions): InstallResult;
|
|
227
|
+
/**
|
|
228
|
+
* Removes the installed skill from one skills directory.
|
|
229
|
+
*
|
|
230
|
+
* Only the `fluentui-design/` directory is removed; any sibling skill is
|
|
231
|
+
* untouched.
|
|
232
|
+
*
|
|
233
|
+
* @param options - Uninstall inputs.
|
|
234
|
+
* @param options.targetDir - Skills directory.
|
|
235
|
+
* @param options.dryRun - Report only, write nothing.
|
|
236
|
+
* @returns A summary of the action.
|
|
237
|
+
*/
|
|
238
|
+
export declare function uninstallSkill(options: {
|
|
239
|
+
targetDir: string;
|
|
240
|
+
dryRun?: boolean;
|
|
241
|
+
}): UninstallResult;
|
|
242
|
+
/**
|
|
243
|
+
* Parses argv into a sub-command and options.
|
|
244
|
+
*
|
|
245
|
+
* @param argv - Arguments after `skill` (or the full argument list).
|
|
246
|
+
* @returns The parsed command and options, plus an error for invalid input.
|
|
247
|
+
*/
|
|
248
|
+
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
249
|
+
/**
|
|
250
|
+
* Runs the installer CLI.
|
|
251
|
+
*
|
|
252
|
+
* @param argv - Arguments after `skill`.
|
|
253
|
+
* @param io - Injectable environment values.
|
|
254
|
+
* @returns Process exit code.
|
|
255
|
+
*/
|
|
256
|
+
export declare function main(argv: string[], io?: InstallerIo): Promise<number>;
|