Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e1b6a03
Initial plan
Copilot Feb 23, 2026
53f2a41
Initial plan for adding AI coding skills prompt to ng-add schematic
Copilot Feb 23, 2026
d85905e
Add AI coding skills prompt to cli-config schematic
Copilot Feb 23, 2026
7d653a5
Improve error logging in fetchSkillContent
Copilot Feb 23, 2026
9d2c441
Revert previous implementation per updated requirements
Copilot Feb 23, 2026
7e585b9
Implement AI skills with agent selection from node_modules
Copilot Feb 23, 2026
56be65b
Address code review: improve null safety in copySkillFile and addAISk…
Copilot Feb 23, 2026
c294c77
Remove tracked d.ts build artifact
Copilot Feb 23, 2026
2dd0a82
Add .agents/skills/ option for VS Code Agents
Copilot Feb 23, 2026
9c8e4b2
Switch to InquirerWrapper-based prompting and revert yarn.lock
Copilot Feb 24, 2026
cd601c0
Extract AGENT_CHOICES constant and use robust label-to-key mapping
Copilot Feb 24, 2026
53e73f5
Merge branch 'master' of https://github.com/IgniteUI/igniteui-cli int…
Marina-L-Stoyanova Mar 17, 2026
fa67f32
feat: add AI skills integration to project setup
Marina-L-Stoyanova Mar 18, 2026
b9967bd
fix: remove unused webcomponents package from upgradeable packages an…
Marina-L-Stoyanova Mar 18, 2026
c6c401d
fix(PackageManager): improve stdio handling during package installati…
Marina-L-Stoyanova Mar 18, 2026
189cef8
fix(PackageManager): simplify stdio handling in npm install calls
Marina-L-Stoyanova Mar 18, 2026
16dd25b
Potential fix for pull request finding
Marina-L-Stoyanova Mar 18, 2026
cd6cc33
feat: implement ScopedTree utility and refactor skill file handling i…
Marina-L-Stoyanova Mar 19, 2026
f966f2e
Merge branch 'copilot/add-ai-coding-instructions' of https://github.c…
Marina-L-Stoyanova Mar 19, 2026
3f44921
Potential fix for pull request finding
Marina-L-Stoyanova Mar 20, 2026
d2eb93f
Merge remote-tracking branch 'origin/master' into copilot/add-ai-codi…
damyanpetev Mar 26, 2026
9dfe26a
fix(): address comments
Marina-L-Stoyanova Mar 26, 2026
7469211
Merge branch 'copilot/add-ai-coding-instructions' of https://github.c…
Marina-L-Stoyanova Mar 26, 2026
bc8d895
fix: update addAISkills condition and correct package name in tests
Marina-L-Stoyanova Mar 26, 2026
15bb3c2
fix: add directory option to CliConfigOptions interface
Marina-L-Stoyanova Mar 26, 2026
2a8c381
fix: add filter to avoid overwriting existing AI skills files
Marina-L-Stoyanova Mar 26, 2026
ff9e6f5
feat: refactor AI skills handling and improve copyAISkillsToProject f…
Marina-L-Stoyanova Mar 27, 2026
a44105e
feat: implement add-skills command to copy AI coding skills to the pr…
Marina-L-Stoyanova Mar 30, 2026
6323f9a
fix: remove ProjectConfig check from add-skills command handler
Marina-L-Stoyanova Mar 30, 2026
9196837
update: add add-skills schematic to copy AI coding skills to the project
Marina-L-Stoyanova Apr 2, 2026
9ac4215
Merge branch 'master' of https://github.com/IgniteUI/igniteui-cli int…
Marina-L-Stoyanova Apr 2, 2026
a3f5051
Merge branch 'master' into copilot/add-ai-coding-instructions
kdinev Apr 2, 2026
3535d83
test: update ng-new schematic tests to include cli-config validation
Marina-L-Stoyanova Apr 2, 2026
9af78b6
Merge branch 'copilot/add-ai-coding-instructions' of https://github.c…
Marina-L-Stoyanova Apr 2, 2026
3c0af57
fix: remove redundant package installation in completeAndRun method
Marina-L-Stoyanova Apr 2, 2026
4ce9572
Merge branch 'master' into copilot/add-ai-coding-instructions
kdinev Apr 16, 2026
ae9c6f8
Update packages/ng-schematics/src/ng-new/index_spec.ts
kdinev Apr 16, 2026
43b3293
fix: update expectedCliConfig type and initialize collection to null
Marina-L-Stoyanova Apr 17, 2026
7be137b
Merge branch 'master' into copilot/add-ai-coding-instructions
damyanpetev Apr 17, 2026
aa33257
Merge branch 'master' into copilot/add-ai-coding-instructions
damyanpetev Apr 17, 2026
209c805
chore: revert resolve to fs change to origin
damyanpetev Apr 17, 2026
3fb05fe
refactor: roll skill copy under ai-config command
damyanpetev Apr 17, 2026
56915ae
refactor: drop extra config check and copy wrapper
damyanpetev Apr 17, 2026
d54b7e8
test: fix
damyanpetev Apr 17, 2026
d879d95
chore: cleanup non-functional leftovers
damyanpetev Apr 17, 2026
fe299fa
fix: always copy skill files
damyanpetev Apr 17, 2026
48a8bd4
docs: update changelog
damyanpetev Apr 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ All scaffolded projects now include AI-ready configuration files to enhance the
* **CLAUDE.md** for Claude Code integration ([#1546](https://github.com/IgniteUI/igniteui-cli/pull/1546))
* **VS Code MCP configuration** (`mcp.json`) pre-configured with `angular-cli`, `igniteui-cli`, and `igniteui-theming` MCP servers ([#1563](https://github.com/IgniteUI/igniteui-cli/pull/1563))
* **Claude skills** for component usage, theming customization, and bundle size optimization ([#1573](https://github.com/IgniteUI/igniteui-cli/pull/1573))
* **`ig ai-config` CLI command** to configure AI tooling in an existing project: writes `.vscode/mcp.json` with `igniteui-cli` and `igniteui-theming` MCP servers and copies AI coding skill files from installed Ignite UI packages to `.claude/skills/` ([#1502](https://github.com/IgniteUI/igniteui-cli/pull/1502))
* **AI skills auto-copy on `ng add`**: the `cli-config` Angular schematic now automatically copies skill files from the installed Ignite UI package's `skills/` directory into `.claude/skills/` as part of the `ng add igniteui-angular` flow ([#1502](https://github.com/IgniteUI/igniteui-cli/pull/1502))

---

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ ig start

## Configure AI Tooling

To automatically configure Ignite UI MCP servers for VS Code, run:
To automatically configure Ignite UI AI tooling - MCP servers and AI coding skills, run:

```bash
ig ai-config
```

This creates or updates `.vscode/mcp.json` in the current project with entries for both the [Ignite UI MCP](#mcp-server) and `igniteui-theming` MCP servers. Existing servers in the file are preserved. New projects are created with AI tooling configuration out of the box.
This creates or updates `.vscode/mcp.json` in the current project with entries for both the [Ignite UI MCP](#mcp-server) and `igniteui-theming` MCP servers. Existing servers in the file are preserved. It also copies any AI coding skill files from installed Ignite UI packages into the project. New projects are created with AI tooling configuration out of the box.

## MCP Server

Expand Down
15 changes: 13 additions & 2 deletions packages/cli/lib/commands/ai-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FsFileSystem, GoogleAnalytics, IFileSystem, Util } from "@igniteui/cli-core";
import { copyAISkillsToProject, FsFileSystem, GoogleAnalytics, IFileSystem, Util } from "@igniteui/cli-core";
import { ArgumentsCamelCase, CommandModule } from "yargs";
import * as path from "path";

Expand Down Expand Up @@ -63,13 +63,24 @@ export function configureMCP(fileSystem: IFileSystem = new FsFileSystem()): void
Util.log(Util.greenCheck() + ` MCP servers configured in ${configPath}`);
}

export function configureSkills(): void {
const result = copyAISkillsToProject();
if (result === "copied") {
Util.log(Util.greenCheck() + " AI skills added to the project.");
} else {
Util.warn("No AI skill files found. Make sure packages are installed (npm install) " +
"and your Ignite UI package includes a skills/ directory.", "yellow");
}
}

export function configure(fileSystem: IFileSystem = new FsFileSystem()): void {
configureMCP(fileSystem);
configureSkills();
}

const command: CommandModule = {
command: "ai-config",
describe: "Configure Ignite UI AI tooling (MCP servers)",
describe: "Configure Ignite UI AI tooling (MCP servers and AI coding skills)",
builder: (yargs) => yargs.usage(""),
async handler(_argv: ArgumentsCamelCase) {
GoogleAnalytics.post({
Expand Down
2 changes: 1 addition & 1 deletion packages/core/prompt/BasePromptSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export abstract class BasePromptSession {
/** Upgrade packages to use private Infragistics feed */
protected abstract upgradePackages();

/** Configure Ignite UI AI tooling (MCP servers) for the project */
/** Configure Ignite UI AI tooling (MCP servers and AI coding skills) for the project */
protected abstract configureAI(): Promise<void>;

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/core/prompt/InquirerWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { checkbox, input, select, Separator } from '@inquirer/prompts';
import { checkbox, confirm, input, select, Separator } from '@inquirer/prompts';
import { Context } from '@inquirer/type';

// ref - node_modules\@inquirer\input\dist\cjs\types\index.d.ts - bc for some reason this is not publicly exported
Expand Down Expand Up @@ -32,4 +32,8 @@ export class InquirerWrapper {
public static async checkbox(message: InputConfig & { choices: (string | Separator)[] }, context?: Context): Promise<string[]> {
return checkbox(message, context);
}

public static async confirm(message: { message: string; default?: boolean }, context?: Context): Promise<boolean> {
return confirm(message, context);
}
}
83 changes: 83 additions & 0 deletions packages/core/util/ai-skills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as path from "path";
import { App } from "./App";
import { IFileSystem, FS_TOKEN } from "../types/FileSystem";
import { ProjectConfig } from "./ProjectConfig";
import { Util } from "./Util";
import { NPM_ANGULAR, NPM_REACT, resolvePackage, UPGRADEABLE_PACKAGES } from "../update/package-resolve";

const CLAUDE_SKILLS_DIR = ".claude/skills";

Comment thread
Marina-L-Stoyanova marked this conversation as resolved.
/**
* Returns the list of 'skills/' directory paths found in installed
* Ignite UI packages that are relevant to the project's detected framework.
*/
function resolveSkillsRoots(): string[] {
const fs = App.container.get<IFileSystem>(FS_TOKEN);
const roots: string[] = [];

let framework: string | null = null;
try {
if (ProjectConfig.hasLocalConfig()) {
framework = ProjectConfig.getConfig().project?.framework?.toLowerCase() ?? null;
}
} catch { /* config not readable – fall through to scan all */ }

const allPkgKeys = Object.keys(UPGRADEABLE_PACKAGES);
let candidates: string[];
if (framework === "angular") {
candidates = [NPM_ANGULAR];
} else if (framework === "react") {
candidates = [NPM_REACT];
} else if (framework === "webcomponents") {
candidates = allPkgKeys.filter(k => k.startsWith("igniteui-webcomponents"));
} else {
candidates = allPkgKeys;
}

for (const pkg of candidates) {
const resolved = resolvePackage(pkg as keyof typeof UPGRADEABLE_PACKAGES);
const skillsRoot = `node_modules/${resolved}/skills`;
if (fs.directoryExists(skillsRoot) && !roots.includes(skillsRoot)) {
roots.push(skillsRoot);
}
}

return roots;
}

/**
* Copies skill files from the installed Ignite UI package(s) into .claude/skills/.
* Works with both real FS (CLI) and virtual Tree FS (schematics) through IFileSystem.
*/
export function copyAISkillsToProject(): "copied" | "no-source" {
const fs = App.container.get<IFileSystem>(FS_TOKEN);
const skillsRoots = resolveSkillsRoots();

if (!skillsRoots.length) {
return "no-source";
}

const multiRoot = skillsRoots.length > 1;
let copied = false;

for (const skillsRoot of skillsRoots) {
const rawPaths = fs.glob(skillsRoot, "**/*");
const pkgDirName = multiRoot ? path.basename(path.dirname(skillsRoot)) : "";

for (const p of rawPaths) {
// Normalize to posix and strip leading '/' so path.posix.relative works
// across both FsFileSystem (relative paths) and NgTreeFileSystem (tree-rooted paths)
const normP = p.replace(/\\/g, "/").replace(/^\//, "");
const normRoot = skillsRoot.replace(/\\/g, "/").replace(/^\//, "");
const rel = path.posix.relative(normRoot, normP);
const dest = multiRoot
? `${CLAUDE_SKILLS_DIR}/${pkgDirName}/${rel}`
: `${CLAUDE_SKILLS_DIR}/${rel}`;

fs.writeFile(dest, fs.readFile(p));
Util.log(`${Util.greenCheck()} Created ${dest}`);
copied = true;
}
}
return copied ? "copied" : "no-source";
}
1 change: 1 addition & 0 deletions packages/core/util/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ai-skills';
export * from './GoogleAnalytics';
export * from './Util';
export * from './ProjectConfig';
Expand Down
4 changes: 3 additions & 1 deletion packages/ng-schematics/src/cli-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as ts from "typescript";
import { DependencyNotFoundException } from "@angular-devkit/core";
import { chain, FileDoesNotExistException, Rule, SchematicContext, Tree } from "@angular-devkit/schematics";
import * as jsonc from "jsonc-parser";
import { addClassToBody, FormatSettings, NPM_ANGULAR, resolvePackage, TypeScriptAstTransformer, TypeScriptUtils } from "@igniteui/cli-core";
import { addClassToBody, copyAISkillsToProject, FormatSettings, NPM_ANGULAR, resolvePackage, TypeScriptAstTransformer, TypeScriptUtils } from "@igniteui/cli-core";
import { AngularTypeScriptFileUpdate } from "@igniteui/angular-templates";
import { createCliConfig } from "../utils/cli-config";
import { setVirtual } from "../utils/NgFileSystem";
Expand Down Expand Up @@ -120,6 +120,8 @@ function importStyles(): Rule {

export function addAIConfig(): Rule {
return (tree: Tree) => {
copyAISkillsToProject();

const mcpFilePath = "/.vscode/mcp.json";
const angularCliServer = {
command: "npx",
Expand Down
2 changes: 1 addition & 1 deletion packages/ng-schematics/src/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"factory": "./cli-config/index"
},
"ai-config": {
"description": "Adds AI/MCP server configuration to .vscode/mcp.json.",
"description": "Configures AI tooling: MCP servers and AI coding skills.",
"factory": "./cli-config/index#addAIConfig"
},
"upgrade-packages": {
Expand Down
1 change: 1 addition & 0 deletions packages/ng-schematics/src/component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export function component(options: ComponentOptions): Rule {
component: projLib.components,
custom: projLib.getCustomTemplates()
};
void properties; // cache templates for use inside chooseActionLoop
let prompt: SchematicsPromptSession;
if (!options.template || !options.name) {
prompt = new SchematicsPromptSession(templateManager);
Expand Down
3 changes: 2 additions & 1 deletion spec/acceptance/help-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ describe("Help command", () => {
upgrade-packages upgrades Ignite UI Packages
mcp Starts the Ignite UI MCP server for AI assistant
integration
ai-config Configure Ignite UI AI tooling (MCP servers)
ai-config Configure Ignite UI AI tooling (MCP servers and AI
coding skills)
Options:
-v, --version Show current Ignite UI CLI version [boolean]
-h, --help Show help [boolean]`.replace(/\s/g, "");
Expand Down
2 changes: 2 additions & 0 deletions spec/unit/PromptSession-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ describe("Unit - PromptSession", () => {
spyOn(Util, "log");
spyOn(add, "addTemplate").and.returnValue(Promise.resolve(true));
spyOn(PackageManager, "flushQueue").and.returnValue(Promise.resolve());
spyOn(PackageManager, "installPackages").and.returnValue(Promise.resolve());
spyOn(start, "start").and.returnValue(Promise.resolve());

spyOn(InquirerWrapper, "select").and.returnValues(
Expand Down Expand Up @@ -667,6 +668,7 @@ describe("Unit - PromptSession", () => {
spyOn(Util, "log");
spyOn(add, "addTemplate").and.returnValue(Promise.resolve(true));
spyOn(PackageManager, "flushQueue").and.returnValue(Promise.resolve());
spyOn(PackageManager, "installPackages").and.returnValue(Promise.resolve());
//spyOn(start, "start").and.returnValue(Promise.resolve({port: 3333 }));
spyOn(start, "start").and.returnValue(Promise.resolve());

Expand Down
3 changes: 2 additions & 1 deletion spec/unit/ai-config-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from "path";
import { GoogleAnalytics, IFileSystem, Util } from "@igniteui/cli-core";
import { App, FS_TOKEN, GoogleAnalytics, IFileSystem, Util } from "@igniteui/cli-core";
import { configureMCP } from "../../packages/cli/lib/commands/ai-config";
import * as aiConfig from "../../packages/cli/lib/commands/ai-config";

Expand Down Expand Up @@ -118,6 +118,7 @@ describe("Unit - ai-config command", () => {

describe("handler", () => {
it("posts analytics and calls configure", async () => {
App.container.set(FS_TOKEN, createMockFs());
const fs = require("fs");
spyOn(fs, "readFileSync").and.throwError(new Error("ENOENT"));
spyOn(fs, "existsSync").and.returnValue(false);
Expand Down
Loading
Loading