diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index b4cbb8b6..5ed64e51 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -47,7 +47,7 @@ Do not deviate from this structure when editing or adding chapter content. ## Markdown Formatting - Use standard GitHub-Flavored Markdown. -- Images go in the repo-root `images/` directory. +- Images go in the repo-root `assets/` directory. - Use relative links for cross-chapter references (e.g., `../03-development-workflows/README.md`). - Emoji usage is encouraged for section headers (matching existing style). @@ -55,7 +55,7 @@ Do not deviate from this structure when editing or adding chapter content. | Change Made | Files to Update | |---|---| -| New chapter added | `README.md` (course table), `AGENTS.md` (structure table), `images/learning-path.png` | +| New chapter added | `README.md` (course table), `AGENTS.md` (structure table), `assets/learning-path.png` | | Chapter content updated | The chapter's `README.md`, verify cross-references in adjacent chapters | | New sample app variant added | `AGENTS.md` (structure table), `samples/` directory, relevant chapter references | | Sample app code changed | `samples/book-app-project/tests/` (update/add tests), chapters referencing that code | @@ -66,5 +66,5 @@ Do not deviate from this structure when editing or adding chapter content. | Glossary term introduced | `GLOSSARY.md` — add definition in alphabetical order | | npm scripts changed | `package.json`, `AGENTS.md` (build section) | | Devcontainer updated | `.devcontainer/devcontainer.json`, Chapter 00 (setup instructions) | -| Image or banner changed | `images/` directory, any README referencing the image | +| Image or banner changed | `assets/` directory, any README referencing the image | | Copilot CLI version requirements change | Chapter 00, Chapter 01, `.devcontainer/devcontainer.json` | diff --git a/.github/instructions/python-standards.instructions.md b/.github/instructions/python-standards.instructions.md new file mode 100644 index 00000000..b249c570 --- /dev/null +++ b/.github/instructions/python-standards.instructions.md @@ -0,0 +1,25 @@ +--- +applyTo: "**/*.py" +--- + +# Python Standards + +These rules apply automatically whenever Copilot works on a Python file in +this project. They never load for other file types, so a conversation about a +Dockerfile or some JSON stays clutter-free. + +## Style + +- Follow PEP 8 style conventions. +- Add type hints to every function signature. +- Prefer f-strings over `%` formatting or `str.format()`. + +## Error Handling + +- Catch specific exceptions; never use a bare `except:`. +- Validate inputs at function boundaries and fail with a clear message. + +## Testing + +- Put pytest tests in `samples/book-app-project/tests/` using `test_*.py` naming. +- Cover the happy path and edge cases (empty input, missing data). diff --git a/.github/scripts/copy-content-engine-files.js b/.github/scripts/copy-content-engine-files.js new file mode 100644 index 00000000..f55e358b --- /dev/null +++ b/.github/scripts/copy-content-engine-files.js @@ -0,0 +1,353 @@ +#!/usr/bin/env node +/** + * Copy the course content subset required by the CSE content engine. + * + * Usage: + * npm run copy:content-engine + * + * Optional: + * CONTENT_ENGINE_DESTINATION_ROOT=/path/to/cse-content-engine/content/learning-pathways/copilot-cli-for-beginners npm run copy:content-engine + */ + +const { + cpSync, + existsSync, + mkdirSync, + readdirSync, + readFileSync, + rmSync, + statSync, + writeFileSync, +} = require('fs'); +const { dirname, join, relative, resolve } = require('path'); + +const sourceRoot = process.cwd(); +const defaultDestinationRoot = resolve( + sourceRoot, + '../cse-content-engine/content/learning-pathways/copilot-cli-for-beginners', +); +const destinationRoot = resolve(process.env.CONTENT_ENGINE_DESTINATION_ROOT || defaultDestinationRoot); +const destinationParent = dirname(destinationRoot); +const contentEngineSchema = { + $schema: 'http://json-schema.org/draft-07/schema#', + type: 'object', + properties: { + aliases: { + type: 'array', + description: 'Relative paths to redirect to this item', + items: { + type: 'string', + description: 'A relative path to redirect to this item', + }, + }, + audience: { + type: 'string', + description: 'The intended audience for the guide', + }, + description: { + type: 'string', + description: 'A brief description of the item', + }, + icon: { + type: 'string', + description: 'An icon to represent the item', + }, + id: { + type: 'string', + description: 'A unique identifier for the guide', + }, + params: { + type: 'object', + description: "Flexible parameters that don't affect presentation", + }, + slug: { + type: 'string', + description: 'A kebab-case identifier', + }, + title: { + type: 'string', + description: 'The display name of the item', + }, + weight: { + type: 'integer', + description: 'The order to display the item in', + }, + }, + required: ['title', 'description', 'weight'], + additionalProperties: true, +}; + +function log(message) { + console.log(` ${message}`); +} + +function fail(message) { + console.error(`\nError: ${message}`); + process.exit(1); +} + +function ensureSafeDestination() { + if (!existsSync(destinationParent)) { + fail(`Destination parent does not exist: ${destinationParent}`); + } + + const resolvedSource = resolve(sourceRoot); + const resolvedDestination = resolve(destinationRoot); + + if (resolvedSource === resolvedDestination) { + fail('Destination cannot be the source repository root.'); + } + + if (resolvedDestination.startsWith(`${resolvedSource}/`)) { + fail('Destination cannot be inside the source repository.'); + } +} + +function resetDestination() { + rmSync(destinationRoot, { recursive: true, force: true }); + log(`Cleared ${destinationRoot}`); +} + +function copyFile(sourcePath, destinationPath) { + mkdirSync(dirname(destinationPath), { recursive: true }); + + if (sourcePath.endsWith('.md')) { + writeFileSync(destinationPath, prepareMarkdownForContentEngine(sourcePath), 'utf8'); + } else { + cpSync(sourcePath, destinationPath); + } + + log(`Copied ${relative(sourceRoot, sourcePath)} -> ${relative(destinationRoot, destinationPath)}`); +} + +function prepareMarkdownForContentEngine(sourcePath) { + const markdown = readFileSync(sourcePath, 'utf8'); + const frontmatter = getMarkdownFrontmatter(markdown); + + if (!frontmatter) { + return markdown; + } + + return markdown.replace(/^\r?\n*/, `---\n${frontmatter}\n---\n\n`); +} + +function getMarkdownFrontmatter(markdown) { + const hiddenFrontmatter = markdown.match(/^/)?.[1]; + const visibleFrontmatter = markdown.match(/^---\r?\n([\s\S]*?)\r?\n---/)?.[1]; + + return (hiddenFrontmatter ?? visibleFrontmatter)?.replace(/\r\n/g, '\n'); +} + +function getFrontmatterField(frontmatter, field) { + return frontmatter.match(new RegExp(`^${field}:.*$`, 'm'))?.[0]; +} + +function writeIndexFromReadme(sourceReadmePath, destinationDirectory, extraFields = []) { + const markdown = readFileSync(sourceReadmePath, 'utf8'); + const frontmatter = getMarkdownFrontmatter(markdown); + + if (!frontmatter) { + fail(`Cannot create index.yml because ${relative(sourceRoot, sourceReadmePath)} has no frontmatter.`); + } + + const indexFields = ['title', 'description', 'slug', 'weight', 'icon'] + .map((field) => getFrontmatterField(frontmatter, field)) + .filter(Boolean); + indexFields.push(...extraFields); + + if (indexFields.length === 0) { + fail(`Cannot create index.yml because ${relative(sourceRoot, sourceReadmePath)} has no index metadata.`); + } + + mkdirSync(destinationDirectory, { recursive: true }); + writeFileSync(join(destinationDirectory, 'index.yml'), `${indexFields.join('\n')}\n`, 'utf8'); + log(`Generated ${relative(destinationRoot, join(destinationDirectory, 'index.yml'))}`); +} + +function writeContentEngineSchema() { + const destinationPath = join(destinationRoot, 'schema.json'); + writeFileSync(destinationPath, `${JSON.stringify(contentEngineSchema, null, 2)}\n`, 'utf8'); + log(`Generated ${relative(destinationRoot, destinationPath)}`); +} + +function copyDirectory(sourcePath, destinationPath) { + if (!existsSync(sourcePath)) { + fail(`Required directory does not exist: ${relative(sourceRoot, sourcePath)}`); + } + + cpSync(sourcePath, destinationPath, { recursive: true }); + log(`Copied ${relative(sourceRoot, sourcePath)}/ -> ${relative(destinationRoot, destinationPath)}/`); +} + +function getChapterFolders() { + return readdirSync(sourceRoot) + .filter((entry) => /^0[0-7]-/.test(entry)) + .filter((entry) => statSync(join(sourceRoot, entry)).isDirectory()) + .sort(); +} + +function stripFragmentAndQuery(target) { + return target.split('#')[0].split('?')[0]; +} + +function isExternalLink(target) { + return /^[a-z][a-z0-9+.-]*:/i.test(target) || target.startsWith('//') || target.startsWith('#'); +} + +function getChapterLocalMarkdownLinks(chapterPath) { + const readmePath = join(chapterPath, 'README.md'); + const readme = readFileSync(readmePath, 'utf8'); + const links = new Set(); + const patterns = [ + /\[[^\]]+\]\(([^)\s]+\.md(?:#[^)]+)?)(?:\s+"[^"]*")?\)/gi, + /]*\bhref=["']([^"']+\.md(?:#[^"']+)?)["']/gi, + ]; + + for (const pattern of patterns) { + for (const match of readme.matchAll(pattern)) { + const target = stripFragmentAndQuery(match[1]); + if (!target || isExternalLink(target)) { + continue; + } + + const resolvedTarget = resolve(chapterPath, target); + if (dirname(resolvedTarget) === resolve(chapterPath) && resolvedTarget !== resolve(readmePath)) { + links.add(resolvedTarget); + } + } + } + + return [...links].sort(); +} + +function copyAppendices() { + const sourceAppendices = join(sourceRoot, 'appendices'); + const destinationAppendices = join(destinationRoot, 'appendices'); + + if (!existsSync(sourceAppendices)) { + fail('Required appendices directory does not exist.'); + } + + writeIndexFromReadme(join(sourceAppendices, 'README.md'), destinationAppendices); + + for (const markdownFile of findMarkdownFiles(sourceAppendices)) { + copyFile(markdownFile, join(destinationAppendices, relative(sourceAppendices, markdownFile))); + } +} + +function copyCourseContent() { + console.log(`Overlaying course content into:\n${destinationRoot}\n`); + + mkdirSync(destinationRoot, { recursive: true }); + + copyFile(join(sourceRoot, 'README.md'), join(destinationRoot, 'README.md')); + writeContentEngineSchema(); + writeIndexFromReadme(join(sourceRoot, 'README.md'), destinationRoot, ['icon: CopilotIcon']); + copyDirectory(join(sourceRoot, 'assets'), join(destinationRoot, 'assets')); + + for (const chapterFolder of getChapterFolders()) { + const sourceChapter = join(sourceRoot, chapterFolder); + const destinationChapter = join(destinationRoot, chapterFolder); + + mkdirSync(destinationChapter, { recursive: true }); + copyFile(join(sourceChapter, 'README.md'), join(destinationChapter, 'README.md')); + writeIndexFromReadme(join(sourceChapter, 'README.md'), destinationChapter); + copyDirectory(join(sourceChapter, 'assets'), join(destinationChapter, 'assets')); + + for (const linkedMarkdown of getChapterLocalMarkdownLinks(sourceChapter)) { + copyFile(linkedMarkdown, join(destinationChapter, relative(sourceChapter, linkedMarkdown))); + } + } + + copyAppendices(); +} + +function findMarkdownFiles(directory) { + const files = []; + + for (const entry of readdirSync(directory)) { + const path = join(directory, entry); + const stat = statSync(path); + + if (stat.isDirectory()) { + files.push(...findMarkdownFiles(path)); + } else if (entry.endsWith('.md')) { + files.push(path); + } + } + + return files; +} + +function validateMarkdownImagePaths() { + const imagePatterns = [ + /!\[[^\]]*]\(([^)\s]+)(?:\s+"[^"]*")?\)/g, + /]*\bsrc=["']([^"']+)["']/gi, + ]; + const brokenLinks = []; + + for (const markdownFile of findMarkdownFiles(destinationRoot)) { + const markdown = readFileSync(markdownFile, 'utf8'); + + for (const pattern of imagePatterns) { + for (const match of markdown.matchAll(pattern)) { + const target = stripFragmentAndQuery(match[1]); + if (!target || isExternalLink(target)) { + continue; + } + + const resolvedTarget = target.startsWith('/') + ? join(destinationRoot, target.slice(1)) + : resolve(dirname(markdownFile), target); + + if (!existsSync(resolvedTarget)) { + const line = markdown.slice(0, match.index).split('\n').length; + brokenLinks.push(`${relative(destinationRoot, markdownFile)}:${line} -> ${target}`); + } + } + } + } + + if (brokenLinks.length > 0) { + fail(`Broken copied Markdown image references:\n${brokenLinks.join('\n')}`); + } + + console.log('\nValidation passed: all copied Markdown image references resolve.'); +} + +function validateMarkdownFrontmatter() { + const requiredFields = contentEngineSchema.required ?? []; + const missingFrontmatter = []; + + for (const markdownFile of findMarkdownFiles(destinationRoot)) { + const markdown = readFileSync(markdownFile, 'utf8'); + const frontmatter = markdown.match(/^---\n([\s\S]*?)\n---\n/)?.[1]; + const relativePath = relative(destinationRoot, markdownFile); + + if (!frontmatter) { + missingFrontmatter.push(`${relativePath}: missing frontmatter`); + continue; + } + + const missingFields = requiredFields.filter( + (field) => !new RegExp(`^${field}:`, 'm').test(frontmatter), + ); + + if (missingFields.length > 0) { + missingFrontmatter.push(`${relativePath}: missing ${missingFields.join(', ')}`); + } + } + + if (missingFrontmatter.length > 0) { + fail(`Copied Markdown frontmatter does not match schema requirements:\n${missingFrontmatter.join('\n')}`); + } + + console.log('Validation passed: copied Markdown frontmatter includes required schema fields.'); +} + +ensureSafeDestination(); +resetDestination(); +copyCourseContent(); +validateMarkdownFrontmatter(); +validateMarkdownImagePaths(); +console.log('\nDone.'); diff --git a/.github/scripts/create-tapes.js b/.github/scripts/create-tapes.js index 66583962..95e0f69e 100644 --- a/.github/scripts/create-tapes.js +++ b/.github/scripts/create-tapes.js @@ -136,13 +136,13 @@ console.log('📝 Creating tape files from demos.json...\n'); let created = 0; for (const demo of config.demos) { - const imagesDir = join(rootDir, demo.chapter, 'images'); - const tapePath = join(imagesDir, `${demo.name}.tape`); + const assetsDir = join(rootDir, demo.chapter, 'assets'); + const tapePath = join(assetsDir, `${demo.name}.tape`); - // Ensure images directory exists - if (!existsSync(imagesDir)) { - mkdirSync(imagesDir, { recursive: true }); - console.log(` Created: ${demo.chapter}/images/`); + // Ensure assets directory exists + if (!existsSync(assetsDir)) { + mkdirSync(assetsDir, { recursive: true }); + console.log(` Created: ${demo.chapter}/assets/`); } // Generate tape content @@ -150,7 +150,7 @@ for (const demo of config.demos) { // Write tape file writeFileSync(tapePath, content); - console.log(` ✓ ${demo.chapter}/images/${demo.name}.tape`); + console.log(` ✓ ${demo.chapter}/assets/${demo.name}.tape`); created++; } diff --git a/.github/scripts/filter-co-op-review.js b/.github/scripts/filter-co-op-review.js new file mode 100644 index 00000000..2b36960b --- /dev/null +++ b/.github/scripts/filter-co-op-review.js @@ -0,0 +1,105 @@ +#!/usr/bin/env node + +// Runs `co-op-review` and post-filters its findings so the workflow only fails +// on genuine errors. +// +// Why this exists: the `translate` command and the `co-op-review` command ship +// with *different* exclusion lists. `translate` skips `.github/**` (it is in +// Co-op Translator's EXCLUDED_DIRS), so those files are never translated. But +// `co-op-review` does NOT exclude `.github/**`, so it reports every one of those +// untranslated source files as a "Missing translated file" error and fails the +// build. Those errors are false positives for paths this repo intentionally +// leaves untranslated. The review CLI exposes no way to extend its exclusions, +// so we drop findings under the excluded paths here and fail only on the rest. + +const { spawnSync } = require("child_process"); + +// Source paths that are intentionally excluded from translation. Keep this in +// sync with the excludes in .github/workflows/co-op-translator.yml and the +// guidance in .github/workflows/translation-polisher.md. +const EXCLUDED_PREFIXES = [".github/", "samples/"]; + +const languages = process.argv + .slice(2) + .flatMap((value) => value.split(/\s+/)) + .map((value) => value.trim()) + .filter(Boolean); + +if (languages.length === 0) { + console.error("Usage: node .github/scripts/filter-co-op-review.js "); + process.exit(1); +} + +const result = spawnSync( + "co-op-review", + ["-l", languages.join(" "), "--format", "github"], + { encoding: "utf8" } +); + +if (result.error && result.error.code === "ENOENT") { + console.log("co-op-review is not available in the installed Co-op Translator package; skipping."); + process.exit(0); +} + +const report = result.stdout || ""; +const stderr = result.stderr || ""; + +// Always surface the full report in the job log (and summary when available). +if (report.trim()) { + console.log(report.trimEnd()); +} +if (process.env.GITHUB_STEP_SUMMARY && report.trim()) { + try { + require("fs").appendFileSync(process.env.GITHUB_STEP_SUMMARY, `${report.trimEnd()}\n`); + } catch (err) { + console.error(`Could not write review report to step summary: ${err.message}`); + } +} + +const isExcluded = (filePath) => + EXCLUDED_PREFIXES.some((prefix) => filePath.startsWith(prefix)); + +const genuineErrors = []; +const ignoredErrors = []; + +for (const line of report.split("\n")) { + if (!line.trimStart().startsWith("|")) { + continue; + } + const cells = line.split("|").map((cell) => cell.trim()); + // cells[0] is the empty string before the leading pipe. + const severity = (cells[1] || "").toLowerCase(); + if (severity !== "error" && severity !== "warning") { + continue; // Skip the metrics table, header, and separator rows. + } + if (severity !== "error") { + continue; // Only errors fail the build; warnings are informational. + } + const filePath = (cells[4] || "").replace(/`/g, "").trim(); + if (isExcluded(filePath)) { + ignoredErrors.push(filePath); + } else { + genuineErrors.push({ filePath, message: cells[5] || "" }); + } +} + +if (ignoredErrors.length > 0) { + console.log( + `\nIgnored ${ignoredErrors.length} expected finding(s) for intentionally untranslated paths ` + + `(${EXCLUDED_PREFIXES.join(", ")}).` + ); +} + +if (genuineErrors.length > 0) { + console.error(`\nco-op-review found ${genuineErrors.length} genuine error(s):`); + for (const { filePath, message } of genuineErrors) { + console.error(` - ${filePath}: ${message}`); + } + if (stderr.trim()) { + console.error(stderr.trimEnd()); + } + process.exit(1); +} + +console.log("\nco-op-review passed (no genuine errors)."); +process.exit(0); diff --git a/.github/scripts/generate-chapter-headers.py b/.github/scripts/generate-chapter-headers.py index 5c44a927..0520f6be 100644 --- a/.github/scripts/generate-chapter-headers.py +++ b/.github/scripts/generate-chapter-headers.py @@ -23,7 +23,7 @@ # Get project root (parent of scripts folder) SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) PROJECT_ROOT = os.path.dirname(os.path.dirname(SCRIPT_DIR)) -BACKGROUND_IMAGE = os.path.join(PROJECT_ROOT, "images", "chapter-header-bg.png") +BACKGROUND_IMAGE = os.path.join(PROJECT_ROOT, "assets", "chapter-header-bg.png") # Font settings - 25% larger than original 36px FONT_SIZE = 45 @@ -112,8 +112,8 @@ def generate_header(chapter_folder, title, font): y = (height - text_height) // 2 draw.text((x, y), title, fill=(255, 255, 255), font=font) - # Save to chapter's images folder - output_dir = os.path.join(PROJECT_ROOT, chapter_folder, "images") + # Save to chapter's assets folder + output_dir = os.path.join(PROJECT_ROOT, chapter_folder, "assets") os.makedirs(output_dir, exist_ok=True) output_path = os.path.join(output_dir, "chapter-header.png") diff --git a/.github/scripts/generate-demos.js b/.github/scripts/generate-demos.js index 09076750..457ef558 100644 --- a/.github/scripts/generate-demos.js +++ b/.github/scripts/generate-demos.js @@ -2,7 +2,7 @@ /** * Generate course demo GIFs from .tape files * - * This script finds all .tape files in [chapter]/images/ folders and runs VHS + * This script finds all .tape files in [chapter]/assets/ folders and runs VHS * to generate GIFs. VHS is run from the project root so that @file references * in prompts resolve correctly. * @@ -135,7 +135,7 @@ function cleanupCopilotWrapper() { try { rmSync(wrapperDir, { recursive: true }); } catch (e) { /* ignore */ } } -// Find all .tape files in [chapter]/images/ folders +// Find all .tape files in [chapter]/assets/ folders function findTapeFiles(dir, chapterFilter) { const tapeFiles = []; @@ -151,17 +151,17 @@ function findTapeFiles(dir, chapterFilter) { if (!matches) continue; } - const imagesDir = join(fullPath, 'images'); - if (existsSync(imagesDir)) { + const assetsDir = join(fullPath, 'assets'); + if (existsSync(assetsDir)) { try { - const imagesEntries = readdirSync(imagesDir); - for (const file of imagesEntries) { + const assetsEntries = readdirSync(assetsDir); + for (const file of assetsEntries) { if (file.endsWith('.tape')) { - tapeFiles.push(join(imagesDir, file)); + tapeFiles.push(join(assetsDir, file)); } } } catch (e) { - // Can't read images folder, skip + // Can't read assets folder, skip } } } diff --git a/.github/scripts/preview-gifs.js b/.github/scripts/preview-gifs.js index f3fec522..0c095d1e 100644 --- a/.github/scripts/preview-gifs.js +++ b/.github/scripts/preview-gifs.js @@ -32,11 +32,11 @@ function findGifs() { const gifs = []; for (const entry of readdirSync(rootDir)) { if (!/^\d{2}-/.test(entry)) continue; - const imagesDir = join(rootDir, entry, 'images'); - if (!existsSync(imagesDir)) continue; - for (const file of readdirSync(imagesDir)) { + const assetsDir = join(rootDir, entry, 'assets'); + if (!existsSync(assetsDir)) continue; + for (const file of readdirSync(assetsDir)) { if (file.endsWith('-demo.gif')) { - gifs.push({ path: join(imagesDir, file), chapter: entry }); + gifs.push({ path: join(assetsDir, file), chapter: entry }); } } } diff --git a/.github/scripts/verify-gifs.js b/.github/scripts/verify-gifs.js index 93cd1c17..04c94aa0 100644 --- a/.github/scripts/verify-gifs.js +++ b/.github/scripts/verify-gifs.js @@ -41,11 +41,11 @@ function findGifs(dir) { const fullPath = join(dir, entry); const stat = statSync(fullPath); if (stat.isDirectory() && !entry.startsWith('.') && entry !== 'node_modules') { - const imagesDir = join(fullPath, 'images'); - if (existsSync(imagesDir)) { - for (const file of readdirSync(imagesDir)) { + const assetsDir = join(fullPath, 'assets'); + if (existsSync(assetsDir)) { + for (const file of readdirSync(assetsDir)) { if (file.endsWith('-demo.gif')) { - gifs.push(join(imagesDir, file)); + gifs.push(join(assetsDir, file)); } } } diff --git a/.github/uvs.csv b/.github/uvs.csv index eb888c3c..345702fd 100644 --- a/.github/uvs.csv +++ b/.github/uvs.csv @@ -88,3 +88,52 @@ "05/29",731 "05/30",329 "05/31",352 +"06/01",681 +"06/02",521 +"06/03",613 +"06/04",516 +"06/05",662 +"06/06",291 +"06/07",299 +"06/08",631 +"06/09",744 +"06/10",624 +"06/11",685 +"06/12",733 +"06/13",288 +"06/14",294 +"06/15",674 +"06/16",425 +"06/17",612 +"06/18",717 +"06/19",568 +"06/20",227 +"06/21",244 +"06/22",650 +"06/23",591 +"06/24",583 +"06/25",565 +"06/26",517 +"06/27",241 +"06/28",287 +"06/29",605 +"06/30",550 +"07/01",492 +"07/02",419 +"07/03",497 +"07/04",198 +"07/05",226 +"07/06",507 +"07/07",441 +"07/08",490 +"07/09",474 +"07/10",463 +"07/11",377 +"07/12",336 +"07/13",478 +"07/14",497 +"07/15",426 +"07/16",407 +"07/17",474 +"07/18",213 +"07/19",238 diff --git a/.github/views.csv b/.github/views.csv index 1e70c650..4f566887 100644 --- a/.github/views.csv +++ b/.github/views.csv @@ -87,3 +87,52 @@ "05/29",1534 "05/30",840 "05/31",892 +"06/01",1430 +"06/02",1007 +"06/03",1271 +"06/04",1065 +"06/05",1484 +"06/06",665 +"06/07",781 +"06/08",1249 +"06/09",1507 +"06/10",1229 +"06/11",1504 +"06/12",1691 +"06/13",693 +"06/14",684 +"06/15",1280 +"06/16",735 +"06/17",1235 +"06/18",1826 +"06/19",1319 +"06/20",589 +"06/21",552 +"06/22",1348 +"06/23",1152 +"06/24",1154 +"06/25",1230 +"06/26",1066 +"06/27",593 +"06/28",590 +"06/29",1184 +"06/30",1116 +"07/01",1035 +"07/02",1032 +"07/03",1199 +"07/04",495 +"07/05",794 +"07/06",2370 +"07/07",2880 +"07/08",4565 +"07/09",4512 +"07/10",904 +"07/11",850 +"07/12",788 +"07/13",981 +"07/14",980 +"07/15",924 +"07/16",822 +"07/17",1162 +"07/18",485 +"07/19",596 diff --git a/.github/workflows/co-op-translator.yml b/.github/workflows/co-op-translator.yml index edff8cc4..a06a9c38 100644 --- a/.github/workflows/co-op-translator.yml +++ b/.github/workflows/co-op-translator.yml @@ -14,7 +14,7 @@ on: - "!translations/**" - "!translated_images/**" - "!.github/**" - - "!samples/skills/**" + - "!samples/**" permissions: contents: write @@ -43,12 +43,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.12" @@ -87,32 +87,28 @@ jobs: run: | migrate-links -l "$TRANSLATION_LANGUAGES" -y node .github/scripts/fix-translated-markdown.js "$TRANSLATION_LANGUAGES" - if command -v co-op-review >/dev/null 2>&1; then - co-op-review -l "$TRANSLATION_LANGUAGES" --format github - else - echo "co-op-review is not available in the installed Co-op Translator package; skipping." - fi + node .github/scripts/filter-co-op-review.js "$TRANSLATION_LANGUAGES" - name: Remove excluded translations run: | for language in $TRANSLATION_LANGUAGES; do rm -rf \ "translations/$language/.github" \ - "translations/$language/samples/skills" \ + "translations/$language/samples" \ "translated_images/$language/.github" \ - "translated_images/$language/samples/skills" + "translated_images/$language/samples" done - name: Upload Co-op Translator logs if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: co-op-translator-logs path: logs/ if-no-files-found: ignore - name: Create pull request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: token: ${{ secrets.GH_AW_GITHUB_TOKEN }} commit-message: "Update translations via Co-op Translator" diff --git a/.github/workflows/sync-content-engine.yml b/.github/workflows/sync-content-engine.yml new file mode 100644 index 00000000..208f7d78 --- /dev/null +++ b/.github/workflows/sync-content-engine.yml @@ -0,0 +1,60 @@ +name: Sync content-engine copy + +on: + workflow_dispatch: + push: + branches: + - main + +permissions: + contents: read + +concurrency: + group: sync-content-engine-copy + cancel-in-progress: true + +jobs: + sync-content: + name: Copy content and open content-engine PR + runs-on: ubuntu-latest + timeout-minutes: 15 + + steps: + - name: Checkout course repository + uses: actions/checkout@v4 + with: + path: copilot-cli-for-beginners + + - name: Checkout content-engine repository + uses: actions/checkout@v4 + with: + repository: github/cse-content-engine + token: ${{ secrets.GH_AW_GITHUB_TOKEN }} + path: cse-content-engine + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Copy course content into content-engine + working-directory: copilot-cli-for-beginners + env: + CONTENT_ENGINE_DESTINATION_ROOT: ${{ github.workspace }}/cse-content-engine/content/learning-pathways/copilot-cli-for-beginners + run: npm run copy:content-engine + + - name: Create content-engine pull request + uses: peter-evans/create-pull-request@v7 + with: + path: cse-content-engine + token: ${{ secrets.GH_AW_GITHUB_TOKEN }} + commit-message: "Update Copilot CLI for Beginners content" + title: "Update Copilot CLI for Beginners content" + body: | + This automated PR syncs the latest `github/copilot-cli-for-beginners` + content into the content-engine learning pathway. + + Source commit: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} + branch: update/copilot-cli-for-beginners-content + base: main + delete-branch: true diff --git a/.github/workflows/translation-polisher.md b/.github/workflows/translation-polisher.md index 64a3063c..7eff0d74 100644 --- a/.github/workflows/translation-polisher.md +++ b/.github/workflows/translation-polisher.md @@ -93,7 +93,7 @@ You may edit only translated Markdown files: Exclude these generated translation paths from review, grading, and edits: - `translations/*/.github/**` -- `translations/*/samples/skills/**` +- `translations/*/samples/**` Leave skill definition Markdown in English. @@ -107,11 +107,15 @@ Do not edit: ## Required process -1. Identify the target pull request number and head branch. +> **Shell tooling constraint:** Only the `gh`, `git`, and `node` commands are available in this environment. Do **not** call `python`, `python3`, `sed`, `awk`, or `grep` pipelines — they are not permitted and will fail with a permission error. Filter and process command output yourself instead of piping through unsupported tools. + +1. Identify the target pull request number and head branch, then list the files the pull request changed. Use only the available shell tools: + - List changed files with `git diff --name-only origin/main...HEAD` (the branch is checked out with full history) or `gh pr diff --name-only`. + - From that output, select only files matching `translations/**/*.md`, and ignore `translations/*/.github/**` and `translations/*/samples/**`. Do this selection yourself from the file list rather than piping through `grep`/`sed`. 2. Compare each changed translated Markdown file with its corresponding English source file. - Example: compare `translations/es/README.md` with `README.md`. - Example: compare `translations/es/03-development-workflows/README.md` with `03-development-workflows/README.md`. -3. Focus on files changed by the pull request, not every translated file in the repository. Ignore excluded translation paths under `translations/*/.github/**` and `translations/*/samples/skills/**`. +3. Focus on files changed by the pull request, not every translated file in the repository. Ignore excluded translation paths under `translations/*/.github/**` and `translations/*/samples/**`. 4. If the pull request body already has a managed `## Translation Quality Review` section, identify files with grades below A- and repair those files first. 5. Preserve Markdown structure exactly unless a link or heading fix is required. 6. Apply the shared quality rules and the language quality profile for each target language present in the pull request. diff --git a/.gitignore b/.gitignore index d54b2511..9b6560e3 100644 --- a/.gitignore +++ b/.gitignore @@ -101,4 +101,5 @@ Desktop.ini .plans .plans.vhs-wrapper demo-previews -blog \ No newline at end of file +blog +migration.md \ No newline at end of file diff --git a/00-quick-start/README.md b/00-quick-start/README.md index dcc0f1c8..3891c9a9 100644 --- a/00-quick-start/README.md +++ b/00-quick-start/README.md @@ -1,4 +1,15 @@ -![Chapter 00: Quick Start](images/chapter-header.png) + + +![Chapter 00: Quick Start](assets/chapter-header.png) Welcome! In this chapter, you'll get GitHub Copilot CLI (Command Line Interface) installed, signed in with your GitHub account, and verified that everything works. This is a quick setup chapter. Once you're up and running, the real demos start in Chapter 01! @@ -124,7 +135,7 @@ copilot You'll be asked to trust the folder containing the repository (if you haven't already). You can trust it one time or across all future sessions. -Trusting files in a folder with the Copilot CLI +Trusting files in a folder with the Copilot CLI After trusting the folder, you can sign in with your GitHub account. @@ -140,7 +151,7 @@ After trusting the folder, you can sign in with your GitHub account. 4. Select "Authorize" to grant GitHub Copilot CLI access 5. Return to your terminal - you're now signed in! -Device Authorization Flow - showing the 5-step process from terminal login to signed-in confirmation +Device Authorization Flow - showing the 5-step process from terminal login to signed-in confirmation *The device authorization flow: your terminal generates a code, you verify it in the browser, and Copilot CLI is authenticated.* @@ -169,7 +180,7 @@ After you receive a response, you can exit the CLI:
🎬 See it in action! -![Hello Demo](images/hello-demo.gif) +![Hello Demo](assets/hello-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* diff --git a/00-quick-start/images/auth-device-flow.png b/00-quick-start/assets/auth-device-flow.png similarity index 100% rename from 00-quick-start/images/auth-device-flow.png rename to 00-quick-start/assets/auth-device-flow.png diff --git a/00-quick-start/images/chapter-header.png b/00-quick-start/assets/chapter-header.png similarity index 100% rename from 00-quick-start/images/chapter-header.png rename to 00-quick-start/assets/chapter-header.png diff --git a/00-quick-start/images/copilot-trust.png b/00-quick-start/assets/copilot-trust.png similarity index 100% rename from 00-quick-start/images/copilot-trust.png rename to 00-quick-start/assets/copilot-trust.png diff --git a/00-quick-start/images/hello-demo.gif b/00-quick-start/assets/hello-demo.gif similarity index 100% rename from 00-quick-start/images/hello-demo.gif rename to 00-quick-start/assets/hello-demo.gif diff --git a/00-quick-start/images/hello-demo.tape b/00-quick-start/assets/hello-demo.tape similarity index 100% rename from 00-quick-start/images/hello-demo.tape rename to 00-quick-start/assets/hello-demo.tape diff --git a/01-setup-and-first-steps/README.md b/01-setup-and-first-steps/README.md index 41553300..ba53741b 100644 --- a/01-setup-and-first-steps/README.md +++ b/01-setup-and-first-steps/README.md @@ -1,4 +1,15 @@ -![Chapter 01: First Steps](images/chapter-header.png) + + +![Chapter 01: First Steps](assets/chapter-header.png) > **Watch AI find bugs instantly, explain confusing code, and generate working scripts. Then learn three different ways to use GitHub Copilot CLI.** @@ -20,7 +31,7 @@ By the end of this chapter, you'll be able to: # Your First Copilot CLI Experience -Developer sitting at a desk with code on the monitor and glowing particles representing AI assistance +Developer sitting at a desk with code on the monitor and glowing particles representing AI assistance Jump right in and see what Copilot CLI can do. @@ -86,7 +97,7 @@ Once inside the interactive Copilot CLI session, run the following:
🎬 See it in action! -![Code Review Demo](images/code-review-demo.gif) +![Code Review Demo](assets/code-review-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -111,7 +122,7 @@ Ever stared at code wondering what it does? Try this in your Copilot CLI session
🎬 See it in action! -![Explain Code Demo](images/explain-code-demo.gif) +![Explain Code Demo](assets/explain-code-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -167,7 +178,7 @@ Need a function you'd otherwise spend 15 minutes googling? Still in your session
🎬 See it in action! -![Generate Code Demo](images/generate-code-demo.gif) +![Generate Code Demo](assets/generate-code-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -189,7 +200,7 @@ When you're done exploring, exit the session: # Modes and Commands -Futuristic control panel with glowing screens, dials, and equalizers representing Copilot CLI modes and commands +Futuristic control panel with glowing screens, dials, and equalizers representing Copilot CLI modes and commands You've just seen what Copilot CLI can do. Now let's understand *how* to use these capabilities effectively. The key is knowing which of the three interaction modes to use for different situations. @@ -209,7 +220,7 @@ Think of using GitHub Copilot CLI like going out to eat. From planning the trip Just like dining out, you'll naturally learn when each approach feels right. -Three Ways to Use GitHub Copilot CLI - Plan Mode (GPS route to restaurant), Interactive Mode (talking to waiter), Programmatic Mode (drive-through) +Three Ways to Use GitHub Copilot CLI - Plan Mode (GPS route to restaurant), Interactive Mode (talking to waiter), Programmatic Mode (drive-through) *Choose your mode based on the task: Plan for mapping it out first, Interactive for back-and-forth collaboration, Programmatic for quick one-shot results* @@ -230,7 +241,7 @@ Once you're comfortable, try: ### Mode 1: Interactive Mode (start here) -Interactive Mode - Like talking to a waiter who can answer questions and adjust the order +Interactive Mode - Like talking to a waiter who can answer questions and adjust the order **Best for**: Exploration, iteration, multi-turn conversations. Like talking to a waiter who can answer questions, take feedback, and adjust the order on the fly. @@ -268,7 +279,7 @@ Notice how each prompt builds on the previous answer. You're having a conversati ### Mode 2: Plan Mode -Plan Mode - Like planning a route before a trip using GPS +Plan Mode - Like planning a route before a trip using GPS **Best for**: Complex tasks where you want to review the approach before execution. Similar to planning a route before a trip using GPS. @@ -324,7 +335,7 @@ Proceed with implementation? [Y/n] ### Mode 3: Programmatic Mode -Programmatic Mode - Like using a drive-through for a quick order +Programmatic Mode - Like using a drive-through for a quick order **Best for**: Automation, scripts, CI/CD, single-shot commands. Like using a drive-through for a quick order without needing to talk to a waiter. @@ -372,11 +383,14 @@ These commands are great to learn initially as you're getting started with Copil | `/help` | Show all available commands | When you forget a command | | `/model` | Show or switch AI model | When you want to change the AI model | | `/plan` | Plan your work out before coding | For more complex features | +| `/refine` | Rewrite a rough, stream-of-consciousness prompt into a clear, focused one | When your prompt feels messy and you want better results | | `/research` | Deep research using GitHub and web sources | When you need to investigate a topic before coding | | `/exit` | End the session | When you're done | > 💡 **`/ask` vs regular chat**: Normally every message you send becomes part of the ongoing conversation and affects future responses. `/ask` is an "off the record" shortcut — perfect for quick one-off questions like `/ask What does YAML mean?` without polluting your session context. +> 💡 **`/refine` for better prompts**: Not sure if your prompt is clear enough? Type it out as it comes to mind, then run `/refine` to let Copilot rewrite it into a precise, well-structured prompt before sending. This is especially useful when you're new to AI tools and still learning how to write effective prompts. + > 💡 **Tab-completion**: When typing a slash command, press **Tab** to auto-complete the command name or cycle through available subcommands and arguments. This is especially handy when you can't remember the exact name of a command. That's it for getting started! As you become comfortable, you can explore additional commands. @@ -396,6 +410,7 @@ That's it for getting started! As you become comfortable, you can explore additi | `/env` | Show loaded environment details — what instructions, MCP servers, skills, agents, and plugins are active | | `/init` | Initialize Copilot instructions for your repository | | `/mcp` | Manage MCP server configuration | +| `/settings` | Open an interactive dialog to browse and edit all user settings in one place | | `/skills` | Manage skills for enhanced capabilities | > 💡 Agents are covered in [Chapter 04](../04-agents-custom-instructions/README.md), skills are covered in [Chapter 05](../05-skills/README.md), and MCP servers are covered in [Chapter 06](../06-mcp-servers/README.md). @@ -447,6 +462,8 @@ That's it for getting started! As you become comfortable, you can explore additi | `/usage` | Display session usage metrics and statistics, including quota progress bars | | `/session` | Show session info and workspace summary; use `/session delete`, `/session delete `, or `/session delete-all` to remove sessions | | `/share` | Export session as a markdown file, GitHub gist, or self-contained HTML file | +| `/every ` | Schedule a prompt to run on a recurring interval (e.g., `/every 1h summarize new commits`). Use natural language for the interval. `/loop` is an alias for `/every`. | +| `/after
--- # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Time to put what you've learned into action. @@ -648,7 +669,7 @@ The examples used `/plan` for a search feature and `-p` for batch reviews. Now t |---------|--------------|-----| | Typing `exit` instead of `/exit` | Copilot CLI treats "exit" as a prompt, not a command | Slash commands always start with `/` | | Using `-p` for multi-turn conversations | Each `-p` call is isolated with no memory of previous calls | Use interactive mode (`copilot`) for conversations that build on context | -| Forgetting quotes around prompts with `$` or `!` | Shell interprets special characters before Copilot CLI sees them | Wrap prompts in quotes: `copilot -p "What does $HOME mean?"` | +| Forgetting quotes around prompts with `$` or `!` | Shell interprets special characters before Copilot CLI sees them | Wrap prompts in single quotes: `copilot -p 'What does $HOME mean?'` | | Pressing Esc once to cancel a running task | A single Esc no longer cancels in-flight work (to prevent accidents) | Press **Esc twice** to cancel while Copilot CLI is processing | ### Troubleshooting diff --git a/01-setup-and-first-steps/images/chapter-header.png b/01-setup-and-first-steps/assets/chapter-header.png similarity index 100% rename from 01-setup-and-first-steps/images/chapter-header.png rename to 01-setup-and-first-steps/assets/chapter-header.png diff --git a/01-setup-and-first-steps/images/code-review-demo.gif b/01-setup-and-first-steps/assets/code-review-demo.gif similarity index 100% rename from 01-setup-and-first-steps/images/code-review-demo.gif rename to 01-setup-and-first-steps/assets/code-review-demo.gif diff --git a/01-setup-and-first-steps/images/code-review-demo.tape b/01-setup-and-first-steps/assets/code-review-demo.tape similarity index 100% rename from 01-setup-and-first-steps/images/code-review-demo.tape rename to 01-setup-and-first-steps/assets/code-review-demo.tape diff --git a/01-setup-and-first-steps/images/explain-code-demo.gif b/01-setup-and-first-steps/assets/explain-code-demo.gif similarity index 100% rename from 01-setup-and-first-steps/images/explain-code-demo.gif rename to 01-setup-and-first-steps/assets/explain-code-demo.gif diff --git a/01-setup-and-first-steps/images/explain-code-demo.tape b/01-setup-and-first-steps/assets/explain-code-demo.tape similarity index 100% rename from 01-setup-and-first-steps/images/explain-code-demo.tape rename to 01-setup-and-first-steps/assets/explain-code-demo.tape diff --git a/01-setup-and-first-steps/images/first-copilot-experience.png b/01-setup-and-first-steps/assets/first-copilot-experience.png similarity index 100% rename from 01-setup-and-first-steps/images/first-copilot-experience.png rename to 01-setup-and-first-steps/assets/first-copilot-experience.png diff --git a/01-setup-and-first-steps/images/generate-code-demo.gif b/01-setup-and-first-steps/assets/generate-code-demo.gif similarity index 100% rename from 01-setup-and-first-steps/images/generate-code-demo.gif rename to 01-setup-and-first-steps/assets/generate-code-demo.gif diff --git a/01-setup-and-first-steps/images/generate-code-demo.tape b/01-setup-and-first-steps/assets/generate-code-demo.tape similarity index 100% rename from 01-setup-and-first-steps/images/generate-code-demo.tape rename to 01-setup-and-first-steps/assets/generate-code-demo.tape diff --git a/01-setup-and-first-steps/images/interactive-mode.png b/01-setup-and-first-steps/assets/interactive-mode.png similarity index 100% rename from 01-setup-and-first-steps/images/interactive-mode.png rename to 01-setup-and-first-steps/assets/interactive-mode.png diff --git a/01-setup-and-first-steps/images/modes-and-commands.png b/01-setup-and-first-steps/assets/modes-and-commands.png similarity index 100% rename from 01-setup-and-first-steps/images/modes-and-commands.png rename to 01-setup-and-first-steps/assets/modes-and-commands.png diff --git a/01-setup-and-first-steps/images/ordering-food-analogy.png b/01-setup-and-first-steps/assets/ordering-food-analogy.png similarity index 100% rename from 01-setup-and-first-steps/images/ordering-food-analogy.png rename to 01-setup-and-first-steps/assets/ordering-food-analogy.png diff --git a/01-setup-and-first-steps/images/plan-mode.png b/01-setup-and-first-steps/assets/plan-mode.png similarity index 100% rename from 01-setup-and-first-steps/images/plan-mode.png rename to 01-setup-and-first-steps/assets/plan-mode.png diff --git a/01-setup-and-first-steps/images/programmatic-mode.png b/01-setup-and-first-steps/assets/programmatic-mode.png similarity index 100% rename from 01-setup-and-first-steps/images/programmatic-mode.png rename to 01-setup-and-first-steps/assets/programmatic-mode.png diff --git a/02-context-conversations/README.md b/02-context-conversations/README.md index 16a134cd..60397cbb 100644 --- a/02-context-conversations/README.md +++ b/02-context-conversations/README.md @@ -1,4 +1,15 @@ -![Chapter 02: Context and Conversations](images/chapter-header.png) + + +![Chapter 02: Context and Conversations](assets/chapter-header.png) > **What if AI could see your entire codebase, not just one file at a time?** @@ -20,7 +31,7 @@ By the end of this chapter, you'll be able to: ## 🧩 Real-World Analogy: Working with a Colleague -Context Makes the Difference - Without vs With Context +Context Makes the Difference - Without vs With Context *Just like your colleagues, Copilot CLI isn't a mind reader. Providing more information helps humans and Copilot alike provide targeted support!* @@ -36,7 +47,7 @@ To provide context to Copilot CLI use *the `@` syntax* to point Copilot CLI at s # Essential: Basic Context -Glowing code blocks connected by light trails representing how context flows through Copilot CLI conversations +Glowing code blocks connected by light trails representing how context flows through Copilot CLI conversations This section covers everything you need to work effectively with context. Master these basics first. @@ -89,7 +100,7 @@ copilot
🎬 See it in action! -![File Context Demo](images/file-context-demo.gif) +![File Context Demo](assets/file-context-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -119,7 +130,7 @@ copilot This is where context becomes a superpower. Single-file analysis is useful. Cross-file analysis is transformative. -Cross-File Intelligence - comparing single-file vs cross-file analysis showing how analyzing files together reveals bugs, data flow, and patterns invisible in isolation +Cross-File Intelligence - comparing single-file vs cross-file analysis showing how analyzing files together reveals bugs, data flow, and patterns invisible in isolation ### Demo: Find Bugs That Span Multiple Files @@ -142,7 +153,7 @@ copilot
🎬 See it in action! -![Multi-File Demo](images/multi-file-demo.gif) +![Multi-File Demo](assets/multi-file-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -185,7 +196,7 @@ Cross-Module Analysis ### Demo: Understand a Codebase in 60 Seconds -Split-screen comparison showing manual code review taking 1 hour versus AI-assisted analysis taking 10 seconds +Split-screen comparison showing manual code review taking 1 hour versus AI-assisted analysis taking 10 seconds New to a project? Learn about it quickly using Copilot CLI. @@ -253,7 +264,7 @@ copilot
🎬 See a multi-turn conversation in action! -![Multi-Turn Demo](images/multi-turn-demo.gif) +![Multi-Turn Demo](assets/multi-turn-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -303,6 +314,9 @@ copilot --continue # Pick from a list of sessions interactively copilot --resume +# -r is a shorthand for --resume (saves some typing!) +copilot -r + # Or resume a specific session by ID copilot --resume=abc123 @@ -400,7 +414,7 @@ Context usage: 62k/200k tokens (31%) ### Pick Up Where You Left Off -Timeline showing how GitHub Copilot CLI sessions persist across days - start on Monday, resume on Wednesday with full context restored +Timeline showing how GitHub Copilot CLI sessions persist across days - start on Monday, resume on Wednesday with full context restored *Sessions auto-save when you exit. Resume days later with full context: files, issues, and progress all remembered.* @@ -459,7 +473,7 @@ No re-explaining. No re-reading files. Just continue working. # Optional: Going Deeper -Abstract crystal cave in blue and purple tones representing deeper exploration of context concepts +Abstract crystal cave in blue and purple tones representing deeper exploration of context concepts These topics build on the essentials above. **Pick what interests you, or skip ahead to [Practice](#practice).** @@ -571,7 +585,7 @@ You already know `/context` and `/clear` from the essentials. Here's the deeper Every AI has a "context window," which is the amount of text it can consider at once. -Context Window Visualization +Context Window Visualization *The context window is like a desk: it can only hold so much at once. Files, conversation history, and system prompts all take space.* @@ -734,9 +748,9 @@ You can include images in your conversations using the `@` syntax, or simply **p ```bash copilot -> @images/screenshot.png What is happening in this image? +> @assets/screenshot.png What is happening in this image? -> @images/mockup.png Write the HTML and CSS to match this design. Place it in a new file called index.html and put the CSS in styles.css. +> @assets/mockup.png Write the HTML and CSS to match this design. Place it in a new file called index.html and put the CSS in styles.css. ``` > 📖 **Learn more**: See [Additional Context Features](../appendices/additional-context.md#working-with-images) for supported formats, practical use cases, and tips for combining images with code. @@ -747,7 +761,7 @@ copilot # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Time to apply your context and session management skills. diff --git a/02-context-conversations/images/chapter-header.png b/02-context-conversations/assets/chapter-header.png similarity index 100% rename from 02-context-conversations/images/chapter-header.png rename to 02-context-conversations/assets/chapter-header.png diff --git a/02-context-conversations/images/codebase-understanding.png b/02-context-conversations/assets/codebase-understanding.png similarity index 100% rename from 02-context-conversations/images/codebase-understanding.png rename to 02-context-conversations/assets/codebase-understanding.png diff --git a/02-context-conversations/images/colleague-context-analogy.png b/02-context-conversations/assets/colleague-context-analogy.png similarity index 100% rename from 02-context-conversations/images/colleague-context-analogy.png rename to 02-context-conversations/assets/colleague-context-analogy.png diff --git a/02-context-conversations/images/context-window-visualization.png b/02-context-conversations/assets/context-window-visualization.png similarity index 100% rename from 02-context-conversations/images/context-window-visualization.png rename to 02-context-conversations/assets/context-window-visualization.png diff --git a/02-context-conversations/images/cross-file-intelligence.png b/02-context-conversations/assets/cross-file-intelligence.png similarity index 100% rename from 02-context-conversations/images/cross-file-intelligence.png rename to 02-context-conversations/assets/cross-file-intelligence.png diff --git a/02-context-conversations/images/essential-basic-context.png b/02-context-conversations/assets/essential-basic-context.png similarity index 100% rename from 02-context-conversations/images/essential-basic-context.png rename to 02-context-conversations/assets/essential-basic-context.png diff --git a/02-context-conversations/images/file-context-demo.gif b/02-context-conversations/assets/file-context-demo.gif similarity index 100% rename from 02-context-conversations/images/file-context-demo.gif rename to 02-context-conversations/assets/file-context-demo.gif diff --git a/02-context-conversations/images/file-context-demo.tape b/02-context-conversations/assets/file-context-demo.tape similarity index 100% rename from 02-context-conversations/images/file-context-demo.tape rename to 02-context-conversations/assets/file-context-demo.tape diff --git a/02-context-conversations/images/multi-file-demo.gif b/02-context-conversations/assets/multi-file-demo.gif similarity index 100% rename from 02-context-conversations/images/multi-file-demo.gif rename to 02-context-conversations/assets/multi-file-demo.gif diff --git a/02-context-conversations/images/multi-file-demo.tape b/02-context-conversations/assets/multi-file-demo.tape similarity index 100% rename from 02-context-conversations/images/multi-file-demo.tape rename to 02-context-conversations/assets/multi-file-demo.tape diff --git a/02-context-conversations/images/multi-turn-demo.gif b/02-context-conversations/assets/multi-turn-demo.gif similarity index 100% rename from 02-context-conversations/images/multi-turn-demo.gif rename to 02-context-conversations/assets/multi-turn-demo.gif diff --git a/02-context-conversations/images/multi-turn-demo.tape b/02-context-conversations/assets/multi-turn-demo.tape similarity index 100% rename from 02-context-conversations/images/multi-turn-demo.tape rename to 02-context-conversations/assets/multi-turn-demo.tape diff --git a/02-context-conversations/images/optional-going-deeper.png b/02-context-conversations/assets/optional-going-deeper.png similarity index 100% rename from 02-context-conversations/images/optional-going-deeper.png rename to 02-context-conversations/assets/optional-going-deeper.png diff --git a/02-context-conversations/images/session-persistence-timeline.png b/02-context-conversations/assets/session-persistence-timeline.png similarity index 100% rename from 02-context-conversations/images/session-persistence-timeline.png rename to 02-context-conversations/assets/session-persistence-timeline.png diff --git a/03-development-workflows/README.md b/03-development-workflows/README.md index a7b3f0c3..0116c50f 100644 --- a/03-development-workflows/README.md +++ b/03-development-workflows/README.md @@ -1,4 +1,15 @@ -![Chapter 03: Development Workflows](images/chapter-header.png) + + +![Chapter 03: Development Workflows](assets/chapter-header.png) > **What if the AI could find bugs you didn't even know to ask about?** @@ -22,7 +33,7 @@ By the end of this chapter, you'll be able to: A carpenter doesn't just know how to use tools, they have *workflows* for different jobs: -Craftsman workshop showing three workflow lanes: Building Furniture (Measure, Cut, Assemble, Finish), Fixing Damage (Assess, Remove, Repair, Match), and Quality Check (Inspect, Test Joints, Check Alignment) +Craftsman workshop showing three workflow lanes: Building Furniture (Measure, Cut, Assemble, Finish), Fixing Damage (Assess, Remove, Repair, Match), and Quality Check (Inspect, Test Joints, Check Alignment) Similarly, developers have workflows for different tasks. GitHub Copilot CLI enhances each of these workflows, making you more efficient and effective in your daily coding tasks. @@ -30,7 +41,7 @@ Similarly, developers have workflows for different tasks. GitHub Copilot CLI enh # The Five Workflows -Five glowing neon icons representing code review, testing, debugging, refactoring, and git integration workflows +Five glowing neon icons representing code review, testing, debugging, refactoring, and git integration workflows Each workflow below is self-contained. Pick the ones that match your current needs, or work through them all. @@ -40,7 +51,7 @@ Each workflow below is self-contained. Pick the ones that match your current nee This chapter covers five workflows that developers typically use. **However, you don't need to read them all at once!** Each workflow is self-contained in a collapsible section below. Pick the ones that match what you need and that fits best with your current project. You can always come back and explore the others later. -Five Development Workflows: Code Review, Refactoring, Debugging, Test Generation, and Git Integration shown as horizontal swimlanes +Five Development Workflows: Code Review, Refactoring, Debugging, Test Generation, and Git Integration shown as horizontal swimlanes | I want to... | Jump to | |---|---| @@ -60,7 +71,7 @@ This chapter covers five workflows that developers typically use. **However, you
Workflow 1: Code Review - Review files, use the /review agent, create severity checklists -Code review workflow: review, identify issues, prioritize, generate checklist. +Code review workflow: review, identify issues, prioritize, generate checklist. ### Basic Review @@ -77,7 +88,7 @@ copilot
🎬 See it in action! -![Code Review Demo](images/code-review-demo.gif) +![Code Review Demo](assets/code-review-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -185,7 +196,7 @@ copilot
Workflow 2: Refactoring - Restructure code, separate concerns, improve error handling -Refactoring workflow: assess code, plan changes, implement, verify behavior. +Refactoring workflow: assess code, plan changes, implement, verify behavior. ### Simple Refactoring @@ -210,7 +221,7 @@ copilot
🎬 See it in action! -![Refactor Demo](images/refactor-demo.gif) +![Refactor Demo](assets/refactor-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -278,7 +289,7 @@ copilot
Workflow 3: Debugging - Track down bugs, security audits, trace issues across files -Debugging workflow: understand error, locate root cause, fix, test. +Debugging workflow: understand error, locate root cause, fix, test. ### Simple Debugging @@ -306,7 +317,7 @@ copilot
🎬 See it in action! -![Fix Bug Demo](images/fix-bug-demo.gif) +![Fix Bug Demo](assets/fix-bug-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -420,7 +431,7 @@ copilot
Workflow 4: Test Generation - Generate comprehensive tests and edge cases automatically -Test Generation workflow: analyze function, generate tests, include edge cases, run. +Test Generation workflow: analyze function, generate tests, include edge cases, run. > **Try this first:** `@samples/book-app-project/books.py Generate pytest tests for all functions including edge cases` @@ -450,7 +461,7 @@ copilot
🎬 See it in action! -![Test Generation Demo](images/test-gen-demo.gif) +![Test Generation Demo](assets/test-gen-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -571,9 +582,9 @@ copilot
-Workflow 5: Git Integration - Commit messages, PR descriptions, /pr, /delegate, and /diff +Workflow 5: Git Integration - Commit messages, PR descriptions, /pr, /delegate, /diff, and /branch -Git Integration workflow: stage changes, generate message, commit, create PR. +Git Integration workflow: stage changes, generate message, commit, create PR. > 💡 **This workflow assumes basic git familiarity** (staging, committing, branches). If git is new to you, try the other four workflows first. @@ -604,7 +615,7 @@ copilot -p "Generate a conventional commit message for: $(git diff --staged)"
🎬 See it in action! -![Git Integration Demo](images/git-integration-demo.gif) +![Git Integration Demo](assets/git-integration-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -680,7 +691,7 @@ This is great for well-defined tasks you want completed while you focus on other ### Using /diff to Review Session Changes -The `/diff` command shows all changes made during your current session. Use this slash command to see a visual diff of everything Copilot CLI has modified before you commit. +The `/diff` command shows all changes made during your current session. Use this slash command to see a visual diff of everything Copilot CLI has modified before you commit. It also works in folders that aren't git repositories. ```bash copilot @@ -692,6 +703,28 @@ copilot # Great for reviewing before committing ``` +### Branching Your Session with /branch or /fork + +Sometimes you want to explore two different approaches to a problem without losing your original conversation. The `/branch` command (also available as `/fork`) creates a copy of your current session so you can try a different direction and then compare results. + +```bash +copilot + +> Fix the find_by_author function to support partial matches + +# You want to try a different approach — branch first! +> /branch + +# Now you're in a new session copy. Try your alternative approach: +> Fix find_by_author using a different regex-based strategy + +# If you don't like the result, switch back to your original session using /session +``` + +> 💡 **`/branch` and `/fork` are the same**: Both commands do identical things. `/branch` was added as a more intuitive name. Use whichever makes more sense to you. + +> 💡 **When to branch**: Branching is great when you're unsure which approach is better and want to keep both options open. +
--- @@ -770,7 +803,7 @@ git commit -m "" # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Now it's your turn to apply these workflows. @@ -850,7 +883,7 @@ copilot The exercise shows developers how to use GitHub Copilot CLI to create issues, generate code, and collaborate from the terminal while building a Node.js calculator app. You'll install the CLI, use templates and agents, and practice iterative, command-line driven development. -##### [Start the "Create applications with the Copilot CLI" Skills Exercise](https://github.com/skills/create-applications-with-the-copilot-cli) +##### [Start the "Create applications with the Copilot CLI" Skills Exercise](https://github.com/skills/create-applications-with-the-copilot-cli) --- @@ -904,7 +937,7 @@ copilot ## 🔑 Key Takeaways -Specialized Workflows for Every Task: Code Review, Refactoring, Debugging, Testing, and Git Integration +Specialized Workflows for Every Task: Code Review, Refactoring, Debugging, Testing, and Git Integration 1. **Code review** becomes comprehensive with specific prompts 2. **Refactoring** is safer when you generate tests first diff --git a/03-development-workflows/images/carpenter-workflow-steps.png b/03-development-workflows/assets/carpenter-workflow-steps.png similarity index 100% rename from 03-development-workflows/images/carpenter-workflow-steps.png rename to 03-development-workflows/assets/carpenter-workflow-steps.png diff --git a/03-development-workflows/images/chapter-header.png b/03-development-workflows/assets/chapter-header.png similarity index 100% rename from 03-development-workflows/images/chapter-header.png rename to 03-development-workflows/assets/chapter-header.png diff --git a/03-development-workflows/images/code-review-demo.gif b/03-development-workflows/assets/code-review-demo.gif similarity index 100% rename from 03-development-workflows/images/code-review-demo.gif rename to 03-development-workflows/assets/code-review-demo.gif diff --git a/03-development-workflows/images/code-review-demo.tape b/03-development-workflows/assets/code-review-demo.tape similarity index 100% rename from 03-development-workflows/images/code-review-demo.tape rename to 03-development-workflows/assets/code-review-demo.tape diff --git a/03-development-workflows/images/code-review-swimlane-single.png b/03-development-workflows/assets/code-review-swimlane-single.png similarity index 100% rename from 03-development-workflows/images/code-review-swimlane-single.png rename to 03-development-workflows/assets/code-review-swimlane-single.png diff --git a/03-development-workflows/images/debugging-swimlane-single.png b/03-development-workflows/assets/debugging-swimlane-single.png similarity index 100% rename from 03-development-workflows/images/debugging-swimlane-single.png rename to 03-development-workflows/assets/debugging-swimlane-single.png diff --git a/03-development-workflows/images/five-workflows-swimlane.png b/03-development-workflows/assets/five-workflows-swimlane.png similarity index 100% rename from 03-development-workflows/images/five-workflows-swimlane.png rename to 03-development-workflows/assets/five-workflows-swimlane.png diff --git a/03-development-workflows/images/five-workflows.png b/03-development-workflows/assets/five-workflows.png similarity index 100% rename from 03-development-workflows/images/five-workflows.png rename to 03-development-workflows/assets/five-workflows.png diff --git a/03-development-workflows/images/fix-bug-demo.gif b/03-development-workflows/assets/fix-bug-demo.gif similarity index 100% rename from 03-development-workflows/images/fix-bug-demo.gif rename to 03-development-workflows/assets/fix-bug-demo.gif diff --git a/03-development-workflows/images/fix-bug-demo.tape b/03-development-workflows/assets/fix-bug-demo.tape similarity index 100% rename from 03-development-workflows/images/fix-bug-demo.tape rename to 03-development-workflows/assets/fix-bug-demo.tape diff --git a/03-development-workflows/images/git-integration-demo.gif b/03-development-workflows/assets/git-integration-demo.gif similarity index 100% rename from 03-development-workflows/images/git-integration-demo.gif rename to 03-development-workflows/assets/git-integration-demo.gif diff --git a/03-development-workflows/images/git-integration-demo.tape b/03-development-workflows/assets/git-integration-demo.tape similarity index 100% rename from 03-development-workflows/images/git-integration-demo.tape rename to 03-development-workflows/assets/git-integration-demo.tape diff --git a/03-development-workflows/images/git-integration-swimlane-single.png b/03-development-workflows/assets/git-integration-swimlane-single.png similarity index 100% rename from 03-development-workflows/images/git-integration-swimlane-single.png rename to 03-development-workflows/assets/git-integration-swimlane-single.png diff --git a/03-development-workflows/images/refactor-demo.gif b/03-development-workflows/assets/refactor-demo.gif similarity index 100% rename from 03-development-workflows/images/refactor-demo.gif rename to 03-development-workflows/assets/refactor-demo.gif diff --git a/03-development-workflows/images/refactor-demo.tape b/03-development-workflows/assets/refactor-demo.tape similarity index 100% rename from 03-development-workflows/images/refactor-demo.tape rename to 03-development-workflows/assets/refactor-demo.tape diff --git a/03-development-workflows/images/refactoring-swimlane-single.png b/03-development-workflows/assets/refactoring-swimlane-single.png similarity index 100% rename from 03-development-workflows/images/refactoring-swimlane-single.png rename to 03-development-workflows/assets/refactoring-swimlane-single.png diff --git a/03-development-workflows/images/request.json b/03-development-workflows/assets/request.json similarity index 100% rename from 03-development-workflows/images/request.json rename to 03-development-workflows/assets/request.json diff --git a/03-development-workflows/images/specialized-workflows.png b/03-development-workflows/assets/specialized-workflows.png similarity index 100% rename from 03-development-workflows/images/specialized-workflows.png rename to 03-development-workflows/assets/specialized-workflows.png diff --git a/03-development-workflows/images/test-gen-demo.gif b/03-development-workflows/assets/test-gen-demo.gif similarity index 100% rename from 03-development-workflows/images/test-gen-demo.gif rename to 03-development-workflows/assets/test-gen-demo.gif diff --git a/03-development-workflows/images/test-gen-demo.tape b/03-development-workflows/assets/test-gen-demo.tape similarity index 100% rename from 03-development-workflows/images/test-gen-demo.tape rename to 03-development-workflows/assets/test-gen-demo.tape diff --git a/03-development-workflows/images/test-gen-swimlane-single.png b/03-development-workflows/assets/test-gen-swimlane-single.png similarity index 100% rename from 03-development-workflows/images/test-gen-swimlane-single.png rename to 03-development-workflows/assets/test-gen-swimlane-single.png diff --git a/04-agents-custom-instructions/README.md b/04-agents-custom-instructions/README.md index 5321b172..44c93a93 100644 --- a/04-agents-custom-instructions/README.md +++ b/04-agents-custom-instructions/README.md @@ -1,4 +1,15 @@ -![Chapter 04: Agents and Custom Instructions](images/chapter-header.png) + + +![Chapter 04: Agents and Custom Instructions](assets/chapter-header.png) > **What if you could hire a Python code reviewer, testing expert, and security reviewer... all in one tool?** @@ -32,7 +43,7 @@ When you need help with your house, you don't call one "general helper." You cal Agents work the same way. Instead of a generic AI, use agents that focus on specific tasks and know the right process to follow. Set up the instructions once, then reuse them whenever you need that specialty: code review, testing, security, documentation. -Hiring Specialists Analogy - Just as you call specialized tradespeople for house repairs, AI agents are specialized for specific tasks like code review, testing, security, and documentation +Hiring Specialists Analogy - Just as you call specialized tradespeople for house repairs, AI agents are specialized for specific tasks like code review, testing, security, and documentation --- @@ -105,7 +116,7 @@ What about the Task Agent? It works behind the scenes to manage and track what i You can simply define your own agents to be part of your workflow! Define once, then direct! -Four colorful AI robots standing together, each with different tools representing specialized agent capabilities +Four colorful AI robots standing together, each with different tools representing specialized agent capabilities ## 🗂️ Add your agents @@ -185,11 +196,13 @@ copilot --agent python-reviewer > 💡 **Switching agents**: You can switch to a different agent at any time by using `/agent` or `--agent` again. To return to the standard Copilot CLI experience, use `/agent` and select **no agent**. +> 💡 **Agent mode is session-scoped**: The agent you select applies only to the current session. When you start a new session with `/new`, `/clear`, or by opening a fresh terminal, Copilot returns to its default mode — your agent selection does not carry over automatically. This means each session starts with a clean slate, which is a good habit to keep your work focused. + --- # Going Deeper with Agents -Robot being assembled on a workbench surrounded by components and tools representing custom agent creation +Robot being assembled on a workbench surrounded by components and tools representing custom agent creation > 💡 **This section is optional.** The built-in agents (`/plan`, `/review`) are powerful enough for most workflows. Create custom agents when you need specialized expertise that's consistently applied across your work. @@ -337,7 +350,7 @@ copilot
🎬 See it in action! -![Python Reviewer Demo](images/python-reviewer-demo.gif) +![Python Reviewer Demo](assets/python-reviewer-demo.gif) *Demo output varies - your model, tools, and responses will differ from what's shown here.* @@ -386,7 +399,7 @@ Think of it this way: agents are specialists you call on, and instruction files You already know the two main locations (see [Where to put agent files](#where-to-put-agent-files) above). Use this decision tree to choose: -Decision tree for where to put agent files: experimenting → current folder, team use → .github/agents/, everywhere → ~/.copilot/agents/ +Decision tree for where to put agent files: experimenting → current folder, team use → .github/agents/, everywhere → ~/.copilot/agents/ **Start simple:** Create a single `*.agent.md` file in your project folder. Move it to a permanent location once you're happy with it. @@ -422,6 +435,7 @@ Copilot will scan your project and create tailored instruction files. You can ed | `AGENTS.md` | Project root or nested | **Cross-platform standard** - works with Copilot and other AI assistants | | `.github/copilot-instructions.md` | Project | GitHub Copilot specific | | `.github/instructions/*.instructions.md` | Project | Granular, topic-specific instructions | +| `~/.copilot/instructions/**/*.instructions.md` | User (all projects) | Personal instructions that apply everywhere, across all your repos | | `CLAUDE.md`, `GEMINI.md` | Project root | Supported for compatibility | > 🎯 **Just getting started?** Use `AGENTS.md` for project instructions. You can explore the other formats later as needed. @@ -472,6 +486,22 @@ Here are some common patterns: > 💡 **Tip**: Wrap the glob pattern in quotes (e.g., `"**/*.py"`) to ensure it is interpreted correctly across all operating systems and shells. +#### Importing Other Files with `@` + +You can reference another file inside `AGENTS.md` or any instruction file using `@filepath` syntax. Copilot expands the reference and includes that file's content automatically, so you can keep your main file short while storing the details elsewhere: + +```markdown + +# Project Instructions + +@.github/instructions/python-standards.instructions.md +@.github/instructions/test-standards.instructions.md +``` + +This is handy when your instructions grow large. Split them into focused files and `@`-import them from a single `AGENTS.md`. The same syntax works inside `.github/copilot-instructions.md` and other instruction files too. + +> 💡 **Tip**: Use `@`-imports to share a common base file across multiple instruction files. For example, you could have a `@.github/instructions/shared-rules.md` that every other instruction file pulls in. + **Finding community instruction files**: Browse [github/awesome-copilot](https://github.com/github/awesome-copilot) for pre-made instruction files covering .NET, Angular, Azure, Python, Docker, and many more technologies. ### Disabling Custom Instructions @@ -565,7 +595,7 @@ For community agents, see [github/awesome-copilot](https://github.com/github/awe # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Create your own agents and see them in action. diff --git a/04-agents-custom-instructions/images/agent-file-placement-decision-tree.png b/04-agents-custom-instructions/assets/agent-file-placement-decision-tree.png similarity index 100% rename from 04-agents-custom-instructions/images/agent-file-placement-decision-tree.png rename to 04-agents-custom-instructions/assets/agent-file-placement-decision-tree.png diff --git a/04-agents-custom-instructions/images/chapter-header.png b/04-agents-custom-instructions/assets/chapter-header.png similarity index 100% rename from 04-agents-custom-instructions/images/chapter-header.png rename to 04-agents-custom-instructions/assets/chapter-header.png diff --git a/04-agents-custom-instructions/images/creating-custom-agents.png b/04-agents-custom-instructions/assets/creating-custom-agents.png similarity index 100% rename from 04-agents-custom-instructions/images/creating-custom-agents.png rename to 04-agents-custom-instructions/assets/creating-custom-agents.png diff --git a/04-agents-custom-instructions/images/hiring-specialists-analogy.png b/04-agents-custom-instructions/assets/hiring-specialists-analogy.png similarity index 100% rename from 04-agents-custom-instructions/images/hiring-specialists-analogy.png rename to 04-agents-custom-instructions/assets/hiring-specialists-analogy.png diff --git a/04-agents-custom-instructions/images/python-reviewer-demo.gif b/04-agents-custom-instructions/assets/python-reviewer-demo.gif similarity index 100% rename from 04-agents-custom-instructions/images/python-reviewer-demo.gif rename to 04-agents-custom-instructions/assets/python-reviewer-demo.gif diff --git a/04-agents-custom-instructions/images/python-reviewer-demo.tape b/04-agents-custom-instructions/assets/python-reviewer-demo.tape similarity index 100% rename from 04-agents-custom-instructions/images/python-reviewer-demo.tape rename to 04-agents-custom-instructions/assets/python-reviewer-demo.tape diff --git a/04-agents-custom-instructions/images/using-agents.png b/04-agents-custom-instructions/assets/using-agents.png similarity index 100% rename from 04-agents-custom-instructions/images/using-agents.png rename to 04-agents-custom-instructions/assets/using-agents.png diff --git a/05-skills/README.md b/05-skills/README.md index e3a55209..7036d2c7 100644 --- a/05-skills/README.md +++ b/05-skills/README.md @@ -1,4 +1,15 @@ -![Chapter 05: Skills System](images/chapter-header.png) + + +![Chapter 05: Skills System](assets/chapter-header.png) > **What if Copilot could automatically apply your team's best practices without you having to explain them every time?** @@ -21,7 +32,7 @@ By the end of this chapter, you'll be able to: ## 🧩 Real-World Analogy: Power Tools A general-purpose drill is useful, but specialized attachments make it powerful. -Power Tools - Skills Extend Copilot's Capabilities +Power Tools - Skills Extend Copilot's Capabilities Skills work the same way. Just like swapping drill bits for different jobs, you can add skills to Copilot for different tasks: @@ -41,7 +52,7 @@ Skills work the same way. Just like swapping drill bits for different jobs, you # How Skills Work -Glowing RPG-style skill icons connected by light trails on a starfield background representing Copilot skills +Glowing RPG-style skill icons connected by light trails on a starfield background representing Copilot skills Learn what skills are, why they matter, and how they differ from agents and MCP. @@ -137,7 +148,7 @@ Skills are just one piece of GitHub Copilot's extensibility model. Here's how th > *Don't worry about MCP quite yet. We'll cover it in [Chapter 06](../06-mcp-servers/). It's included here so you can see how skills fit into the overall picture.* -Comparison diagram showing the differences between Agents, Skills, and MCP Servers and how they combine into your workflow +Comparison diagram showing the differences between Agents, Skills, and MCP Servers and how they combine into your workflow | Feature | What It Does | When to Use | |---------|--------------|-------------| @@ -192,7 +203,7 @@ copilot 3. Automatically loads your team's quality checklist 4. Applies all checks without you listing them -How Skills Auto-Trigger - 4-step flow showing how Copilot automatically matches your prompt to the right skill +How Skills Auto-Trigger - 4-step flow showing how Copilot automatically matches your prompt to the right skill *Just ask naturally. Copilot matches your prompt to the right skill and applies it automatically.* @@ -227,7 +238,7 @@ copilot
🎬 See it in action! -![Skill Trigger Demo](images/skill-trigger-demo.gif) +![Skill Trigger Demo](assets/skill-trigger-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -275,7 +286,7 @@ PR Review: feature/user-auth # Creating Custom Skills -Human and robotic hands building a wall of glowing LEGO-like blocks representing skill creation and management +Human and robotic hands building a wall of glowing LEGO-like blocks representing skill creation and management Build your own skills from SKILL.md files. @@ -358,6 +369,9 @@ Provide issues as a numbered list with severity: | `name` | **Yes** | Unique identifier (lowercase, hyphens for spaces) | | `description` | **Yes** | What the skill does and when Copilot should use it | | `license` | No | License that applies to this skill | +| `argument-hint` | No | Short hint shown to users describing what argument the skill expects (e.g., `"file path or code snippet"`) | + +> 💡 **What is `argument-hint`?** When users invoke a skill directly (e.g., `/security-audit`), the `argument-hint` text appears as a placeholder showing what to type next — like a mini help prompt. For example, setting `argument-hint: "file path to review"` tells the user to provide a file path after the skill name. > 📖 **Official docs**: [About Agent Skills](https://docs.github.com/copilot/concepts/agents/about-agent-skills) @@ -472,13 +486,33 @@ copilot --agent code-reviewer Discover installed skills, find community skills, and share your own. -Managing and Sharing Skills - showing the discover, use, create, and share cycle for CLI skills +Managing and Sharing Skills - showing the discover, use, create, and share cycle for CLI skills --- -## Managing Skills with the `/skills` Command +## Managing Skills with the `copilot skill` Command and `/skills` + +Copilot CLI gives you two ways to manage skills. You can do it directly from the terminal before starting Copilot or from inside a Copilot session. + +### Option 1: `copilot skill` (Terminal Command) -Use the `/skills` command to manage your installed skills: +The `copilot skill` subcommand lets you manage skills directly from your terminal, without opening an interactive Copilot session. This is handy for scripting, quick checks, or adding skills before you start working. + +```bash +# See all installed skills +copilot skill list + +# Add a skill from a local file, URL, or directory +copilot skill add .github/skills/my-skill/SKILL.md +copilot skill add https://example.com/skills/security-audit/SKILL.md + +# Remove a skill by name +copilot skill remove security-audit +``` + +### Option 2: `/skills` (Inside Copilot Session) + +Once you're in an interactive Copilot session, use `/skills` (or its shortcut `/skill`) to manage skills without leaving: | Command | What It Does | |---------|--------------| @@ -488,11 +522,23 @@ Use the `/skills` command to manage your installed skills: | `/skills remove ` | Disable or uninstall a skill | | `/skills reload` | Reload skills after editing SKILL.md files | +> 💡 **`/skill` shortcut**: You can type `/skill` instead of `/skills` — they're interchangeable. For example, `/skill list` works the same as `/skills list`. + > 💡 **Remember**: You don't need to "activate" skills for each prompt. Once installed, skills are **automatically triggered** when your prompt matches their description. These commands are for managing which skills are available, not for using them. ### Example: View Your Skills ```bash +# From the terminal (no interactive session needed): +copilot skill list + +Available skills: +- security-audit: Security-focused code review checking OWASP Top 10 +- generate-tests: Generate comprehensive unit tests with edge cases +- code-checklist: Team code quality checklist +... + +# Or from inside a Copilot session: copilot > /skills list @@ -516,7 +562,7 @@ Description: Security-focused code review checking OWASP Top 10 vulnerabilities
See it in action! -![List Skills Demo](images/list-skills-demo.gif) +![List Skills Demo](assets/list-skills-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -595,7 +641,7 @@ gh skill install github/awesome-copilot ai-ready --scope user # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Apply what you've learned by building and testing your own skills. @@ -862,9 +908,10 @@ Run `/skills reload` after creating or editing skills to ensure changes are pick 1. **Skills are automatic**: Copilot loads them when your prompt matches the skill's description 2. **Direct invocation**: You can also invoke skills directly with `/skill-name` as a slash command -3. **SKILL.md format**: YAML frontmatter (name, description, optional license) plus markdown instructions +3. **SKILL.md format**: YAML frontmatter (name, description, optional license, argument-hint) plus markdown instructions 4. **Location matters**: `.github/skills/` for project/team sharing, `~/.copilot/skills/` for personal use 5. **Description is key**: Write descriptions that match how you naturally ask questions +6. **Two ways to manage skills**: Use `copilot skill` from the terminal or `/skills` (shortcut: `/skill`) inside a session > 📋 **Quick Reference**: See the [GitHub Copilot CLI command reference](https://docs.github.com/en/copilot/reference/cli-command-reference) for a complete list of commands and shortcuts. diff --git a/05-skills/images/chapter-header.png b/05-skills/assets/chapter-header.png similarity index 100% rename from 05-skills/images/chapter-header.png rename to 05-skills/assets/chapter-header.png diff --git a/05-skills/images/creating-managing-skills.png b/05-skills/assets/creating-managing-skills.png similarity index 100% rename from 05-skills/images/creating-managing-skills.png rename to 05-skills/assets/creating-managing-skills.png diff --git a/05-skills/images/how-skills-work.png b/05-skills/assets/how-skills-work.png similarity index 100% rename from 05-skills/images/how-skills-work.png rename to 05-skills/assets/how-skills-work.png diff --git a/05-skills/images/list-skills-demo.gif b/05-skills/assets/list-skills-demo.gif similarity index 100% rename from 05-skills/images/list-skills-demo.gif rename to 05-skills/assets/list-skills-demo.gif diff --git a/05-skills/images/list-skills-demo.tape b/05-skills/assets/list-skills-demo.tape similarity index 100% rename from 05-skills/images/list-skills-demo.tape rename to 05-skills/assets/list-skills-demo.tape diff --git a/05-skills/images/managing-sharing-skills.png b/05-skills/assets/managing-sharing-skills.png similarity index 100% rename from 05-skills/images/managing-sharing-skills.png rename to 05-skills/assets/managing-sharing-skills.png diff --git a/05-skills/images/power-tools-analogy.png b/05-skills/assets/power-tools-analogy.png similarity index 100% rename from 05-skills/images/power-tools-analogy.png rename to 05-skills/assets/power-tools-analogy.png diff --git a/05-skills/images/skill-auto-discovery-flow.png b/05-skills/assets/skill-auto-discovery-flow.png similarity index 100% rename from 05-skills/images/skill-auto-discovery-flow.png rename to 05-skills/assets/skill-auto-discovery-flow.png diff --git a/05-skills/images/skill-trigger-demo.gif b/05-skills/assets/skill-trigger-demo.gif similarity index 100% rename from 05-skills/images/skill-trigger-demo.gif rename to 05-skills/assets/skill-trigger-demo.gif diff --git a/05-skills/images/skill-trigger-demo.tape b/05-skills/assets/skill-trigger-demo.tape similarity index 100% rename from 05-skills/images/skill-trigger-demo.tape rename to 05-skills/assets/skill-trigger-demo.tape diff --git a/05-skills/images/skills-agents-mcp-comparison.png b/05-skills/assets/skills-agents-mcp-comparison.png similarity index 100% rename from 05-skills/images/skills-agents-mcp-comparison.png rename to 05-skills/assets/skills-agents-mcp-comparison.png diff --git a/06-mcp-servers/README.md b/06-mcp-servers/README.md index a81bf57b..bfbc7f80 100644 --- a/06-mcp-servers/README.md +++ b/06-mcp-servers/README.md @@ -1,4 +1,15 @@ -![Chapter 06: MCP Servers](images/chapter-header.png) + + +![Chapter 06: MCP Servers](assets/chapter-header.png) > **What if Copilot could read your GitHub issues, check your database, and create PRs... all from the terminal?** @@ -24,7 +35,7 @@ By the end of this chapter, you'll be able to: ## 🧩 Real-World Analogy: Browser Extensions -MCP Servers are like Browser Extensions +MCP Servers are like Browser Extensions Think of MCP servers like browser extensions. Your browser on its own can display web pages, but extensions connect it to extra services: @@ -42,7 +53,7 @@ Without extensions, your browser is still useful, but with them, it becomes a po --- -Power cable connecting with bright electrical spark surrounded by floating tech icons representing MCP server connections +Power cable connecting with bright electrical spark surrounded by floating tech icons representing MCP server connections # Quick Start: MCP in 30 Seconds @@ -80,7 +91,7 @@ MCP Servers:
🎬 See it in action! -![MCP Status Demo](images/mcp-status-demo.gif) +![MCP Status Demo](assets/mcp-status-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -117,7 +128,7 @@ MCP makes Copilot aware of your actual development environment. # Configuring MCP Servers -Hands adjusting knobs and sliders on a professional audio mixing board representing MCP server configuration +Hands adjusting knobs and sliders on a professional audio mixing board representing MCP server configuration Now that you've seen MCP in action, let's set up additional servers. You can add servers in two ways: **from the built-in registry** (easiest — guided setup right in the CLI) or by **editing the config file** manually (more flexible). Start with the registry option if you're not sure which to choose. @@ -141,7 +152,7 @@ Copilot opens an interactive picker showing available servers. Select one, and t ## MCP Configuration File -MCP servers are configured in `~/.copilot/mcp-config.json` (user-level, applies to all projects) or `.mcp.json` (project-level, placed in the root of your project). If you used `/mcp search` above, the CLI already created or updated this file for you, but it's useful to understand the format for customization. +MCP servers can be configured at the user level in `~/.copilot/mcp-config.json`, which applies across projects, at the project level in `.mcp.json`, or in the workspace config file `.github/mcp.json`. `.github/mcp.json` is auto-loaded alongside `.mcp.json`. If you used `/mcp search`, the CLI created or updated your user-level `~/.copilot/mcp-config.json`, but understanding the JSON format is useful when you want to customize or share project-level MCP configuration. > ⚠️ **Note**: `.vscode/mcp.json` is no longer supported as an MCP config source. If you have an existing `.vscode/mcp.json`, migrate it to `.mcp.json` in your project root. The CLI will show a migration hint if it detects an old config file. @@ -359,7 +370,7 @@ Save this as `~/.copilot/mcp-config.json` for global access or `.mcp.json` in th Now that you have MCP servers configured, let's see what they can do. -Using MCP Servers - Hub-and-spoke diagram showing a Developer CLI connected to GitHub, Filesystem, Context7, and Custom/Web Fetch servers +Using MCP Servers - Hub-and-spoke diagram showing a Developer CLI connected to GitHub, Filesystem, Context7, and Custom/Web Fetch servers --- @@ -557,7 +568,7 @@ copilot These workflows show why developers say "I never want to work without this again." Each example combines multiple MCP servers in a single session. -Issue to PR Workflow using MCP - Shows the complete flow from getting a GitHub issue through creating a pull request +Issue to PR Workflow using MCP - Shows the complete flow from getting a GitHub issue through creating a pull request *Complete MCP workflow: GitHub MCP retrieves repo data, Filesystem MCP finds code, Context7 MCP provides best practices, and Copilot handles analysis* @@ -617,7 +628,7 @@ Suggestions:
🎬 See the MCP workflow in action! -![MCP Workflow Demo](images/mcp-workflow-demo.gif) +![MCP Workflow Demo](assets/mcp-workflow-demo.gif) *Demo output varies. Your model, tools, and responses will differ from what's shown here.* @@ -709,7 +720,7 @@ Recommendations: # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice **🎉 You now know the essentials!** You understand MCP, you've seen how to configure servers, and you've seen real workflows in action. Now it's time to try it yourself. @@ -913,6 +924,7 @@ These work when you're already inside `copilot`: | Command | What It Does | |---------|--------------| | `/mcp show` | Show all configured MCP servers and their status | +| `/mcp list` | Show currently attached MCP servers and their status; can be run while Copilot is working | | `/mcp add` | Interactive setup for adding a new server | | `/mcp edit ` | Edit an existing server configuration | | `/mcp enable ` | Enable a disabled server (persists across sessions) | diff --git a/06-mcp-servers/images/browser-extensions-analogy.png b/06-mcp-servers/assets/browser-extensions-analogy.png similarity index 100% rename from 06-mcp-servers/images/browser-extensions-analogy.png rename to 06-mcp-servers/assets/browser-extensions-analogy.png diff --git a/06-mcp-servers/images/chapter-header.png b/06-mcp-servers/assets/chapter-header.png similarity index 100% rename from 06-mcp-servers/images/chapter-header.png rename to 06-mcp-servers/assets/chapter-header.png diff --git a/06-mcp-servers/images/configuring-mcp-servers.png b/06-mcp-servers/assets/configuring-mcp-servers.png similarity index 100% rename from 06-mcp-servers/images/configuring-mcp-servers.png rename to 06-mcp-servers/assets/configuring-mcp-servers.png diff --git a/06-mcp-servers/images/issue-to-pr-workflow.png b/06-mcp-servers/assets/issue-to-pr-workflow.png similarity index 100% rename from 06-mcp-servers/images/issue-to-pr-workflow.png rename to 06-mcp-servers/assets/issue-to-pr-workflow.png diff --git a/06-mcp-servers/images/mcp-status-demo.gif b/06-mcp-servers/assets/mcp-status-demo.gif similarity index 100% rename from 06-mcp-servers/images/mcp-status-demo.gif rename to 06-mcp-servers/assets/mcp-status-demo.gif diff --git a/06-mcp-servers/images/mcp-status-demo.tape b/06-mcp-servers/assets/mcp-status-demo.tape similarity index 100% rename from 06-mcp-servers/images/mcp-status-demo.tape rename to 06-mcp-servers/assets/mcp-status-demo.tape diff --git a/06-mcp-servers/images/mcp-workflow-demo.gif b/06-mcp-servers/assets/mcp-workflow-demo.gif similarity index 100% rename from 06-mcp-servers/images/mcp-workflow-demo.gif rename to 06-mcp-servers/assets/mcp-workflow-demo.gif diff --git a/06-mcp-servers/images/mcp-workflow-demo.tape b/06-mcp-servers/assets/mcp-workflow-demo.tape similarity index 100% rename from 06-mcp-servers/images/mcp-workflow-demo.tape rename to 06-mcp-servers/assets/mcp-workflow-demo.tape diff --git a/06-mcp-servers/images/multi-server-workflow.png b/06-mcp-servers/assets/multi-server-workflow.png similarity index 100% rename from 06-mcp-servers/images/multi-server-workflow.png rename to 06-mcp-servers/assets/multi-server-workflow.png diff --git a/06-mcp-servers/images/quick-start-mcp.png b/06-mcp-servers/assets/quick-start-mcp.png similarity index 100% rename from 06-mcp-servers/images/quick-start-mcp.png rename to 06-mcp-servers/assets/quick-start-mcp.png diff --git a/06-mcp-servers/images/using-mcp-servers.png b/06-mcp-servers/assets/using-mcp-servers.png similarity index 100% rename from 06-mcp-servers/images/using-mcp-servers.png rename to 06-mcp-servers/assets/using-mcp-servers.png diff --git a/06-mcp-servers/mcp-custom-server.md b/06-mcp-servers/mcp-custom-server.md index 03166f6a..beb96668 100644 --- a/06-mcp-servers/mcp-custom-server.md +++ b/06-mcp-servers/mcp-custom-server.md @@ -1,3 +1,14 @@ + + # Building a Custom MCP Server > ⚠️ **This content is completely optional.** You can be highly productive with Copilot CLI using only the pre-built MCP servers (GitHub, filesystem, Context7). This guide is for developers who want to connect Copilot to custom internal APIs. See the [MCP for Beginners course](https://github.com/microsoft/mcp-for-beginners) for more details. diff --git a/07-putting-it-together/README.md b/07-putting-it-together/README.md index 2678d647..829c7999 100644 --- a/07-putting-it-together/README.md +++ b/07-putting-it-together/README.md @@ -1,4 +1,15 @@ -![Chapter 07: Putting It All Together](images/chapter-header.png) + + +![Chapter 07: Putting It All Together](assets/chapter-header.png) > **Everything you learned combines here. Go from idea to merged PR in a single session.** @@ -21,7 +32,7 @@ By the end of this chapter, you'll be able to: ## 🧩 Real-World Analogy: The Orchestra -Orchestra Analogy - Unified Workflow +Orchestra Analogy - Unified Workflow A symphony orchestra has many sections: - **Strings** provide the foundation (like your core workflows) @@ -109,7 +120,7 @@ copilot # Additional Workflows -People assembling a colorful giant jigsaw puzzle with gears, representing how agents, skills, and MCP combine into unified workflows +People assembling a colorful giant jigsaw puzzle with gears, representing how agents, skills, and MCP combine into unified workflows For power users who completed Chapters 04-06, these workflows show how agents, skills, and MCP multiply your effectiveness. @@ -117,7 +128,7 @@ For power users who completed Chapters 04-06, these workflows show how agents, s Here's the mental model for combining everything: -The Integration Pattern - A 4-phase workflow: Gather Context (MCP), Analyze and Plan (Agents), Execute (Skills + Manual), Complete (MCP) +The Integration Pattern - A 4-phase workflow: Gather Context (MCP), Analyze and Plan (Agents), Execute (Skills + Manual), Complete (MCP) --- @@ -375,7 +386,7 @@ For teams with existing CI/CD pipelines, you can automate Copilot reviews on eve # Practice -Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice +Warm desk setup with monitor showing code, lamp, coffee cup, and headphones ready for hands-on practice Put the complete workflow into practice. diff --git a/07-putting-it-together/images/chapter-header.png b/07-putting-it-together/assets/chapter-header.png similarity index 100% rename from 07-putting-it-together/images/chapter-header.png rename to 07-putting-it-together/assets/chapter-header.png diff --git a/07-putting-it-together/images/combined-workflows.png b/07-putting-it-together/assets/combined-workflows.png similarity index 100% rename from 07-putting-it-together/images/combined-workflows.png rename to 07-putting-it-together/assets/combined-workflows.png diff --git a/07-putting-it-together/images/integration-pattern.png b/07-putting-it-together/assets/integration-pattern.png similarity index 100% rename from 07-putting-it-together/images/integration-pattern.png rename to 07-putting-it-together/assets/integration-pattern.png diff --git a/07-putting-it-together/images/orchestra-analogy.png b/07-putting-it-together/assets/orchestra-analogy.png similarity index 100% rename from 07-putting-it-together/images/orchestra-analogy.png rename to 07-putting-it-together/assets/orchestra-analogy.png diff --git a/README.md b/README.md index 72bdc8e5..d6b8433d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,15 @@ -![GitHub Copilot CLI for Beginners](./images/copilot-banner.png) + + +![GitHub Copilot CLI for Beginners](./assets/copilot-banner.png) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)  [![Open project in GitHub Codespaces](https://img.shields.io/badge/Codespaces-Open-blue?style=flat-square&logo=github)](https://codespaces.new/github/copilot-cli-for-beginners?hide_repo_select=true&ref=main&quickstart=true)  @@ -54,7 +65,7 @@ This course focuses on **GitHub Copilot CLI**, bringing AI assistance directly t ## 📚 Course Structure -![GitHub Copilot CLI Learning Path](images/learning-path.png) +![GitHub Copilot CLI Learning Path](assets/learning-path.png) | Chapter | Title | What You'll Build | |:-------:|-------|-------------------| @@ -102,4 +113,3 @@ The **[GitHub Copilot CLI command reference](https://docs.github.com/en/copilot/ ## License This project is licensed under the terms of the MIT open source license. Please refer to the [LICENSE](./LICENSE) file for the full terms. - diff --git a/appendices/README.md b/appendices/README.md index 30b93f2c..0e016943 100644 --- a/appendices/README.md +++ b/appendices/README.md @@ -1,3 +1,14 @@ + + # Appendices These appendices cover additional topics that extend the core course content. They're optional reading for when you need these specific capabilities. diff --git a/appendices/additional-context.md b/appendices/additional-context.md index 55906f74..6f13e377 100644 --- a/appendices/additional-context.md +++ b/appendices/additional-context.md @@ -1,3 +1,14 @@ + + # Additional Context Features > 📖 **Prerequisite**: Complete [Chapter 02: Context and Conversations](../02-context-conversations/README.md) before reading this appendix. diff --git a/appendices/ci-cd-integration.md b/appendices/ci-cd-integration.md index 176bd717..921e2957 100644 --- a/appendices/ci-cd-integration.md +++ b/appendices/ci-cd-integration.md @@ -1,3 +1,14 @@ + + # CI/CD Integration > 📖 **Prerequisite**: Complete [Chapter 07: Putting It All Together](../07-putting-it-together/README.md) before reading this appendix. diff --git a/images/chapter-header-bg.png b/assets/chapter-header-bg.png similarity index 100% rename from images/chapter-header-bg.png rename to assets/chapter-header-bg.png diff --git a/images/copilot-banner.png b/assets/copilot-banner.png similarity index 100% rename from images/copilot-banner.png rename to assets/copilot-banner.png diff --git a/images/copilot-dev-days.png b/assets/copilot-dev-days.png similarity index 100% rename from images/copilot-dev-days.png rename to assets/copilot-dev-days.png diff --git a/images/github-skills-logo.png b/assets/github-skills-logo.png similarity index 100% rename from images/github-skills-logo.png rename to assets/github-skills-logo.png diff --git a/images/learning-path.png b/assets/learning-path.png similarity index 100% rename from images/learning-path.png rename to assets/learning-path.png diff --git a/images/mockup.png b/assets/mockup.png similarity index 100% rename from images/mockup.png rename to assets/mockup.png diff --git a/images/practice.png b/assets/practice.png similarity index 100% rename from images/practice.png rename to assets/practice.png diff --git a/images/qr.png b/assets/qr.png similarity index 100% rename from images/qr.png rename to assets/qr.png diff --git a/images/quick-reference-header.png b/assets/quick-reference-header.png similarity index 100% rename from images/quick-reference-header.png rename to assets/quick-reference-header.png diff --git a/images/screenshot.png b/assets/screenshot.png similarity index 100% rename from images/screenshot.png rename to assets/screenshot.png diff --git a/package.json b/package.json index 26a84cf4..10eff8eb 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "create:tapes": "node .github/scripts/create-tapes.js", "generate:vhs": "node .github/scripts/generate-demos.js", "verify:gifs": "node .github/scripts/verify-gifs.js", + "copy:content-engine": "node .github/scripts/copy-content-engine-files.js", "generate:demos": "npm run create:tapes && npm run generate:vhs && npm run verify:gifs", "release": "npm run generate:demos", "release:ci": "npm run generate:headers"