From 5e02ce8c865d29dfa5669ed4af845ec7b532419a Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Mon, 20 Jul 2026 18:59:12 -0700 Subject: [PATCH] chore(skills): move agent skills under playwright-core, add init-skills Consolidate all agent skills (playwright-cli, component testing, trace) under packages/playwright-core/src/tools/skills// and deploy them with a single copy rule. All installers share installSkills(), and the new `npx playwright init-skills` command installs all of them. --- .claude/skills/playwright-dev/dashboard.md | 2 +- eslint.config.mjs | 2 +- .../src/tools/cli-client/program.ts | 2 +- .../src/tools/cli-daemon/DEPS.list | 1 + .../src/tools/cli-daemon/program.ts | 12 +++--- packages/playwright-core/src/tools/index.ts | 1 + .../skill => skills/playwright-cli}/SKILL.md | 0 .../references/element-attributes.md | 0 .../references/playwright-tests.md | 0 .../references/request-mocking.md | 0 .../references/running-code.md | 0 .../references/session-management.md | 0 .../references/storage-state.md | 0 .../references/test-generation.md | 0 .../playwright-cli}/references/tracing.md | 0 .../references/video-recording.md | 0 .../playwright-component-testing}/SKILL.md | 0 .../references/gallery-spec.md | 0 .../references/migration.md | 0 .../references/react.md | 0 .../references/vue.md | 0 .../templates/react/Button.story.tsx | 0 .../templates/react/button.spec.ts | 0 .../templates/vue/Button.story.ts | 0 .../templates/vue/button.spec.ts | 0 .../playwright-trace}/SKILL.md | 0 .../playwright-core/src/tools/trace/DEPS.list | 1 + .../src/tools/trace/installSkill.ts | 32 --------------- .../src/tools/trace/traceCli.ts | 4 +- .../playwright-core/src/tools/utils/DEPS.list | 4 ++ .../src/tools/utils/installSkills.ts | 39 +++++++++++++++++++ packages/playwright/src/program.ts | 18 +++++++++ tests/mcp/cli-misc.spec.ts | 4 +- tests/mcp/init-agents.spec.ts | 19 +++++++++ tsconfig.json | 2 +- utils/build/build.js | 15 +------ utils/check_deps.js | 3 +- 37 files changed, 100 insertions(+), 61 deletions(-) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/SKILL.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/element-attributes.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/playwright-tests.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/request-mocking.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/running-code.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/session-management.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/storage-state.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/test-generation.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/tracing.md (100%) rename packages/playwright-core/src/tools/{cli-client/skill => skills/playwright-cli}/references/video-recording.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/SKILL.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/references/gallery-spec.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/references/migration.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/references/react.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/references/vue.md (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/templates/react/Button.story.tsx (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/templates/react/button.spec.ts (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/templates/vue/Button.story.ts (100%) rename packages/{skills/component-testing => playwright-core/src/tools/skills/playwright-component-testing}/templates/vue/button.spec.ts (100%) rename packages/playwright-core/src/tools/{trace => skills/playwright-trace}/SKILL.md (100%) delete mode 100644 packages/playwright-core/src/tools/trace/installSkill.ts create mode 100644 packages/playwright-core/src/tools/utils/installSkills.ts diff --git a/.claude/skills/playwright-dev/dashboard.md b/.claude/skills/playwright-dev/dashboard.md index 606ed221e22b3..326f338f73ce1 100644 --- a/.claude/skills/playwright-dev/dashboard.md +++ b/.claude/skills/playwright-dev/dashboard.md @@ -32,4 +32,4 @@ npx playwright cli video-stop # afterwards, use ffmpeg to turn the video into mp4 for sharing. ``` -Full CLI reference: `packages/playwright-core/src/tools/cli-client/skill/SKILL.md`. In this repo, invoke as `npx playwright cli` instead of `playwright-cli`. +Full CLI reference: `packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md`. In this repo, invoke as `npx playwright cli` instead of `playwright-cli`. diff --git a/eslint.config.mjs b/eslint.config.mjs index 4cce0bdb63a97..cf67709a83088 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -54,7 +54,7 @@ const ignores = [ "packages/playwright-core/types/*", "packages/playwright-ct-core/src/generated/*", "packages/playwright/bundles/expect/third_party/", - "packages/skills/", + "packages/playwright-core/src/tools/skills/", "packages/html-reporter/bundle.ts", "packages/html-reporter/playwright.config.ts", "packages/html-reporter/playwright/*", diff --git a/packages/playwright-core/src/tools/cli-client/program.ts b/packages/playwright-core/src/tools/cli-client/program.ts index 095d375f24097..6cf1a6b37e043 100644 --- a/packages/playwright-core/src/tools/cli-client/program.ts +++ b/packages/playwright-core/src/tools/cli-client/program.ts @@ -101,7 +101,7 @@ export async function program(options?: { embedderVersion?: string}) { } else { const lines = ['playwright-cli - run playwright mcp commands from terminal']; if (process.env.CLAUDECODE || process.env.COPILOT_CLI) - lines.push(`Agent skill: ${path.relative(process.cwd(), libPath('tools', 'cli-client', 'skill', 'SKILL.md'))}`); + lines.push(`Agent skill: ${path.relative(process.cwd(), libPath('tools', 'skills', 'playwright-cli', 'SKILL.md'))}`); lines.push(help.global); output.help(lines.join('\n\n')); } diff --git a/packages/playwright-core/src/tools/cli-daemon/DEPS.list b/packages/playwright-core/src/tools/cli-daemon/DEPS.list index 2c911112cd918..af8874ca8887f 100644 --- a/packages/playwright-core/src/tools/cli-daemon/DEPS.list +++ b/packages/playwright-core/src/tools/cli-daemon/DEPS.list @@ -1,6 +1,7 @@ [*] ../../package.ts ../utils/socketConnection.ts +../utils/installSkills.ts ../cli-client/registry.ts ../backend/ ../mcp/ diff --git a/packages/playwright-core/src/tools/cli-daemon/program.ts b/packages/playwright-core/src/tools/cli-daemon/program.ts index b9e8930306277..b57ce32118a45 100644 --- a/packages/playwright-core/src/tools/cli-daemon/program.ts +++ b/packages/playwright-core/src/tools/cli-daemon/program.ts @@ -22,12 +22,12 @@ import path from 'path'; import { getAsBooleanFromENV, guessClientName } from '@utils/env'; import { gracefullyProcessExitDoNotHang } from '@utils/processLauncher'; -import { libPath } from '../../package'; import { startCliDaemonServer } from './daemon'; import { setupExitWatchdog } from '../mcp/watchdog'; import { createBrowserWithInfo } from '../mcp/browserFactory'; import * as configUtils from '../mcp/config'; import { createClientInfo } from '../cli-client/registry'; +import { installSkills } from '../utils/installSkills'; import { registry as browserRegistry } from '../../server/registry/index'; import type { Command } from 'commander'; @@ -92,16 +92,14 @@ export async function initWorkspace(initSkills: string | undefined) { console.log(`✅ Workspace initialized at \`${cwd}\`.`); if (initSkills) { - const skillSourceDir = libPath('tools', 'cli-client', 'skill'); const target = initSkills === 'agents' ? 'agents' : 'claude'; - const skillDestDir = path.join(cwd, `.${target}`, 'skills', 'playwright-cli'); - if (!fs.existsSync(skillSourceDir)) { - console.error('❌ Skills source directory not found:', skillSourceDir); + try { + await installSkills(['playwright-cli'], target); + } catch (error) { + console.error('❌', error instanceof Error ? error.message : error); // eslint-disable-next-line no-restricted-properties process.exit(1); } - await fs.promises.cp(skillSourceDir, skillDestDir, { recursive: true }); - console.log(`✅ Skills installed to \`${path.relative(cwd, skillDestDir)}\`.`); } await ensureConfiguredBrowserInstalled(); diff --git a/packages/playwright-core/src/tools/index.ts b/packages/playwright-core/src/tools/index.ts index ec3e606812f67..f0cf3859f9933 100644 --- a/packages/playwright-core/src/tools/index.ts +++ b/packages/playwright-core/src/tools/index.ts @@ -32,6 +32,7 @@ export { decorateMCPCommand } from './mcp/program'; export { program as cliProgram } from './cli-client/program'; export { generateHelp, generateHelpJSON } from './cli-daemon/helpGenerator'; export { decorateProgram as decorateCliDaemonProgram, initWorkspace } from './cli-daemon/program'; +export { allSkills, installSkills } from './utils/installSkills'; export { openDashboardApp, openDashboardForContext } from './dashboard/dashboardApp'; export type { ContextConfig } from './backend/context'; diff --git a/packages/playwright-core/src/tools/cli-client/skill/SKILL.md b/packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/SKILL.md rename to packages/playwright-core/src/tools/skills/playwright-cli/SKILL.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/element-attributes.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/element-attributes.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/element-attributes.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/element-attributes.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/playwright-tests.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/playwright-tests.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/playwright-tests.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/request-mocking.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/request-mocking.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/request-mocking.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/request-mocking.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/running-code.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/running-code.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/running-code.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/running-code.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/session-management.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/session-management.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/session-management.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/session-management.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/storage-state.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/storage-state.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/storage-state.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/storage-state.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/test-generation.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/test-generation.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/test-generation.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/test-generation.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/tracing.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/tracing.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/tracing.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/tracing.md diff --git a/packages/playwright-core/src/tools/cli-client/skill/references/video-recording.md b/packages/playwright-core/src/tools/skills/playwright-cli/references/video-recording.md similarity index 100% rename from packages/playwright-core/src/tools/cli-client/skill/references/video-recording.md rename to packages/playwright-core/src/tools/skills/playwright-cli/references/video-recording.md diff --git a/packages/skills/component-testing/SKILL.md b/packages/playwright-core/src/tools/skills/playwright-component-testing/SKILL.md similarity index 100% rename from packages/skills/component-testing/SKILL.md rename to packages/playwright-core/src/tools/skills/playwright-component-testing/SKILL.md diff --git a/packages/skills/component-testing/references/gallery-spec.md b/packages/playwright-core/src/tools/skills/playwright-component-testing/references/gallery-spec.md similarity index 100% rename from packages/skills/component-testing/references/gallery-spec.md rename to packages/playwright-core/src/tools/skills/playwright-component-testing/references/gallery-spec.md diff --git a/packages/skills/component-testing/references/migration.md b/packages/playwright-core/src/tools/skills/playwright-component-testing/references/migration.md similarity index 100% rename from packages/skills/component-testing/references/migration.md rename to packages/playwright-core/src/tools/skills/playwright-component-testing/references/migration.md diff --git a/packages/skills/component-testing/references/react.md b/packages/playwright-core/src/tools/skills/playwright-component-testing/references/react.md similarity index 100% rename from packages/skills/component-testing/references/react.md rename to packages/playwright-core/src/tools/skills/playwright-component-testing/references/react.md diff --git a/packages/skills/component-testing/references/vue.md b/packages/playwright-core/src/tools/skills/playwright-component-testing/references/vue.md similarity index 100% rename from packages/skills/component-testing/references/vue.md rename to packages/playwright-core/src/tools/skills/playwright-component-testing/references/vue.md diff --git a/packages/skills/component-testing/templates/react/Button.story.tsx b/packages/playwright-core/src/tools/skills/playwright-component-testing/templates/react/Button.story.tsx similarity index 100% rename from packages/skills/component-testing/templates/react/Button.story.tsx rename to packages/playwright-core/src/tools/skills/playwright-component-testing/templates/react/Button.story.tsx diff --git a/packages/skills/component-testing/templates/react/button.spec.ts b/packages/playwright-core/src/tools/skills/playwright-component-testing/templates/react/button.spec.ts similarity index 100% rename from packages/skills/component-testing/templates/react/button.spec.ts rename to packages/playwright-core/src/tools/skills/playwright-component-testing/templates/react/button.spec.ts diff --git a/packages/skills/component-testing/templates/vue/Button.story.ts b/packages/playwright-core/src/tools/skills/playwright-component-testing/templates/vue/Button.story.ts similarity index 100% rename from packages/skills/component-testing/templates/vue/Button.story.ts rename to packages/playwright-core/src/tools/skills/playwright-component-testing/templates/vue/Button.story.ts diff --git a/packages/skills/component-testing/templates/vue/button.spec.ts b/packages/playwright-core/src/tools/skills/playwright-component-testing/templates/vue/button.spec.ts similarity index 100% rename from packages/skills/component-testing/templates/vue/button.spec.ts rename to packages/playwright-core/src/tools/skills/playwright-component-testing/templates/vue/button.spec.ts diff --git a/packages/playwright-core/src/tools/trace/SKILL.md b/packages/playwright-core/src/tools/skills/playwright-trace/SKILL.md similarity index 100% rename from packages/playwright-core/src/tools/trace/SKILL.md rename to packages/playwright-core/src/tools/skills/playwright-trace/SKILL.md diff --git a/packages/playwright-core/src/tools/trace/DEPS.list b/packages/playwright-core/src/tools/trace/DEPS.list index cf63107215805..57de59e88cb93 100644 --- a/packages/playwright-core/src/tools/trace/DEPS.list +++ b/packages/playwright-core/src/tools/trace/DEPS.list @@ -1,5 +1,6 @@ [*] ../../package.ts +../utils/installSkills.ts @isomorphic/** @utils/** diff --git a/packages/playwright-core/src/tools/trace/installSkill.ts b/packages/playwright-core/src/tools/trace/installSkill.ts deleted file mode 100644 index eb3f348f3c0cb..0000000000000 --- a/packages/playwright-core/src/tools/trace/installSkill.ts +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* eslint-disable no-console */ - -import fs from 'fs'; -import path from 'path'; - -import { libPath } from '../../package'; - -export async function installSkill() { - const cwd = process.cwd(); - const skillSource = libPath('tools', 'trace', 'SKILL.md'); - const destDir = path.join(cwd, '.claude', 'skills', 'playwright-trace'); - await fs.promises.mkdir(destDir, { recursive: true }); - const destFile = path.join(destDir, 'SKILL.md'); - await fs.promises.copyFile(skillSource, destFile); - console.log(`✅ Skill installed to \`${path.relative(cwd, destFile)}\`.`); -} diff --git a/packages/playwright-core/src/tools/trace/traceCli.ts b/packages/playwright-core/src/tools/trace/traceCli.ts index 3fedeb8e93c99..629f65595e401 100644 --- a/packages/playwright-core/src/tools/trace/traceCli.ts +++ b/packages/playwright-core/src/tools/trace/traceCli.ts @@ -26,7 +26,7 @@ import { traceSnapshot } from './traceSnapshot'; import { traceScreenshot } from './traceScreenshot'; import { traceAttachments } from './traceAttachments'; import { traceAttachment } from './traceAttachments'; -import { installSkill } from './installSkill'; +import { installSkills } from '../utils/installSkills'; import type { Command } from 'commander'; @@ -145,6 +145,6 @@ export function addTraceCommands(program: Command, logErrorAndExit: (e: Error) = .command('install-skill') .description('install SKILL.md for LLM integration') .action(async () => { - installSkill().catch(logErrorAndExit); + installSkills(['playwright-trace']).catch(logErrorAndExit); }); } diff --git a/packages/playwright-core/src/tools/utils/DEPS.list b/packages/playwright-core/src/tools/utils/DEPS.list index 91547c0e3b34b..e4ac7081b6fdf 100644 --- a/packages/playwright-core/src/tools/utils/DEPS.list +++ b/packages/playwright-core/src/tools/utils/DEPS.list @@ -6,3 +6,7 @@ [extension.ts] "strict" + +[installSkills.ts] +"strict" +../../package.ts diff --git a/packages/playwright-core/src/tools/utils/installSkills.ts b/packages/playwright-core/src/tools/utils/installSkills.ts new file mode 100644 index 0000000000000..43d4978a690f3 --- /dev/null +++ b/packages/playwright-core/src/tools/utils/installSkills.ts @@ -0,0 +1,39 @@ +/** + * Copyright (c) Microsoft Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* eslint-disable no-console */ + +import fs from 'fs'; +import path from 'path'; + +import { libPath } from '../../package'; + +export const allSkills = ['playwright-cli', 'playwright-component-testing', 'playwright-trace'] as const; + +export type SkillName = typeof allSkills[number]; +export type SkillTarget = 'claude' | 'agents'; + +export async function installSkills(skills: readonly SkillName[], target: SkillTarget = 'claude') { + const cwd = process.cwd(); + for (const skill of skills) { + const sourceDir = libPath('tools', 'skills', skill); + if (!fs.existsSync(sourceDir)) + throw new Error(`Skill source directory not found: ${sourceDir}`); + const destDir = path.join(cwd, `.${target}`, 'skills', skill); + await fs.promises.cp(sourceDir, destDir, { recursive: true }); + console.log(`✅ Skill installed to \`${path.relative(cwd, destDir)}\`.`); + } +} diff --git a/packages/playwright/src/program.ts b/packages/playwright/src/program.ts index 8449c12090916..eea299a9db04f 100644 --- a/packages/playwright/src/program.ts +++ b/packages/playwright/src/program.ts @@ -185,6 +185,23 @@ function addInitAgentsCommand(program: Command) { }); } +function addInitSkillsCommand(program: Command) { + const command = program.command('init-skills'); + command.description('Install Playwright agent skills'); + const option = command.createOption('--loop ', 'Agentic loop provider'); + option.choices(['claude', 'agents']); + option.default('claude'); + command.addOption(option); + command.action(async opts => { + try { + await tools.installSkills(tools.allSkills, opts.loop); + } catch (e) { + console.error(e); + gracefullyProcessExitDoNotHang(1); + } + }); +} + const kTraceModes: TraceMode[] = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure', 'retain-on-first-failure', 'retain-on-failure-and-retries']; // Note: update docs/src/test-cli-js.md when you update this, program is the source of truth. @@ -237,3 +254,4 @@ addClearCacheCommand(program); addTestMCPServerCommand(program); addTestServerCommand(program); addInitAgentsCommand(program); +addInitSkillsCommand(program); diff --git a/tests/mcp/cli-misc.spec.ts b/tests/mcp/cli-misc.spec.ts index 41907ad9331c1..67ba1e004040f 100644 --- a/tests/mcp/cli-misc.spec.ts +++ b/tests/mcp/cli-misc.spec.ts @@ -42,7 +42,7 @@ test('install workspace', async ({ cli }, testInfo) => { test('install workspace w/skills', async ({ cli }, testInfo) => { const { output } = await cli('install', '--skills'); - expect(output).toContain(`Skills installed to \`.claude${path.sep}skills${path.sep}playwright-cli\`.`); + expect(output).toContain(`Skill installed to \`.claude${path.sep}skills${path.sep}playwright-cli\`.`); const skillFile = testInfo.outputPath('.claude', 'skills', 'playwright-cli', 'SKILL.md'); expect(fs.existsSync(skillFile)).toBe(true); @@ -54,7 +54,7 @@ test('install workspace w/skills', async ({ cli }, testInfo) => { test('install workspace w/--skills=agents', async ({ cli }, testInfo) => { const { output } = await cli('install', '--skills=agents'); - expect(output).toContain(`Skills installed to \`.agents${path.sep}skills${path.sep}playwright-cli\`.`); + expect(output).toContain(`Skill installed to \`.agents${path.sep}skills${path.sep}playwright-cli\`.`); const skillFile = testInfo.outputPath('.agents', 'skills', 'playwright-cli', 'SKILL.md'); expect(fs.existsSync(skillFile)).toBe(true); diff --git a/tests/mcp/init-agents.spec.ts b/tests/mcp/init-agents.spec.ts index dca2fe39451b0..08c62fc4d69b2 100644 --- a/tests/mcp/init-agents.spec.ts +++ b/tests/mcp/init-agents.spec.ts @@ -121,3 +121,22 @@ test('codex generates agent toml files', async ({ }) => { expect(healerToml).toContain(`sandbox_mode = "workspace-write"`); expect(healerToml).toMatch(/enabled_tools = \[[^\]]*"test_debug"[^\]]*\]/); }); + +test('init-skills installs all skills', async ({ }) => { + const baseDir = await writeFiles({}); + + await spawnAsync('npx', ['playwright', 'init-skills'], { cwd: baseDir, shell: true }); + + for (const skill of ['playwright-cli', 'playwright-component-testing', 'playwright-trace']) + expect(fs.existsSync(path.join(baseDir, '.claude', 'skills', skill, 'SKILL.md'))).toBe(true); + expect(fs.existsSync(path.join(baseDir, '.claude', 'skills', 'playwright-cli', 'references', 'tracing.md'))).toBe(true); +}); + +test('init-skills installs into .agents with --loop agents', async ({ }) => { + const baseDir = await writeFiles({}); + + await spawnAsync('npx', ['playwright', 'init-skills', '--loop', 'agents'], { cwd: baseDir, shell: true }); + + for (const skill of ['playwright-cli', 'playwright-component-testing', 'playwright-trace']) + expect(fs.existsSync(path.join(baseDir, '.agents', 'skills', skill, 'SKILL.md'))).toBe(true); +}); diff --git a/tsconfig.json b/tsconfig.json index e8bc4e9f9d4f9..8401d4f79c081 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -43,6 +43,6 @@ "exclude": [ "packages/*/lib", "packages/extension", - "packages/skills", + "packages/playwright-core/src/tools/skills", ] } diff --git a/utils/build/build.js b/utils/build/build.js index 38825020fb0b6..70cbdd1af8a70 100644 --- a/utils/build/build.js +++ b/utils/build/build.js @@ -1055,20 +1055,9 @@ copyFiles.push({ to: 'packages/playwright/lib', }); +// Agent skills ship as-is: SKILL.md, referenced docs and templates. copyFiles.push({ - files: 'packages/skills/**/*', - from: 'packages/skills', - to: 'packages/playwright/lib/skills', -}); - -copyFiles.push({ - files: 'packages/playwright-core/src/tools/cli-client/skill/**/*.md', - from: 'packages/playwright-core/src', - to: 'packages/playwright-core/lib', -}); - -copyFiles.push({ - files: 'packages/playwright-core/src/tools/trace/SKILL.md', + files: 'packages/playwright-core/src/tools/skills/**/*', from: 'packages/playwright-core/src', to: 'packages/playwright-core/lib', }); diff --git a/utils/check_deps.js b/utils/check_deps.js index edc5b4b737007..f6dbf96c125ae 100644 --- a/utils/check_deps.js +++ b/utils/check_deps.js @@ -83,7 +83,8 @@ async function innerCheckDeps(root) { }); const sourceFiles = program.getSourceFiles(); const errors = []; - sourceFiles.filter(x => !x.fileName.includes(path.sep + 'node_modules' + path.sep) && !x.fileName.includes(path.sep + 'bundles' + path.sep)).map(x => visit(x, x.fileName, x.getFullText())); + // Agent skills are shipped as-is (SKILL.md plus user-facing templates), they are not part of the program. + sourceFiles.filter(x => !x.fileName.includes(path.sep + 'node_modules' + path.sep) && !x.fileName.includes(path.sep + 'bundles' + path.sep) && !x.fileName.includes('/tools/skills/')).map(x => visit(x, x.fileName, x.getFullText())); if (errors.length) { for (const error of errors)