diff --git a/.github/workflows/cli-for-beginners-sync.lock.yml b/.github/workflows/cli-for-beginners-sync.lock.yml
new file mode 100644
index 000000000..fb0de6fe8
--- /dev/null
+++ b/.github/workflows/cli-for-beginners-sync.lock.yml
@@ -0,0 +1,1128 @@
+# ___ _ _
+# / _ \ | | (_)
+# | |_| | __ _ ___ _ __ | |_ _ ___
+# | _ |/ _` |/ _ \ '_ \| __| |/ __|
+# | | | | (_| | __/ | | | |_| | (__
+# \_| |_/\__, |\___|_| |_|\__|_|\___|
+# __/ |
+# _ _ |___/
+# | | | | / _| |
+# | | | | ___ _ __ _ __| |_| | _____ ____
+# | |/\| |/ _ \ '__| |/ /| _| |/ _ \ \ /\ / / ___|
+# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
+# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
+#
+# This file was automatically generated by gh-aw (v0.61.2). DO NOT EDIT.
+#
+# To update this file, edit the corresponding .md file and run:
+# gh aw compile
+# Not all edits will cause changes to this file.
+#
+# For more information: https://github.github.com/gh-aw/introduction/overview/
+#
+# Weekly check for updates to github/copilot-cli-for-beginners. Opens a PR to keep the Learning Hub mirror aligned when substantive upstream course changes are detected.
+#
+# gh-aw-metadata: {"schema_version":"v2","frontmatter_hash":"f5011093e1a9b8103cf0012fc0ffb7c07ac1b488a41dddcd55f0ce4ad1b6b16d","compiler_version":"v0.61.2","strict":true}
+
+name: "CLI for Beginners Content Sync"
+"on":
+ schedule:
+ - cron: "34 18 * * 5"
+ # Friendly format: weekly (scattered)
+ workflow_dispatch:
+
+permissions: {}
+
+concurrency:
+ group: "gh-aw-${{ github.workflow }}"
+
+run-name: "CLI for Beginners Content Sync"
+
+jobs:
+ activation:
+ runs-on: ubuntu-slim
+ permissions:
+ contents: read
+ outputs:
+ comment_id: ""
+ comment_repo: ""
+ lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
+ model: ${{ steps.generate_aw_info.outputs.model }}
+ secret_verification_result: ${{ steps.validate-secret.outputs.verification_result }}
+ steps:
+ - name: Setup Scripts
+ uses: github/gh-aw-actions/setup@71cfb3cbe2002225f9d5afa180669fff36b86ea2 # v0.61.2
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+ - name: Generate agentic run info
+ id: generate_aw_info
+ env:
+ GH_AW_INFO_ENGINE_ID: "copilot"
+ GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
+ GH_AW_INFO_VERSION: ""
+ GH_AW_INFO_AGENT_VERSION: "latest"
+ GH_AW_INFO_CLI_VERSION: "v0.61.2"
+ GH_AW_INFO_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ GH_AW_INFO_EXPERIMENTAL: "false"
+ GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
+ GH_AW_INFO_STAGED: "false"
+ GH_AW_INFO_ALLOWED_DOMAINS: '["defaults"]'
+ GH_AW_INFO_FIREWALL_ENABLED: "true"
+ GH_AW_INFO_AWF_VERSION: "v0.24.3"
+ GH_AW_INFO_AWMG_VERSION: ""
+ GH_AW_INFO_FIREWALL_TYPE: "squid"
+ GH_AW_COMPILED_STRICT: "true"
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
+ await main(core, context);
+ - name: Validate COPILOT_GITHUB_TOKEN secret
+ id: validate-secret
+ run: ${RUNNER_TEMP}/gh-aw/actions/validate_multi_secret.sh COPILOT_GITHUB_TOKEN 'GitHub Copilot CLI' https://github.github.com/gh-aw/reference/engines/#github-copilot-default
+ env:
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ - name: Checkout .github and .agents folders
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
+ sparse-checkout: |
+ .github
+ .agents
+ sparse-checkout-cone-mode: true
+ fetch-depth: 1
+ - name: Check workflow file timestamps
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_WORKFLOW_FILE: "cli-for-beginners-sync.lock.yml"
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_workflow_timestamp_api.cjs');
+ await main();
+ - name: Create prompt with built-in context
+ env:
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
+ GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
+ run: |
+ bash ${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh
+ {
+ cat << 'GH_AW_PROMPT_EOF'
+
+ GH_AW_PROMPT_EOF
+ cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
+ cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
+ cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
+ cat "${RUNNER_TEMP}/gh-aw/prompts/cache_memory_prompt.md"
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
+ cat << 'GH_AW_PROMPT_EOF'
+
+ Tools: create_pull_request, missing_tool, missing_data, noop
+ GH_AW_PROMPT_EOF
+ cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md"
+ cat << 'GH_AW_PROMPT_EOF'
+
+
+ The following GitHub context information is available for this workflow:
+ {{#if __GH_AW_GITHUB_ACTOR__ }}
+ - **actor**: __GH_AW_GITHUB_ACTOR__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_REPOSITORY__ }}
+ - **repository**: __GH_AW_GITHUB_REPOSITORY__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_WORKSPACE__ }}
+ - **workspace**: __GH_AW_GITHUB_WORKSPACE__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
+ - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
+ - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
+ - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
+ - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
+ {{/if}}
+ {{#if __GH_AW_GITHUB_RUN_ID__ }}
+ - **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
+ {{/if}}
+
+
+ GH_AW_PROMPT_EOF
+ cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
+ cat << 'GH_AW_PROMPT_EOF'
+
+ GH_AW_PROMPT_EOF
+ cat << 'GH_AW_PROMPT_EOF'
+ {{#runtime-import .github/workflows/cli-for-beginners-sync.md}}
+ GH_AW_PROMPT_EOF
+ } > "$GH_AW_PROMPT"
+ - name: Interpolate variables and render templates
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/interpolate_prompt.cjs');
+ await main();
+ - name: Substitute placeholders
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_ALLOWED_EXTENSIONS: ''
+ GH_AW_CACHE_DESCRIPTION: ''
+ GH_AW_CACHE_DIR: '/tmp/gh-aw/cache-memory/'
+ GH_AW_GITHUB_ACTOR: ${{ github.actor }}
+ GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
+ GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
+ GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
+ GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+
+ const substitutePlaceholders = require('${{ runner.temp }}/gh-aw/actions/substitute_placeholders.cjs');
+
+ // Call the substitution function
+ return await substitutePlaceholders({
+ file: process.env.GH_AW_PROMPT,
+ substitutions: {
+ GH_AW_ALLOWED_EXTENSIONS: process.env.GH_AW_ALLOWED_EXTENSIONS,
+ GH_AW_CACHE_DESCRIPTION: process.env.GH_AW_CACHE_DESCRIPTION,
+ GH_AW_CACHE_DIR: process.env.GH_AW_CACHE_DIR,
+ GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
+ GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
+ GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
+ GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
+ GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
+ GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
+ GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
+ GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE
+ }
+ });
+ - name: Validate prompt placeholders
+ env:
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/validate_prompt_placeholders.sh
+ - name: Print prompt
+ env:
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/print_prompt_summary.sh
+ - name: Upload activation artifact
+ if: success()
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ with:
+ name: activation
+ path: |
+ /tmp/gh-aw/aw_info.json
+ /tmp/gh-aw/aw-prompts/prompt.txt
+ retention-days: 1
+
+ agent:
+ needs: activation
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ concurrency:
+ group: "gh-aw-copilot-${{ github.workflow }}"
+ env:
+ DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
+ GH_AW_ASSETS_ALLOWED_EXTS: ""
+ GH_AW_ASSETS_BRANCH: ""
+ GH_AW_ASSETS_MAX_SIZE_KB: 0
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
+ GH_AW_WORKFLOW_ID_SANITIZED: cliforbeginnerssync
+ outputs:
+ checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
+ detection_conclusion: ${{ steps.detection_conclusion.outputs.conclusion }}
+ detection_success: ${{ steps.detection_conclusion.outputs.success }}
+ has_patch: ${{ steps.collect_output.outputs.has_patch }}
+ inference_access_error: ${{ steps.detect-inference-error.outputs.inference_access_error || 'false' }}
+ model: ${{ needs.activation.outputs.model }}
+ output: ${{ steps.collect_output.outputs.output }}
+ output_types: ${{ steps.collect_output.outputs.output_types }}
+ steps:
+ - name: Setup Scripts
+ uses: github/gh-aw-actions/setup@71cfb3cbe2002225f9d5afa180669fff36b86ea2 # v0.61.2
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+ - name: Set runtime paths
+ run: |
+ echo "GH_AW_SAFE_OUTPUTS=${RUNNER_TEMP}/gh-aw/safeoutputs/outputs.jsonl" >> "$GITHUB_ENV"
+ echo "GH_AW_SAFE_OUTPUTS_CONFIG_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" >> "$GITHUB_ENV"
+ echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json" >> "$GITHUB_ENV"
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
+ - name: Create gh-aw temp directory
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/create_gh_aw_tmp_dir.sh
+ - name: Configure gh CLI for GitHub Enterprise
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/configure_gh_for_ghe.sh
+ env:
+ GH_TOKEN: ${{ github.token }}
+ # Cache memory file share configuration from frontmatter processed below
+ - name: Create cache-memory directory
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/create_cache_memory_dir.sh
+ - name: Restore cache-memory file share data
+ uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
+ with:
+ key: memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
+ path: /tmp/gh-aw/cache-memory
+ restore-keys: |
+ memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-
+ - name: Configure Git credentials
+ env:
+ REPO_NAME: ${{ github.repository }}
+ SERVER_URL: ${{ github.server_url }}
+ run: |
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
+ git config --global user.name "github-actions[bot]"
+ git config --global am.keepcr true
+ # Re-authenticate git with GitHub token
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
+ git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
+ echo "Git configured with standard GitHub Actions identity"
+ - name: Checkout PR branch
+ id: checkout-pr
+ if: |
+ (github.event.pull_request) || (github.event.issue.pull_request)
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
+ await main();
+ - name: Install GitHub Copilot CLI
+ run: ${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh latest
+ env:
+ GH_HOST: github.com
+ - name: Install AWF binary
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/install_awf_binary.sh v0.24.3
+ - name: Determine automatic lockdown mode for GitHub MCP Server
+ id: determine-automatic-lockdown
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
+ GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
+ with:
+ script: |
+ const determineAutomaticLockdown = require('${{ runner.temp }}/gh-aw/actions/determine_automatic_lockdown.cjs');
+ await determineAutomaticLockdown(github, context, core);
+ - name: Download container images
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh ghcr.io/github/gh-aw-firewall/agent:0.24.3 ghcr.io/github/gh-aw-firewall/api-proxy:0.24.3 ghcr.io/github/gh-aw-firewall/squid:0.24.3 ghcr.io/github/gh-aw-mcpg:v0.1.18 ghcr.io/github/github-mcp-server:v0.32.0 node:lts-alpine
+ - name: Write Safe Outputs Config
+ run: |
+ mkdir -p ${RUNNER_TEMP}/gh-aw/safeoutputs
+ mkdir -p /tmp/gh-aw/safeoutputs
+ mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/config.json << 'GH_AW_SAFE_OUTPUTS_CONFIG_EOF'
+ {"create_pull_request":{"max":1,"title_prefix":"[bot] "},"missing_data":{},"missing_tool":{},"noop":{"max":1}}
+ GH_AW_SAFE_OUTPUTS_CONFIG_EOF
+ - name: Write Safe Outputs Tools
+ run: |
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/tools_meta.json << 'GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF'
+ {
+ "description_suffixes": {
+ "create_pull_request": " CONSTRAINTS: Maximum 1 pull request(s) can be created. Title will be prefixed with \"[bot] \". Labels [\"automated-update\" \"learning-hub\" \"cli-for-beginners\"] will be automatically added."
+ },
+ "repo_params": {},
+ "dynamic_tools": []
+ }
+ GH_AW_SAFE_OUTPUTS_TOOLS_META_EOF
+ cat > ${RUNNER_TEMP}/gh-aw/safeoutputs/validation.json << 'GH_AW_SAFE_OUTPUTS_VALIDATION_EOF'
+ {
+ "create_pull_request": {
+ "defaultMax": 1,
+ "fields": {
+ "body": {
+ "required": true,
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 65000
+ },
+ "branch": {
+ "required": true,
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 256
+ },
+ "draft": {
+ "type": "boolean"
+ },
+ "labels": {
+ "type": "array",
+ "itemType": "string",
+ "itemSanitize": true,
+ "itemMaxLength": 128
+ },
+ "repo": {
+ "type": "string",
+ "maxLength": 256
+ },
+ "title": {
+ "required": true,
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 128
+ }
+ }
+ },
+ "missing_data": {
+ "defaultMax": 20,
+ "fields": {
+ "alternatives": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 256
+ },
+ "context": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 256
+ },
+ "data_type": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 128
+ },
+ "reason": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 256
+ }
+ }
+ },
+ "missing_tool": {
+ "defaultMax": 20,
+ "fields": {
+ "alternatives": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 512
+ },
+ "reason": {
+ "required": true,
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 256
+ },
+ "tool": {
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 128
+ }
+ }
+ },
+ "noop": {
+ "defaultMax": 1,
+ "fields": {
+ "message": {
+ "required": true,
+ "type": "string",
+ "sanitize": true,
+ "maxLength": 65000
+ }
+ }
+ }
+ }
+ GH_AW_SAFE_OUTPUTS_VALIDATION_EOF
+ node ${RUNNER_TEMP}/gh-aw/actions/generate_safe_outputs_tools.cjs
+ - name: Generate Safe Outputs MCP Server Config
+ id: safe-outputs-config
+ run: |
+ # Generate a secure random API key (360 bits of entropy, 40+ chars)
+ # Mask immediately to prevent timing vulnerabilities
+ API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
+ echo "::add-mask::${API_KEY}"
+
+ PORT=3001
+
+ # Set outputs for next steps
+ {
+ echo "safe_outputs_api_key=${API_KEY}"
+ echo "safe_outputs_port=${PORT}"
+ } >> "$GITHUB_OUTPUT"
+
+ echo "Safe Outputs MCP server will run on port ${PORT}"
+
+ - name: Start Safe Outputs MCP HTTP Server
+ id: safe-outputs-start
+ env:
+ DEBUG: '*'
+ GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-config.outputs.safe_outputs_port }}
+ GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-config.outputs.safe_outputs_api_key }}
+ GH_AW_SAFE_OUTPUTS_TOOLS_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/tools.json
+ GH_AW_SAFE_OUTPUTS_CONFIG_PATH: ${{ runner.temp }}/gh-aw/safeoutputs/config.json
+ GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
+ run: |
+ # Environment variables are set above to prevent template injection
+ export DEBUG
+ export GH_AW_SAFE_OUTPUTS_PORT
+ export GH_AW_SAFE_OUTPUTS_API_KEY
+ export GH_AW_SAFE_OUTPUTS_TOOLS_PATH
+ export GH_AW_SAFE_OUTPUTS_CONFIG_PATH
+ export GH_AW_MCP_LOG_DIR
+
+ bash ${RUNNER_TEMP}/gh-aw/actions/start_safe_outputs_server.sh
+
+ - name: Start MCP Gateway
+ id: start-mcp-gateway
+ env:
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_SAFE_OUTPUTS_API_KEY: ${{ steps.safe-outputs-start.outputs.api_key }}
+ GH_AW_SAFE_OUTPUTS_PORT: ${{ steps.safe-outputs-start.outputs.port }}
+ GITHUB_MCP_GUARD_MIN_INTEGRITY: ${{ steps.determine-automatic-lockdown.outputs.min_integrity }}
+ GITHUB_MCP_GUARD_REPOS: ${{ steps.determine-automatic-lockdown.outputs.repos }}
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ run: |
+ set -eo pipefail
+ mkdir -p /tmp/gh-aw/mcp-config
+
+ # Export gateway environment variables for MCP config and gateway script
+ export MCP_GATEWAY_PORT="80"
+ export MCP_GATEWAY_DOMAIN="host.docker.internal"
+ MCP_GATEWAY_API_KEY=$(openssl rand -base64 45 | tr -d '/+=')
+ echo "::add-mask::${MCP_GATEWAY_API_KEY}"
+ export MCP_GATEWAY_API_KEY
+ export MCP_GATEWAY_PAYLOAD_DIR="/tmp/gh-aw/mcp-payloads"
+ mkdir -p "${MCP_GATEWAY_PAYLOAD_DIR}"
+ export MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD="524288"
+ export DEBUG="*"
+
+ export GH_AW_ENGINE="copilot"
+ export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.1.18'
+
+ mkdir -p /home/runner/.copilot
+ cat << GH_AW_MCP_CONFIG_EOF | bash ${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.sh
+ {
+ "mcpServers": {
+ "github": {
+ "type": "stdio",
+ "container": "ghcr.io/github/github-mcp-server:v0.32.0",
+ "env": {
+ "GITHUB_HOST": "\${GITHUB_SERVER_URL}",
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
+ "GITHUB_READ_ONLY": "1",
+ "GITHUB_TOOLSETS": "repos"
+ },
+ "guard-policies": {
+ "allow-only": {
+ "min-integrity": "$GITHUB_MCP_GUARD_MIN_INTEGRITY",
+ "repos": "$GITHUB_MCP_GUARD_REPOS"
+ }
+ }
+ },
+ "safeoutputs": {
+ "type": "http",
+ "url": "http://host.docker.internal:$GH_AW_SAFE_OUTPUTS_PORT",
+ "headers": {
+ "Authorization": "\${GH_AW_SAFE_OUTPUTS_API_KEY}"
+ },
+ "guard-policies": {
+ "write-sink": {
+ "accept": [
+ "*"
+ ]
+ }
+ }
+ }
+ },
+ "gateway": {
+ "port": $MCP_GATEWAY_PORT,
+ "domain": "${MCP_GATEWAY_DOMAIN}",
+ "apiKey": "${MCP_GATEWAY_API_KEY}",
+ "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
+ }
+ }
+ GH_AW_MCP_CONFIG_EOF
+ - name: Download activation artifact
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: activation
+ path: /tmp/gh-aw
+ - name: Clean git credentials
+ continue-on-error: true
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/clean_git_credentials.sh
+ - name: Execute GitHub Copilot CLI
+ id: agentic_execution
+ # Copilot CLI tool arguments (sorted):
+ timeout-minutes: 20
+ run: |
+ set -o pipefail
+ touch /tmp/gh-aw/agent-step-summary.md
+ # shellcheck disable=SC1003
+ sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.3 --skip-pull --enable-api-proxy \
+ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-all-tools --add-dir /tmp/gh-aw/cache-memory/ --allow-all-paths --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/agent-stdio.log
+ env:
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || '' }}
+ GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
+ GH_AW_PHASE: agent
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_VERSION: v0.61.2
+ GITHUB_API_URL: ${{ github.api_url }}
+ GITHUB_AW: true
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
+ GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ GITHUB_REF_NAME: ${{ github.ref_name }}
+ GITHUB_SERVER_URL: ${{ github.server_url }}
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
+ GITHUB_WORKSPACE: ${{ github.workspace }}
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
+ GIT_AUTHOR_NAME: github-actions[bot]
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
+ GIT_COMMITTER_NAME: github-actions[bot]
+ XDG_CONFIG_HOME: /home/runner
+ - name: Detect inference access error
+ id: detect-inference-error
+ if: always()
+ continue-on-error: true
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/detect_inference_access_error.sh
+ - name: Configure Git credentials
+ env:
+ REPO_NAME: ${{ github.repository }}
+ SERVER_URL: ${{ github.server_url }}
+ run: |
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
+ git config --global user.name "github-actions[bot]"
+ git config --global am.keepcr true
+ # Re-authenticate git with GitHub token
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
+ git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
+ echo "Git configured with standard GitHub Actions identity"
+ - name: Copy Copilot session state files to logs
+ if: always()
+ continue-on-error: true
+ run: |
+ # Copy Copilot session state files to logs folder for artifact collection
+ # This ensures they are in /tmp/gh-aw/ where secret redaction can scan them
+ SESSION_STATE_DIR="$HOME/.copilot/session-state"
+ LOGS_DIR="/tmp/gh-aw/sandbox/agent/logs"
+
+ if [ -d "$SESSION_STATE_DIR" ]; then
+ echo "Copying Copilot session state files from $SESSION_STATE_DIR to $LOGS_DIR"
+ mkdir -p "$LOGS_DIR"
+ cp -v "$SESSION_STATE_DIR"/*.jsonl "$LOGS_DIR/" 2>/dev/null || true
+ echo "Session state files copied successfully"
+ else
+ echo "No session-state directory found at $SESSION_STATE_DIR"
+ fi
+ - name: Stop MCP Gateway
+ if: always()
+ continue-on-error: true
+ env:
+ MCP_GATEWAY_PORT: ${{ steps.start-mcp-gateway.outputs.gateway-port }}
+ MCP_GATEWAY_API_KEY: ${{ steps.start-mcp-gateway.outputs.gateway-api-key }}
+ GATEWAY_PID: ${{ steps.start-mcp-gateway.outputs.gateway-pid }}
+ run: |
+ bash ${RUNNER_TEMP}/gh-aw/actions/stop_mcp_gateway.sh "$GATEWAY_PID"
+ - name: Redact secrets in logs
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
+ await main();
+ env:
+ GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN'
+ SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
+ SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
+ SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ - name: Append agent step summary
+ if: always()
+ run: bash ${RUNNER_TEMP}/gh-aw/actions/append_agent_step_summary.sh
+ - name: Copy Safe Outputs
+ if: always()
+ run: |
+ mkdir -p /tmp/gh-aw
+ cp "$GH_AW_SAFE_OUTPUTS" /tmp/gh-aw/safeoutputs.jsonl 2>/dev/null || true
+ - name: Ingest agent output
+ id: collect_output
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
+ GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
+ GITHUB_SERVER_URL: ${{ github.server_url }}
+ GITHUB_API_URL: ${{ github.api_url }}
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/collect_ndjson_output.cjs');
+ await main();
+ - name: Parse agent logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: /tmp/gh-aw/sandbox/agent/logs/
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_copilot_log.cjs');
+ await main();
+ - name: Parse MCP Gateway logs for step summary
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_mcp_gateway_log.cjs');
+ await main();
+ - name: Print firewall logs
+ if: always()
+ continue-on-error: true
+ env:
+ AWF_LOGS_DIR: /tmp/gh-aw/sandbox/firewall/logs
+ run: |
+ # Fix permissions on firewall logs so they can be uploaded as artifacts
+ # AWF runs with sudo, creating files owned by root
+ sudo chmod -R a+r /tmp/gh-aw/sandbox/firewall/logs 2>/dev/null || true
+ # Only run awf logs summary if awf command exists (it may not be installed if workflow failed before install step)
+ if command -v awf &> /dev/null; then
+ awf logs summary | tee -a "$GITHUB_STEP_SUMMARY"
+ else
+ echo 'AWF binary not installed, skipping firewall log summary'
+ fi
+ - name: Upload cache-memory data as artifact
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ if: always()
+ with:
+ name: cache-memory
+ path: /tmp/gh-aw/cache-memory
+ - name: Upload agent artifacts
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ with:
+ name: agent
+ path: |
+ /tmp/gh-aw/aw-prompts/prompt.txt
+ /tmp/gh-aw/sandbox/agent/logs/
+ /tmp/gh-aw/redacted-urls.log
+ /tmp/gh-aw/mcp-logs/
+ /tmp/gh-aw/sandbox/firewall/logs/
+ /tmp/gh-aw/agent-stdio.log
+ /tmp/gh-aw/agent/
+ /tmp/gh-aw/safeoutputs.jsonl
+ /tmp/gh-aw/agent_output.json
+ /tmp/gh-aw/aw-*.patch
+ if-no-files-found: ignore
+ # --- Threat Detection (inline) ---
+ - name: Check if detection needed
+ id: detection_guard
+ if: always()
+ env:
+ OUTPUT_TYPES: ${{ steps.collect_output.outputs.output_types }}
+ HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
+ run: |
+ if [[ -n "$OUTPUT_TYPES" || "$HAS_PATCH" == "true" ]]; then
+ echo "run_detection=true" >> "$GITHUB_OUTPUT"
+ echo "Detection will run: output_types=$OUTPUT_TYPES, has_patch=$HAS_PATCH"
+ else
+ echo "run_detection=false" >> "$GITHUB_OUTPUT"
+ echo "Detection skipped: no agent outputs or patches to analyze"
+ fi
+ - name: Clear MCP configuration for detection
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ run: |
+ rm -f /tmp/gh-aw/mcp-config/mcp-servers.json
+ rm -f /home/runner/.copilot/mcp-config.json
+ rm -f "$GITHUB_WORKSPACE/.gemini/settings.json"
+ - name: Prepare threat detection files
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ run: |
+ mkdir -p /tmp/gh-aw/threat-detection/aw-prompts
+ cp /tmp/gh-aw/aw-prompts/prompt.txt /tmp/gh-aw/threat-detection/aw-prompts/prompt.txt 2>/dev/null || true
+ cp /tmp/gh-aw/agent_output.json /tmp/gh-aw/threat-detection/agent_output.json 2>/dev/null || true
+ for f in /tmp/gh-aw/aw-*.patch; do
+ [ -f "$f" ] && cp "$f" /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ done
+ echo "Prepared threat detection files:"
+ ls -la /tmp/gh-aw/threat-detection/ 2>/dev/null || true
+ - name: Setup threat detection
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ WORKFLOW_DESCRIPTION: "Weekly check for updates to github/copilot-cli-for-beginners. Opens a PR to keep the Learning Hub mirror aligned when substantive upstream course changes are detected."
+ HAS_PATCH: ${{ steps.collect_output.outputs.has_patch }}
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/setup_threat_detection.cjs');
+ await main();
+ - name: Ensure threat-detection directory and log
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ run: |
+ mkdir -p /tmp/gh-aw/threat-detection
+ touch /tmp/gh-aw/threat-detection/detection.log
+ - name: Execute GitHub Copilot CLI
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ id: detection_agentic_execution
+ # Copilot CLI tool arguments (sorted):
+ # --allow-tool shell(cat)
+ # --allow-tool shell(grep)
+ # --allow-tool shell(head)
+ # --allow-tool shell(jq)
+ # --allow-tool shell(ls)
+ # --allow-tool shell(tail)
+ # --allow-tool shell(wc)
+ timeout-minutes: 20
+ run: |
+ set -o pipefail
+ touch /tmp/gh-aw/agent-step-summary.md
+ # shellcheck disable=SC1003
+ sudo -E awf --env-all --container-workdir "${GITHUB_WORKSPACE}" --mount "${RUNNER_TEMP}/gh-aw:${RUNNER_TEMP}/gh-aw:ro" --mount "${RUNNER_TEMP}/gh-aw:/host${RUNNER_TEMP}/gh-aw:ro" --allow-domains "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,github.com,host.docker.internal,raw.githubusercontent.com,registry.npmjs.org,telemetry.enterprise.githubcopilot.com" --log-level info --proxy-logs-dir /tmp/gh-aw/sandbox/firewall/logs --enable-host-access --image-tag 0.24.3 --skip-pull --enable-api-proxy \
+ -- /bin/bash -c '/usr/local/bin/copilot --add-dir /tmp/gh-aw/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --add-dir "${GITHUB_WORKSPACE}" --disable-builtin-mcps --allow-tool '\''shell(cat)'\'' --allow-tool '\''shell(grep)'\'' --allow-tool '\''shell(head)'\'' --allow-tool '\''shell(jq)'\'' --allow-tool '\''shell(ls)'\'' --allow-tool '\''shell(tail)'\'' --allow-tool '\''shell(wc)'\'' --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"' 2>&1 | tee -a /tmp/gh-aw/threat-detection/detection.log
+ env:
+ COPILOT_AGENT_RUNNER_TYPE: STANDALONE
+ COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ COPILOT_MODEL: ${{ vars.GH_AW_MODEL_DETECTION_COPILOT || '' }}
+ GH_AW_PHASE: detection
+ GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_VERSION: v0.61.2
+ GITHUB_API_URL: ${{ github.api_url }}
+ GITHUB_AW: true
+ GITHUB_HEAD_REF: ${{ github.head_ref }}
+ GITHUB_REF_NAME: ${{ github.ref_name }}
+ GITHUB_SERVER_URL: ${{ github.server_url }}
+ GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
+ GITHUB_WORKSPACE: ${{ github.workspace }}
+ GIT_AUTHOR_EMAIL: github-actions[bot]@users.noreply.github.com
+ GIT_AUTHOR_NAME: github-actions[bot]
+ GIT_COMMITTER_EMAIL: github-actions[bot]@users.noreply.github.com
+ GIT_COMMITTER_NAME: github-actions[bot]
+ XDG_CONFIG_HOME: /home/runner
+ - name: Parse threat detection results
+ id: parse_detection_results
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ with:
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/parse_threat_detection_results.cjs');
+ await main();
+ - name: Upload threat detection log
+ if: always() && steps.detection_guard.outputs.run_detection == 'true'
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ with:
+ name: detection
+ path: /tmp/gh-aw/threat-detection/detection.log
+ if-no-files-found: ignore
+ - name: Set detection conclusion
+ id: detection_conclusion
+ if: always()
+ env:
+ RUN_DETECTION: ${{ steps.detection_guard.outputs.run_detection }}
+ DETECTION_SUCCESS: ${{ steps.parse_detection_results.outputs.success }}
+ run: |
+ if [[ "$RUN_DETECTION" != "true" ]]; then
+ echo "conclusion=skipped" >> "$GITHUB_OUTPUT"
+ echo "success=true" >> "$GITHUB_OUTPUT"
+ echo "Detection was not needed, marking as skipped"
+ elif [[ "$DETECTION_SUCCESS" == "true" ]]; then
+ echo "conclusion=success" >> "$GITHUB_OUTPUT"
+ echo "success=true" >> "$GITHUB_OUTPUT"
+ echo "Detection passed successfully"
+ else
+ echo "conclusion=failure" >> "$GITHUB_OUTPUT"
+ echo "success=false" >> "$GITHUB_OUTPUT"
+ echo "Detection found issues"
+ fi
+
+ conclusion:
+ needs:
+ - activation
+ - agent
+ - safe_outputs
+ - update_cache_memory
+ if: (always()) && ((needs.agent.result != 'skipped') || (needs.activation.outputs.lockdown_check_failed == 'true'))
+ runs-on: ubuntu-slim
+ permissions:
+ contents: write
+ issues: write
+ pull-requests: write
+ concurrency:
+ group: "gh-aw-conclusion-cli-for-beginners-sync"
+ cancel-in-progress: false
+ outputs:
+ noop_message: ${{ steps.noop.outputs.noop_message }}
+ tools_reported: ${{ steps.missing_tool.outputs.tools_reported }}
+ total_count: ${{ steps.missing_tool.outputs.total_count }}
+ steps:
+ - name: Setup Scripts
+ uses: github/gh-aw-actions/setup@71cfb3cbe2002225f9d5afa180669fff36b86ea2 # v0.61.2
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+ - name: Download agent output artifact
+ id: download-agent-output
+ continue-on-error: true
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: agent
+ path: /tmp/gh-aw/
+ - name: Setup agent output environment variable
+ if: steps.download-agent-output.outcome == 'success'
+ run: |
+ mkdir -p /tmp/gh-aw/
+ find "/tmp/gh-aw/" -type f -print
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV"
+ - name: Process No-Op Messages
+ id: noop
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_NOOP_MAX: "1"
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/noop.cjs');
+ await main();
+ - name: Record Missing Tool
+ id: missing_tool
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/missing_tool.cjs');
+ await main();
+ - name: Handle Agent Failure
+ id: handle_agent_failure
+ if: always()
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
+ GH_AW_WORKFLOW_ID: "cli-for-beginners-sync"
+ GH_AW_SECRET_VERIFICATION_RESULT: ${{ needs.activation.outputs.secret_verification_result }}
+ GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
+ GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
+ GH_AW_CODE_PUSH_FAILURE_ERRORS: ${{ needs.safe_outputs.outputs.code_push_failure_errors }}
+ GH_AW_CODE_PUSH_FAILURE_COUNT: ${{ needs.safe_outputs.outputs.code_push_failure_count }}
+ GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
+ GH_AW_GROUP_REPORTS: "false"
+ GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
+ GH_AW_TIMEOUT_MINUTES: "20"
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_agent_failure.cjs');
+ await main();
+ - name: Handle No-Op Message
+ id: handle_noop_message
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
+ GH_AW_NOOP_MESSAGE: ${{ steps.noop.outputs.noop_message }}
+ GH_AW_NOOP_REPORT_AS_ISSUE: "true"
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_noop_message.cjs');
+ await main();
+ - name: Handle Create Pull Request Error
+ id: handle_create_pr_error
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/handle_create_pr_error.cjs');
+ await main();
+
+ safe_outputs:
+ needs:
+ - activation
+ - agent
+ if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (needs.agent.outputs.detection_success == 'true')
+ runs-on: ubuntu-slim
+ permissions:
+ contents: write
+ issues: write
+ pull-requests: write
+ timeout-minutes: 15
+ env:
+ GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/cli-for-beginners-sync"
+ GH_AW_ENGINE_ID: "copilot"
+ GH_AW_WORKFLOW_ID: "cli-for-beginners-sync"
+ GH_AW_WORKFLOW_NAME: "CLI for Beginners Content Sync"
+ outputs:
+ code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
+ code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
+ create_discussion_error_count: ${{ steps.process_safe_outputs.outputs.create_discussion_error_count }}
+ create_discussion_errors: ${{ steps.process_safe_outputs.outputs.create_discussion_errors }}
+ created_pr_number: ${{ steps.process_safe_outputs.outputs.created_pr_number }}
+ created_pr_url: ${{ steps.process_safe_outputs.outputs.created_pr_url }}
+ process_safe_outputs_processed_count: ${{ steps.process_safe_outputs.outputs.processed_count }}
+ process_safe_outputs_temporary_id_map: ${{ steps.process_safe_outputs.outputs.temporary_id_map }}
+ steps:
+ - name: Setup Scripts
+ uses: github/gh-aw-actions/setup@71cfb3cbe2002225f9d5afa180669fff36b86ea2 # v0.61.2
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+ - name: Download agent output artifact
+ id: download-agent-output
+ continue-on-error: true
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: agent
+ path: /tmp/gh-aw/
+ - name: Setup agent output environment variable
+ if: steps.download-agent-output.outcome == 'success'
+ run: |
+ mkdir -p /tmp/gh-aw/
+ find "/tmp/gh-aw/" -type f -print
+ echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_ENV"
+ - name: Download patch artifact
+ continue-on-error: true
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ with:
+ name: agent
+ path: /tmp/gh-aw/
+ - name: Checkout repository
+ if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ ref: ${{ github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }}
+ token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ persist-credentials: false
+ fetch-depth: 1
+ - name: Configure Git credentials
+ if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'create_pull_request'))
+ env:
+ REPO_NAME: ${{ github.repository }}
+ SERVER_URL: ${{ github.server_url }}
+ GIT_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ run: |
+ git config --global user.email "github-actions[bot]@users.noreply.github.com"
+ git config --global user.name "github-actions[bot]"
+ git config --global am.keepcr true
+ # Re-authenticate git with GitHub token
+ SERVER_URL_STRIPPED="${SERVER_URL#https://}"
+ git remote set-url origin "https://x-access-token:${GIT_TOKEN}@${SERVER_URL_STRIPPED}/${REPO_NAME}.git"
+ echo "Git configured with standard GitHub Actions identity"
+ - name: Configure GH_HOST for enterprise compatibility
+ shell: bash
+ run: |
+ # Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
+ # GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
+ GH_HOST="${GITHUB_SERVER_URL#https://}"
+ GH_HOST="${GH_HOST#http://}"
+ echo "GH_HOST=${GH_HOST}" >> "$GITHUB_ENV"
+ - name: Process Safe Outputs
+ id: process_safe_outputs
+ uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
+ env:
+ GH_AW_AGENT_OUTPUT: ${{ env.GH_AW_AGENT_OUTPUT }}
+ GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
+ GITHUB_SERVER_URL: ${{ github.server_url }}
+ GITHUB_API_URL: ${{ github.api_url }}
+ GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: "{\"create_pull_request\":{\"labels\":[\"automated-update\",\"learning-hub\",\"cli-for-beginners\"],\"max\":1,\"max_patch_size\":1024,\"protected_files\":[\"package.json\",\"bun.lockb\",\"bunfig.toml\",\"deno.json\",\"deno.jsonc\",\"deno.lock\",\"global.json\",\"NuGet.Config\",\"Directory.Packages.props\",\"mix.exs\",\"mix.lock\",\"go.mod\",\"go.sum\",\"stack.yaml\",\"stack.yaml.lock\",\"pom.xml\",\"build.gradle\",\"build.gradle.kts\",\"settings.gradle\",\"settings.gradle.kts\",\"gradle.properties\",\"package-lock.json\",\"yarn.lock\",\"pnpm-lock.yaml\",\"npm-shrinkwrap.json\",\"requirements.txt\",\"Pipfile\",\"Pipfile.lock\",\"pyproject.toml\",\"setup.py\",\"setup.cfg\",\"Gemfile\",\"Gemfile.lock\",\"uv.lock\",\"AGENTS.md\"],\"protected_path_prefixes\":[\".github/\",\".agents/\"],\"title_prefix\":\"[bot] \"},\"missing_data\":{},\"missing_tool\":{},\"noop\":{\"max\":1,\"report-as-issue\":\"true\"}}"
+ GH_AW_CI_TRIGGER_TOKEN: ${{ secrets.GH_AW_CI_TRIGGER_TOKEN }}
+ with:
+ github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/safe_output_handler_manager.cjs');
+ await main();
+ - name: Upload Safe Output Items Manifest
+ if: always()
+ uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
+ with:
+ name: safe-output-items
+ path: /tmp/safe-output-items.jsonl
+ if-no-files-found: warn
+
+ update_cache_memory:
+ needs: agent
+ if: always() && needs.agent.outputs.detection_success == 'true'
+ runs-on: ubuntu-latest
+ permissions: {}
+ env:
+ GH_AW_WORKFLOW_ID_SANITIZED: cliforbeginnerssync
+ steps:
+ - name: Setup Scripts
+ uses: github/gh-aw-actions/setup@71cfb3cbe2002225f9d5afa180669fff36b86ea2 # v0.61.2
+ with:
+ destination: ${{ runner.temp }}/gh-aw/actions
+ - name: Download cache-memory artifact (default)
+ id: download_cache_default
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
+ continue-on-error: true
+ with:
+ name: cache-memory
+ path: /tmp/gh-aw/cache-memory
+ - name: Check if cache-memory folder has content (default)
+ id: check_cache_default
+ shell: bash
+ run: |
+ if [ -d "/tmp/gh-aw/cache-memory" ] && [ "$(ls -A /tmp/gh-aw/cache-memory 2>/dev/null)" ]; then
+ echo "has_content=true" >> "$GITHUB_OUTPUT"
+ else
+ echo "has_content=false" >> "$GITHUB_OUTPUT"
+ fi
+ - name: Save cache-memory to cache (default)
+ if: steps.check_cache_default.outputs.has_content == 'true'
+ uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
+ with:
+ key: memory-${{ env.GH_AW_WORKFLOW_ID_SANITIZED }}-${{ github.run_id }}
+ path: /tmp/gh-aw/cache-memory
+
diff --git a/.github/workflows/cli-for-beginners-sync.md b/.github/workflows/cli-for-beginners-sync.md
new file mode 100644
index 000000000..79406a7a1
--- /dev/null
+++ b/.github/workflows/cli-for-beginners-sync.md
@@ -0,0 +1,135 @@
+---
+name: "CLI for Beginners Content Sync"
+description: "Weekly check for updates to github/copilot-cli-for-beginners. Opens a PR to keep the Learning Hub mirror aligned when substantive upstream course changes are detected."
+on:
+ schedule: weekly
+permissions:
+ contents: read
+tools:
+ github:
+ toolsets: [repos]
+ cache-memory: true
+safe-outputs:
+ create-pull-request:
+ labels: [automated-update, learning-hub, cli-for-beginners]
+ title-prefix: "[bot] "
+---
+
+# CLI for Beginners Content Sync
+
+You are a documentation sync agent for the **awesome-copilot** Learning Hub. Your job is to check whether the upstream source repository [`github/copilot-cli-for-beginners`](https://github.com/github/copilot-cli-for-beginners) has received any meaningful updates since your last run, and — if it has — update the Learning Hub mirror so it stays aligned with the upstream course.
+
+## Step 1 — Determine what's new in the upstream repo
+
+1. Read `cache-memory` and look for a file named `cli-for-beginners-sync-state.json`. It may contain:
+ - `last_synced_sha` — the most recent commit SHA you processed on your previous run
+ - `last_synced_at` — a filesystem-safe timestamp in the format `YYYY-MM-DD-HH-MM-SS`
+
+2. Use GitHub tools to fetch recent commits from `github/copilot-cli-for-beginners` (default branch):
+ - If `last_synced_sha` exists, list commits **since that SHA** (stop once you reach it).
+ - If no cached state exists, list commits from the **past 7 days**.
+
+3. Identify which files changed across those commits. Focus on:
+ - Markdown files (`*.md`) — course content, README, module descriptions
+ - Supporting assets referenced by the course material, especially screenshots and GIFs
+ - Any configuration or metadata files that materially affect the course content or navigation
+
+4. If **no commits** were found since the last sync, stop here and call the `noop` safe output with a message like: "No new commits found in `github/copilot-cli-for-beginners` since last sync (``). No action needed." Then update the cache with the latest SHA.
+
+## Step 2 — Read the changed upstream content
+
+For each file that changed in the upstream repo, use GitHub tools to fetch the **current file contents** from `github/copilot-cli-for-beginners`. Pay close attention to:
+
+- New sections, commands, flags, or concepts introduced
+- Renamed or restructured sections
+- Deprecated commands or workflows that have been removed
+- Updated screenshots, GIFs, image references, or code examples
+- Links to new official documentation or resources
+
+## Step 3 — Compare against the local Learning Hub content
+
+Read the local files in the canonical Learning Hub course folder `website/src/content/docs/learning-hub/cli-for-beginners/`:
+
+```
+website/src/content/docs/learning-hub/cli-for-beginners/
+├── index.md
+├── 00-quick-start.md
+├── 01-setup-and-first-steps.md
+├── 02-context-and-conversations.md
+├── 03-development-workflows.md
+├── 04-agents-and-custom-instructions.md
+├── 05-skills.md
+├── 06-mcp-servers.md
+└── 07-putting-it-all-together.md
+```
+
+Also inspect local course assets in `website/public/images/learning-hub/copilot-cli-for-beginners/` when upstream changes touch screenshots, banners, or GIFs.
+
+If the upstream changes alter course structure or navigation, you may also need to inspect:
+
+- `website/astro.config.mjs`
+- `website/src/content/docs/learning-hub/index.md`
+
+Map the upstream changes to the relevant local file(s). Ask yourself:
+
+- Is the local mirror missing any upstream content, structure, assignments, examples, or visuals?
+- Is any existing Learning Hub content now outdated or incorrect based on upstream changes?
+- Do local route rewrites, repo-link rewrites, or asset paths need updating so the mirrored pages still work on the website?
+- Do the Astro frontmatter fields (especially `lastUpdated`) need updating because the mirrored page changed?
+
+If the local content is already fully consistent with the upstream changes — or the upstream changes are non-substantive (e.g., only CI config, typo fixes, or internal tooling changes) — stop here and call the `noop` safe output with a brief explanation. Still update the cache with the latest commit SHA.
+
+## Step 4 — Update the Learning Hub files
+
+For each local file that needs updating:
+
+1. Edit the relevant local docs, assets, and supporting navigation files so the website remains a **source-faithful mirror** of the upstream course:
+ - Add or update missing concepts, commands, flags, steps, assignments, demos, and visuals
+ - Correct or remove outdated information
+ - Localize newly added screenshots or GIFs into `website/public/images/learning-hub/copilot-cli-for-beginners/`
+ - Bump the `lastUpdated` frontmatter field to today's date (`YYYY-MM-DD`) for any page whose mirrored content changed
+
+2. Keep a **mirror-first** approach:
+ - Preserve upstream wording, headings, section order, assignments, and overall chapter flow as closely as practical
+ - Do not summarize, reinterpret, or "website-optimize" the course into a different learning experience
+ - Only adapt what the website requires: Astro frontmatter, route-safe internal links, GitHub repo links, local asset paths, and minor HTML/CSS hooks needed for presentation
+
+3. If upstream adds, removes, or renames major sections or chapters:
+ - Create, delete, or rename the corresponding markdown files in `website/src/content/docs/learning-hub/cli-for-beginners/`
+ - Update `website/astro.config.mjs` if the sidebar chapter list must change
+ - Update `website/src/content/docs/learning-hub/index.md` only if the landing page's course entry must change
+
+## Step 5 — Update the sync state cache
+
+Before opening the PR, write an updated `cli-for-beginners-sync-state.json` to `cache-memory` with:
+
+```json
+{
+ "last_synced_sha": "",
+ "last_synced_at": "",
+ "files_reviewed": [""],
+ "files_updated": [""]
+}
+```
+
+## Step 6 — Open a pull request
+
+Create a pull request with your changes using the `create-pull-request` safe output. The PR body must include:
+
+1. **What changed upstream** — a concise summary of the commits and file changes found in `github/copilot-cli-for-beginners`
+2. **What was updated locally** — list each mirrored Learning Hub file or asset you edited and what changed
+3. **Source links** — links to the relevant upstream commits or files
+4. A note that the markdown body of this workflow can be edited directly on GitHub.com without recompilation
+
+If there is nothing to change after your analysis, do **not** open a PR. Instead, call the `noop` safe output.
+
+## Guidelines
+
+- The canonical course content lives in `website/src/content/docs/learning-hub/cli-for-beginners/`; do not recreate legacy duplicates elsewhere
+- Prefer changes within the course docs and `website/public/images/learning-hub/copilot-cli-for-beginners/`
+- Only edit `website/astro.config.mjs` or `website/src/content/docs/learning-hub/index.md` when upstream course structure or navigation truly requires it
+- Preserve existing frontmatter fields; only update `lastUpdated` and `description` if genuinely warranted
+- Keep the course source-faithful; avoid summaries or interpretive rewrites
+- Do not auto-merge; the PR is for human review
+- If you are uncertain whether an upstream change warrants a Learning Hub update, err on the side of creating the PR — a human reviewer can always decline
+- Always call either `create-pull-request` or `noop` at the end of your run so the workflow clearly signals its outcome
diff --git a/CODEOWNERS b/CODEOWNERS
index 811048c94..cc3e8ce25 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,6 +1,10 @@
# Default owner for everything
* @aaronpowell
+# Adding Dan Wahlin as the owner for the CLI for Beginners content and images
+/website/src/content/docs/learning-hub/cli-for-beginners/ @DanWahlin
+/website/src/images/cli-for-beginners/ @DanWahlin
+
# Agentic Workflows
/workflows/ @brunoborges
/.github/workflows/validate-agentic-workflows-pr.yml @brunoborges
diff --git a/website/astro.config.mjs b/website/astro.config.mjs
index cc2c8e46f..aa0f74eac 100644
--- a/website/astro.config.mjs
+++ b/website/astro.config.mjs
@@ -88,6 +88,23 @@ export default defineConfig({
label: "Reference",
items: ["learning-hub/github-copilot-terminology-glossary"],
},
+ {
+ label: "Copilot CLI for Beginners",
+ items: [
+ {
+ label: "Overview",
+ link: "/learning-hub/cli-for-beginners/",
+ },
+ "learning-hub/cli-for-beginners/00-quick-start",
+ "learning-hub/cli-for-beginners/01-setup-and-first-steps",
+ "learning-hub/cli-for-beginners/02-context-and-conversations",
+ "learning-hub/cli-for-beginners/03-development-workflows",
+ "learning-hub/cli-for-beginners/04-agents-and-custom-instructions",
+ "learning-hub/cli-for-beginners/05-skills",
+ "learning-hub/cli-for-beginners/06-mcp-servers",
+ "learning-hub/cli-for-beginners/07-putting-it-all-together",
+ ],
+ },
{
label: "Hands-on",
items: [
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/00/auth-device-flow.png b/website/public/images/learning-hub/copilot-cli-for-beginners/00/auth-device-flow.png
new file mode 100644
index 000000000..1aeb9dee9
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/00/auth-device-flow.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/00/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/00/chapter-header.png
new file mode 100644
index 000000000..13bc3b0e7
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/00/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/00/copilot-trust.png b/website/public/images/learning-hub/copilot-cli-for-beginners/00/copilot-trust.png
new file mode 100644
index 000000000..64249f5cc
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/00/copilot-trust.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/00/hello-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/00/hello-demo.gif
new file mode 100644
index 000000000..fbbeca80b
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/00/hello-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/chapter-header.png
new file mode 100644
index 000000000..9348f65d8
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/code-review-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/01/code-review-demo.gif
new file mode 100644
index 000000000..a64139e3d
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/code-review-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/explain-code-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/01/explain-code-demo.gif
new file mode 100644
index 000000000..956f4b95d
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/explain-code-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/first-copilot-experience.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/first-copilot-experience.png
new file mode 100644
index 000000000..f650bb4fe
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/first-copilot-experience.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/generate-code-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/01/generate-code-demo.gif
new file mode 100644
index 000000000..fe4d32640
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/generate-code-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/interactive-mode.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/interactive-mode.png
new file mode 100644
index 000000000..79c45f6c6
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/interactive-mode.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/modes-and-commands.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/modes-and-commands.png
new file mode 100644
index 000000000..6f218e650
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/modes-and-commands.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/ordering-food-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/ordering-food-analogy.png
new file mode 100644
index 000000000..65afc1370
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/ordering-food-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/plan-mode.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/plan-mode.png
new file mode 100644
index 000000000..ff7a04df5
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/plan-mode.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/01/programmatic-mode.png b/website/public/images/learning-hub/copilot-cli-for-beginners/01/programmatic-mode.png
new file mode 100644
index 000000000..1559c22a3
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/01/programmatic-mode.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/chapter-header.png
new file mode 100644
index 000000000..e68561e3e
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/codebase-understanding.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/codebase-understanding.png
new file mode 100644
index 000000000..bf2acbda5
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/codebase-understanding.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/colleague-context-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/colleague-context-analogy.png
new file mode 100644
index 000000000..b831a28ef
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/colleague-context-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/context-window-visualization.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/context-window-visualization.png
new file mode 100644
index 000000000..aac26282c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/context-window-visualization.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/cross-file-intelligence.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/cross-file-intelligence.png
new file mode 100644
index 000000000..86c57a560
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/cross-file-intelligence.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/essential-basic-context.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/essential-basic-context.png
new file mode 100644
index 000000000..827cc98eb
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/essential-basic-context.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/file-context-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/02/file-context-demo.gif
new file mode 100644
index 000000000..00b170160
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/file-context-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-file-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-file-demo.gif
new file mode 100644
index 000000000..c0cefe50c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-file-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-turn-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-turn-demo.gif
new file mode 100644
index 000000000..78e4a407c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/multi-turn-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/optional-going-deeper.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/optional-going-deeper.png
new file mode 100644
index 000000000..cfec09cd9
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/optional-going-deeper.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/02/session-persistence-timeline.png b/website/public/images/learning-hub/copilot-cli-for-beginners/02/session-persistence-timeline.png
new file mode 100644
index 000000000..a15c30e5c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/02/session-persistence-timeline.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/carpenter-workflow-steps.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/carpenter-workflow-steps.png
new file mode 100644
index 000000000..bdcd51ffe
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/carpenter-workflow-steps.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/chapter-header.png
new file mode 100644
index 000000000..031d5726c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-demo.gif
new file mode 100644
index 000000000..0d89dd547
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-swimlane-single.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-swimlane-single.png
new file mode 100644
index 000000000..0d74b8ee9
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/code-review-swimlane-single.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/debugging-swimlane-single.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/debugging-swimlane-single.png
new file mode 100644
index 000000000..433fb263e
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/debugging-swimlane-single.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows-swimlane.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows-swimlane.png
new file mode 100644
index 000000000..269938132
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows-swimlane.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows.png
new file mode 100644
index 000000000..463107502
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/five-workflows.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/fix-bug-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/03/fix-bug-demo.gif
new file mode 100644
index 000000000..535b49986
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/fix-bug-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-demo.gif
new file mode 100644
index 000000000..730bdffbf
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-swimlane-single.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-swimlane-single.png
new file mode 100644
index 000000000..cf2094b69
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/git-integration-swimlane-single.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/github-skills-logo.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/github-skills-logo.png
new file mode 100644
index 000000000..161ee9024
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/github-skills-logo.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactor-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactor-demo.gif
new file mode 100644
index 000000000..61ddd9ac0
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactor-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactoring-swimlane-single.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactoring-swimlane-single.png
new file mode 100644
index 000000000..ff69440bd
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/refactoring-swimlane-single.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/specialized-workflows.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/specialized-workflows.png
new file mode 100644
index 000000000..277ae686b
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/specialized-workflows.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-demo.gif
new file mode 100644
index 000000000..9042ea128
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-swimlane-single.png b/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-swimlane-single.png
new file mode 100644
index 000000000..1438b656c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/03/test-gen-swimlane-single.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/agent-file-placement-decision-tree.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/agent-file-placement-decision-tree.png
new file mode 100644
index 000000000..514cb30e8
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/agent-file-placement-decision-tree.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/chapter-header.png
new file mode 100644
index 000000000..d964b2d74
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/creating-custom-agents.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/creating-custom-agents.png
new file mode 100644
index 000000000..ce82166ed
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/creating-custom-agents.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/hiring-specialists-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/hiring-specialists-analogy.png
new file mode 100644
index 000000000..a82848c1a
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/hiring-specialists-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/python-reviewer-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/04/python-reviewer-demo.gif
new file mode 100644
index 000000000..49d8805dd
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/python-reviewer-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/04/using-agents.png b/website/public/images/learning-hub/copilot-cli-for-beginners/04/using-agents.png
new file mode 100644
index 000000000..d48515c18
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/04/using-agents.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/chapter-header.png
new file mode 100644
index 000000000..0484fb4b9
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/creating-managing-skills.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/creating-managing-skills.png
new file mode 100644
index 000000000..166f7f615
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/creating-managing-skills.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/how-skills-work.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/how-skills-work.png
new file mode 100644
index 000000000..762d2f588
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/how-skills-work.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/list-skills-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/05/list-skills-demo.gif
new file mode 100644
index 000000000..6f3f09fe8
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/list-skills-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/managing-sharing-skills.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/managing-sharing-skills.png
new file mode 100644
index 000000000..4ab492bc3
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/managing-sharing-skills.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/power-tools-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/power-tools-analogy.png
new file mode 100644
index 000000000..a442024de
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/power-tools-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-auto-discovery-flow.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-auto-discovery-flow.png
new file mode 100644
index 000000000..326bae62c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-auto-discovery-flow.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-trigger-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-trigger-demo.gif
new file mode 100644
index 000000000..0035e2ed7
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skill-trigger-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/05/skills-agents-mcp-comparison.png b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skills-agents-mcp-comparison.png
new file mode 100644
index 000000000..a7a7c8efe
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/05/skills-agents-mcp-comparison.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/browser-extensions-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/browser-extensions-analogy.png
new file mode 100644
index 000000000..244888031
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/browser-extensions-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/chapter-header.png
new file mode 100644
index 000000000..fe1be0fa6
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/configuring-mcp-servers.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/configuring-mcp-servers.png
new file mode 100644
index 000000000..2cb41924b
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/configuring-mcp-servers.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/issue-to-pr-workflow.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/issue-to-pr-workflow.png
new file mode 100644
index 000000000..b1b4d4dab
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/issue-to-pr-workflow.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-status-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-status-demo.gif
new file mode 100644
index 000000000..81fe7c7a0
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-status-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-workflow-demo.gif b/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-workflow-demo.gif
new file mode 100644
index 000000000..aec536abc
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/mcp-workflow-demo.gif differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/multi-server-workflow.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/multi-server-workflow.png
new file mode 100644
index 000000000..b841de85d
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/multi-server-workflow.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/quick-start-mcp.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/quick-start-mcp.png
new file mode 100644
index 000000000..b50a2abce
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/quick-start-mcp.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/06/using-mcp-servers.png b/website/public/images/learning-hub/copilot-cli-for-beginners/06/using-mcp-servers.png
new file mode 100644
index 000000000..bc4d5d814
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/06/using-mcp-servers.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/07/chapter-header.png b/website/public/images/learning-hub/copilot-cli-for-beginners/07/chapter-header.png
new file mode 100644
index 000000000..ce35ccb79
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/07/chapter-header.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/07/combined-workflows.png b/website/public/images/learning-hub/copilot-cli-for-beginners/07/combined-workflows.png
new file mode 100644
index 000000000..1cd330a89
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/07/combined-workflows.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/07/integration-pattern.png b/website/public/images/learning-hub/copilot-cli-for-beginners/07/integration-pattern.png
new file mode 100644
index 000000000..774c8505f
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/07/integration-pattern.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/07/orchestra-analogy.png b/website/public/images/learning-hub/copilot-cli-for-beginners/07/orchestra-analogy.png
new file mode 100644
index 000000000..e6102b84a
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/07/orchestra-analogy.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/07/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/07/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/07/practice.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-banner.png b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-banner.png
new file mode 100644
index 000000000..1a37e8ffc
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-banner.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-dev-days.png b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-dev-days.png
new file mode 100644
index 000000000..3f1ef1360
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/copilot-dev-days.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/overview/github-skills-logo.png b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/github-skills-logo.png
new file mode 100644
index 000000000..161ee9024
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/github-skills-logo.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/overview/learning-path.png b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/learning-path.png
new file mode 100644
index 000000000..eed22bdd8
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/learning-path.png differ
diff --git a/website/public/images/learning-hub/copilot-cli-for-beginners/overview/practice.png b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/practice.png
new file mode 100644
index 000000000..9a19f469c
Binary files /dev/null and b/website/public/images/learning-hub/copilot-cli-for-beginners/overview/practice.png differ
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/00-quick-start.md b/website/src/content/docs/learning-hub/cli-for-beginners/00-quick-start.md
new file mode 100644
index 000000000..bb88aa905
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/00-quick-start.md
@@ -0,0 +1,268 @@
+---
+title: '00 · Quick Start'
+description: 'Install GitHub Copilot CLI, authenticate, and verify your environment with the same flow as the source course.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+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!
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll have:
+
+- Installed GitHub Copilot CLI
+- Signed in with your GitHub account
+- Verified it works with a simple test
+
+> ⏱️ **Estimated Time**: ~10 minutes (5 min reading + 5 min hands-on)
+
+---
+
+## ✅ Prerequisites
+
+- **GitHub Account** with Copilot access. [See subscription options](https://github.com/features/copilot/plans). Students/Teachers can access Copilot Pro for [free via GitHub Education](https://education.github.com/pack).
+- **Terminal basics**: Comfortable with commands like `cd` and `ls`
+
+### What "Copilot Access" Means
+
+GitHub Copilot CLI requires an active Copilot subscription. You can check your status at [github.com/settings/copilot](https://github.com/settings/copilot). You should see one of:
+
+- **Copilot Individual** - Personal subscription
+- **Copilot Business** - Through your organization
+- **Copilot Enterprise** - Through your enterprise
+- **GitHub Education** - Free for verified students/teachers
+
+If you see "You don't have access to GitHub Copilot," you'll need to use the free option, subscribe to a plan, or join an organization that provides access.
+
+---
+
+## Installation
+
+> ⏱️ **Time estimate**: Installation takes 2-5 minutes. Authentication adds another 1-2 minutes.
+
+### Recommended: GitHub Codespaces (Zero Setup)
+
+If you don't want to install any of the prerequisites, you can use GitHub Codespaces, which has the GitHub Copilot CLI ready to go (you'll need to sign in), pre-installs Python 3.13, pytest, and the GitHub CLI.
+
+1. [Fork this repository](https://github.com/github/copilot-cli-for-beginners/fork) to your GitHub account
+2. Select **Code** > **Codespaces** > **Create codespace on main**
+3. Wait a few minutes for the container to build
+4. You're ready to go! The terminal will open automatically in the Codespace environment.
+
+> 💡 **Verify in Codespace**: Run `cd samples/book-app-project && python book_app.py help` to confirm Python and the sample app are working.
+
+### Alternative: Local Installation
+
+> 💡 **Not sure which to pick?** Use `npm` if you have Node.js installed. Otherwise, choose the option that matches your system.
+
+> 💡 **Python required for demos**: The course uses a Python sample app. If you're working locally, install [Python 3.10+](https://www.python.org/downloads/) before starting the demos.
+
+> **Note:** While the primary examples shown throughout the course use Python (`samples/book-app-project`), JavaScript (`samples/book-app-project-js`) and C# (`samples/book-app-project-cs`) versions are also available if you prefer to work with those languages. Each sample has a README with instructions for running the app in that language.
+
+Choose the method that works for your system:
+
+### All Platforms (npm)
+
+```bash
+# If you have Node.js installed, this is a quick way to get the CLI
+npm install -g @github/copilot
+```
+
+### macOS/Linux (Homebrew)
+
+```bash
+brew install copilot-cli
+```
+
+### Windows (WinGet)
+
+```bash
+winget install GitHub.Copilot
+```
+
+### macOS/Linux (Install Script)
+
+```bash
+curl -fsSL https://gh.io/copilot-install | bash
+```
+
+---
+
+## Authentication
+
+Open a terminal window at the root of the `copilot-cli-for-beginners` repository, start the CLI and allow access to the folder.
+
+```bash
+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.
+
+
+
+After trusting the folder, you can sign in with your GitHub account.
+
+```
+> /login
+```
+
+**What happens next:**
+
+1. Copilot CLI displays a one-time code (like `ABCD-1234`)
+2. Your browser opens to GitHub's device authorization page. Sign in to GitHub if you haven't already.
+3. Enter the code when prompted
+4. Select "Authorize" to grant GitHub Copilot CLI access
+5. Return to your terminal - you're now signed in!
+
+
+
+*The device authorization flow: your terminal generates a code, you verify it in the browser, and Copilot CLI is authenticated.*
+
+**Tip**: The sign-in persists across sessions. You only need to do this once unless your token expires or you explicitly sign out.
+
+---
+
+## Verify It Works
+
+### Step 1: Test Copilot CLI
+
+Now that you're signed in, let's verify that Copilot CLI is working for you. In the terminal, start the CLI if you haven't already:
+
+```bash
+> Say hello and tell me what you can help with
+```
+
+After you receive a response, you can exit the CLI:
+
+```bash
+> /exit
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**Expected output**: A friendly response listing Copilot CLI's capabilities.
+
+### Step 2: Run the Sample Book App
+
+The course provides a sample app that you'll explore and improve throughout the course using the CLI *(You can see the code for this in /samples/book-app-project)*. Check that the *Python book collection terminal app* works before you get started. Run `python` or `python3` depending on your system.
+
+> **Note:** While the primary examples shown throughout the course use Python (`samples/book-app-project`), JavaScript (`samples/book-app-project-js`) and C# (`samples/book-app-project-cs`) versions are also available if you prefer to work with those languages. Each sample has a README with instructions for running the app in that language.
+
+```bash
+cd samples/book-app-project
+python book_app.py list
+```
+
+**Expected output**: A list of 5 books including "The Hobbit", "1984", and "Dune".
+
+### Step 3: Try Copilot CLI with the Book App
+
+Navigate back to the repository root first (if you ran Step 2):
+
+```bash
+cd ../.. # Back to the repository root if needed
+copilot
+> What does @samples/book-app-project/book_app.py do?
+```
+
+**Expected output**: A summary of the book app's main functions and commands.
+
+If you see an error, check the [troubleshooting section](#troubleshooting) below.
+
+Once you're done you can exit the Copilot CLI:
+
+```bash
+> /exit
+```
+
+---
+
+## ✅ You're Ready!
+
+That's it for installation. The real fun starts in Chapter 01, where you'll:
+
+- Watch AI review the book app and find code quality issues instantly
+- Learn three different ways to use Copilot CLI
+- Generate working code from plain English
+
+**[Continue to Chapter 01: First Steps →](../01-setup-and-first-steps/)**
+
+---
+
+## Troubleshooting
+
+### "copilot: command not found"
+
+The CLI isn't installed. Try a different installation method:
+
+```bash
+# If brew failed, try npm:
+npm install -g @github/copilot
+
+# Or the install script:
+curl -fsSL https://gh.io/copilot-install | bash
+```
+
+### "You don't have access to GitHub Copilot"
+
+1. Verify you have a Copilot subscription at [github.com/settings/copilot](https://github.com/settings/copilot)
+2. Check that your organization permits CLI access if using a work account
+
+### "Authentication failed"
+
+Re-authenticate:
+
+```bash
+copilot
+> /login
+```
+
+### Browser doesn't open automatically
+
+Manually visit [github.com/login/device](https://github.com/login/device) and enter the code shown in your terminal.
+
+### Token expired
+
+Simply run `/login` again:
+
+```bash
+copilot
+> /login
+```
+
+### Still stuck?
+
+- Check the [GitHub Copilot CLI documentation](https://docs.github.com/copilot/concepts/agents/about-copilot-cli)
+- Search [GitHub Issues](https://github.com/github/copilot-cli/issues)
+
+---
+
+## 🔑 Key Takeaways
+
+1. **A GitHub Codespace is a quick way to get started** - Python, pytest, and GitHub Copilot CLI are all pre-installed so you can jump right into the demos
+2. **Multiple installation methods** - Choose what works for your system (Homebrew, WinGet, npm, or install script)
+3. **One-time authentication** - Login persists until token expires
+4. **The book app works** - You'll use `samples/book-app-project` throughout the entire course
+
+> 📚 **Official Documentation**: [Install Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-cli/cli-getting-started) for installation options and requirements.
+
+> 📋 **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.
+
+---
+
+**[Continue to Chapter 01: First Steps →](../01-setup-and-first-steps/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/01-setup-and-first-steps.md b/website/src/content/docs/learning-hub/cli-for-beginners/01-setup-and-first-steps.md
new file mode 100644
index 000000000..a1fd48d22
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/01-setup-and-first-steps.md
@@ -0,0 +1,650 @@
+---
+title: '01 · First Steps'
+description: 'Experience your first GitHub Copilot CLI demos and learn the three main interaction modes.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **Watch AI find bugs instantly, explain confusing code, and generate working scripts. Then learn three different ways to use GitHub Copilot CLI.**
+
+This chapter is where the magic starts! You'll experience firsthand why developers describe GitHub Copilot CLI as having a senior engineer on speed dial. You'll watch AI find security bugs in seconds, get complex code explained in plain English, and generate working scripts instantly. Then you'll master the three interaction modes (Interactive, Plan, and Programmatic) so you know exactly which one to use for any task.
+
+> ⚠️ **Prerequisites**: Make sure you've completed **[Chapter 00: Quick Start](../00-quick-start/)** first. You'll need GitHub Copilot CLI installed and authenticated before running the demos below.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Experience the productivity boost GitHub Copilot CLI provides through hands-on demos
+- Choose the right mode (Interactive, Plan, or Programmatic) for any task
+- Use slash commands to control your sessions
+
+> ⏱️ **Estimated Time**: ~45 minutes (15 min reading + 30 min hands-on)
+
+---
+
+# Your First Copilot CLI Experience
+
+
+
+Jump right in and see what Copilot CLI can do.
+
+---
+
+## Getting Comfortable: Your First Prompts
+
+Before diving into the impressive demos, let's start with some simple prompts you can try right now. **No code repository needed**! Just open a terminal and start Copilot CLI:
+
+```bash
+copilot
+```
+
+Try these beginner-friendly prompts:
+
+```
+> Explain what a dataclass is in Python in simple terms
+
+> Write a function that sorts a list of dictionaries by a specific key
+
+> What's the difference between a list and a tuple in Python?
+
+> Give me 5 best practices for writing clean Python code
+```
+
+Don't use Python? No problem! Just ask questions about your language of choice.
+
+Notice how natural it feels. Just ask questions like you would to a colleague. When you're done exploring, type `/exit` to leave the session.
+
+**The key insight**: GitHub Copilot CLI is conversational. You don't need special syntax to get started. Just ask questions in plain English.
+
+## See It In Action
+
+Now let's see why developers are calling this "having a senior engineer on speed dial."
+
+> 📖 **Reading the Examples**: Lines starting with `>` are prompts you type inside an interactive Copilot CLI session. Lines without a `>` prefix are shell commands you run in your terminal.
+
+> 💡 **About Example Outputs**: The sample outputs shown throughout this course are illustrative. Because Copilot CLI's responses vary each time, your results will differ in wording, formatting, and detail. Focus on the *type* of information returned, not the exact text.
+
+### Demo 1: Code Review in Seconds
+
+The course includes sample files with intentional code quality issues. Let's review one:
+
+```bash
+# Clone the course repository if you're working locally and haven't already
+git clone https://github.com/github/copilot-cli-for-beginners
+cd copilot-cli-for-beginners
+
+# Start Copilot
+copilot
+```
+
+Once inside the interactive session:
+
+```
+> Review @samples/book-app-project/book_app.py for code quality issues and suggest improvements
+```
+
+> 💡 **What's the `@`?** The `@` symbol tells Copilot CLI to read a file. You'll learn all about this in Chapter 02. For now, just copy the command exactly as shown.
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**The takeaway**: A professional code review in seconds. Manual review would take...well...more time than that!
+
+---
+
+### Demo 2: Explain Confusing Code
+
+Ever stared at code wondering what it does? Try this in your Copilot CLI session:
+
+```
+> Explain what @samples/book-app-project/books.py does in simple terms
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**What happens**: (your output will differ) Copilot CLI reads the file, understands the code, and explains it in plain English.
+
+```
+This is a book collection management module using Python dataclasses.
+
+Think of it like a digital bookshelf:
+- Book is a dataclass - a simple way to store book information (title, author, year, read status)
+- BookCollection manages the entire collection and handles saving/loading
+
+Key components:
+
+1. @dataclass decorator (line 8)
+ - Automatically creates __init__, __repr__, etc.
+ - Clean way to define data structures in Python
+
+2. BookCollection class (line 16)
+ - Maintains a list of Book objects
+ - Handles persistence with JSON file I/O
+ - load_books() reads from data.json
+ - save_books() writes to data.json using asdict()
+
+3. Book operations:
+ - add_book() - creates and saves new books
+ - find_book_by_title() - searches collection
+ - mark_as_read() - updates read status
+ - find_by_author() - filters by author name
+
+Common pattern: Read from JSON → Work with Python objects → Write back to JSON
+```
+
+**The takeaway**: Complex code explained like a patient mentor would explain it.
+
+---
+
+### Demo 3: Generate Working Code
+
+Need a function you'd otherwise spend 15 minutes googling? Still in your session:
+
+```
+> Write a Python function that takes a list of books and returns statistics:
+ total count, number read, number unread, oldest and newest book
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**What happens**: A complete, working function in seconds that you can copy-paste-run.
+
+When you're done exploring, exit the session:
+
+```
+> /exit
+```
+
+**The takeaway**: Instant gratification, and you stayed in one continuous session the whole time.
+
+---
+
+# 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.
+
+> 💡 **Note**: Copilot CLI also has an **Autopilot** mode where it works through tasks without waiting for your input. It's powerful but requires granting full permissions and uses premium requests autonomously. This course focuses on the three modes below. We'll point you to Autopilot once you're comfortable with the basics.
+
+---
+
+## 🧩 Real-World Analogy: Dining Out
+
+Think of using GitHub Copilot CLI like going out to eat. From planning the trip to placing your order, different situations call for different approaches:
+
+| Mode | Dining Analogy | When to Use |
+|------|----------------|-------------|
+| **Plan** | GPS route to the restaurant | Complex tasks - map out the route, review stops, agree on the plan, then drive |
+| **Interactive** | Talking to the waiter | Exploration and iteration - ask questions, customize, get real-time feedback |
+| **Programmatic** | Drive-through ordering | Quick, specific tasks - stay in your environment, get a result fast |
+
+Just like dining out, you'll naturally learn when each approach feels right.
+
+
+
+*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*
+
+### Which Mode Should I Start With?
+
+**Start with Interactive mode.**
+- You can experiment and ask follow-up questions
+- Context builds naturally through conversation
+- Mistakes are easy to correct with `/clear`
+
+Once you're comfortable, try:
+- **Programmatic mode** (`copilot -p ""`) for quick, one-off questions
+- **Plan mode** (`/plan`) when you need to plan things out in more detail before coding
+
+---
+
+## The Three Modes
+
+### Mode 1: Interactive Mode (start here)
+
+
+
+**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.
+
+Start an interactive session:
+
+```bash
+copilot
+```
+
+As you've seen up to this point, you'll see a prompt where you can type naturally. To get help on available commands, just type:
+
+```
+> /help
+```
+
+**Key insight**: Interactive mode maintains context. Each message builds on previous ones, just like a real conversation.
+
+#### Interactive Mode Example
+
+```bash
+copilot
+
+> Review @samples/book-app-project/utils.py and suggest improvements
+
+> Add type hints to all functions
+
+> Make the error handling more robust
+
+> /exit
+```
+
+Notice how each prompt builds on the previous answer. You're having a conversation, not starting over each time.
+
+---
+
+### Mode 2: Plan Mode
+
+
+
+**Best for**: Complex tasks where you want to review the approach before execution. Similar to planning a route before a trip using GPS.
+
+Plan mode helps you create a step-by-step plan before writing any code. Use the `/plan` command or press **Shift+Tab** to cycle into Plan Mode:
+
+> 💡 **Tip**: **Shift+Tab** cycles between modes: Interactive → Plan → Autopilot. Press it anytime during an interactive session to switch modes without typing a command.
+
+```bash
+copilot
+
+> /plan Add a "mark as read" command to the book app
+```
+
+**Plan mode output:** (your output may differ)
+
+```
+📋 Implementation Plan
+
+Step 1: Update the command handler in book_app.py
+ - Add new elif branch for "mark" command
+ - Create handle_mark_as_read() function
+
+Step 2: Implement the handler function
+ - Prompt user for book title
+ - Call collection.mark_as_read(title)
+ - Display success/failure message
+
+Step 3: Update help text
+ - Add "mark" to available commands list
+ - Document the command usage
+
+Step 4: Test the flow
+ - Add a book
+ - Mark it as read
+ - Verify status changes in list output
+
+Proceed with implementation? [Y/n]
+```
+
+**Key insight**: Plan mode lets you review and modify the approach before any code is written. Once a plan is complete, you can even tell Copilot CLI to save it to a file for later reference. For example, "Save this plan to `mark_as_read_plan.md`" would create a markdown file with the plan details.
+
+> 💡 **Want something more complex?** Try: `/plan Add search and filter capabilities to the book app`. Plan mode scales from simple features to full applications.
+
+> 📚 **Autopilot mode**: You may have noticed Shift+Tab cycles through a third mode called **Autopilot**. In autopilot mode, Copilot works through an entire plan without waiting for your input after each step — like handing a task to a colleague and saying "let me know when you're finished." The typical workflow is plan → accept → autopilot, which means you need to be good at writing plans first. Get comfortable with Interactive and Plan modes, then see the [official docs](https://docs.github.com/copilot/concepts/agents/copilot-cli/autopilot) when you're ready.
+
+---
+
+### Mode 3: Programmatic Mode
+
+
+
+**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.
+
+Use the `-p` flag for one-time commands that don't need interaction:
+
+```bash
+# Generate code
+copilot -p "Write a function that checks if a number is even or odd"
+
+# Get quick help
+copilot -p "How do I read a JSON file in Python?"
+```
+
+**Key insight**: Programmatic mode gives you a quick answer and exits. No conversation, just input → output.
+
+
+📚 Going Further: Using Programmatic Mode in Scripts (click to expand)
+
+Once you're comfortable, you can use `-p` in shell scripts:
+
+```bash
+#!/bin/bash
+
+# Generate commit messages automatically
+COMMIT_MSG=$(copilot -p "Generate a commit message for: $(git diff --staged)")
+git commit -m "$COMMIT_MSG"
+
+# Review a file
+copilot --allow-all -p "Review @myfile.py for issues"
+```
+> ⚠️ **About `--allow-all`**: This flag skips all permission prompts, letting Copilot CLI read files, run commands, and access URLs without asking first. This is necessary for programmatic mode (`-p`) since there's no interactive session to approve actions. Only use `--allow-all` with prompts you've written yourself and in directories you trust. Never use it with untrusted input or in sensitive directories.
+
+
+
+---
+
+## Essential Slash Commands
+
+These commands work in interactive mode. **Start with just these six** - they cover 90% of daily use:
+
+| Command | What It Does | When to Use |
+|---------|--------------|-------------|
+| `/help` | Show all available commands | When you forget a command |
+| `/clear` | Clear conversation and start fresh | When switching topics |
+| `/plan` | Plan your work out before coding | For more complex features |
+| `/research` | Deep research using GitHub and web sources | When you need to investigate a topic before coding |
+| `/model` | Show or switch AI model | When you want to change the AI model |
+| `/exit` | End the session | When you're done |
+
+That's it for getting started! As you become comfortable, you can explore additional commands.
+
+> 📚 **Official Documentation**: [CLI command reference](https://docs.github.com/copilot/reference/cli-command-reference) for the complete list of commands and flags.
+
+
+📚 Additional Commands (click to expand)
+
+> 💡 The essential commands above cover a lot of what you'll do on a daily use. This reference is here for when you're ready to explore more.
+
+### Agent Environment
+
+| Command | What It Does |
+|---------|--------------|
+| `/init` | Initialize Copilot instructions for your repository |
+| `/agent` | Browse and select from available agents |
+| `/skills` | Manage skills for enhanced capabilities |
+| `/mcp` | Manage MCP server configuration |
+
+> 💡 Skills are covered in detail in [Chapter 05](../05-skills/). MCP servers are covered in [Chapter 06](../06-mcp-servers/).
+
+### Models and Subagents
+
+| Command | What It Does |
+|---------|--------------|
+| `/model` | Show or switch AI model |
+| `/delegate` | Hand off task to Copilot coding agent on GitHub (agent in the cloud) |
+| `/fleet` | Split a complex task into parallel subtasks for faster completion |
+| `/tasks` | View background subagents and detached shell sessions |
+
+### Code
+
+| Command | What It Does |
+|---------|--------------|
+| `/diff` | Review the changes made in the current directory |
+| `/pr` | Operate on pull requests for the current branch |
+| `/review` | Run the code-review agent to analyze changes |
+| `/research` | Run deep research investigation using GitHub and web sources |
+| `/terminal-setup` | Enable multiline input support (shift+enter and ctrl+enter) |
+
+### Permissions
+
+| Command | What It Does |
+|---------|--------------|
+| `/allow-all` | Auto-approve all permission prompts for this session |
+| `/add-dir ` | Add a directory to allowed list |
+| `/list-dirs` | Show all allowed directories |
+| `/cwd`, `/cd [directory]` | View or change working directory |
+
+> ⚠️ **Use with caution**: `/allow-all` skips confirmation prompts. Great for trusted projects, but be careful with untrusted code.
+
+### Session
+
+| Command | What It Does |
+|---------|--------------|
+| `/resume` | Switch to a different session (optionally specify session ID) |
+| `/rename` | Rename the current session |
+| `/context` | Show context window token usage and visualization |
+| `/usage` | Display session usage metrics and statistics |
+| `/session` | Show session info and workspace summary |
+| `/compact` | Summarize conversation to reduce context usage |
+| `/share` | Export session as markdown file or GitHub gist |
+
+### Help and Feedback
+
+| Command | What It Does |
+|---------|--------------|
+| `/help` | Show all available commands |
+| `/changelog` | Display changelog for CLI versions |
+| `/feedback` | Submit feedback to GitHub |
+| `/theme` | View or set terminal theme |
+
+### Quick Shell Commands
+
+Run shell commands directly without AI by prefixing with `!`:
+
+```bash
+copilot
+
+> !git status
+# Runs git status directly, bypassing the AI
+
+> !python -m pytest tests/
+# Runs pytest directly
+```
+
+### Switching Models
+
+Copilot CLI supports multiple AI models from OpenAI, Anthropic, Google, and others. The models available to you depend on your subscription level and region. Use `/model` to see your options and switch between them:
+
+```bash
+copilot
+> /model
+
+# Shows available models and lets you pick one. Select Sonnet 4.5.
+```
+
+> 💡 **Tip**: Some models cost more "premium requests" than others. Models marked **1x** (like Claude Sonnet 4.5) are a great default. They're capable and efficient. Higher-multiplier models use your premium request quota faster, so save those for when you really need them.
+
+
+
+---
+
+# Practice
+
+
+
+Time to put what you've learned into action.
+
+---
+
+## ▶️ Try It Yourself
+
+### Interactive Exploration
+
+Start Copilot and use follow-up prompts to iteratively improve the book app:
+
+```bash
+copilot
+
+> Review @samples/book-app-project/book_app.py - what could be improved?
+
+> Refactor the if/elif chain into a more maintainable structure
+
+> Add type hints to all the handler functions
+
+> /exit
+```
+
+### Plan a Feature
+
+Use `/plan` to have Copilot CLI map out an implementation before writing any code:
+
+```bash
+copilot
+
+> /plan Add a search feature to the book app that can find books by title or author
+
+# Review the plan
+# Approve or modify
+# Watch it implement step by step
+```
+
+### Automate with Programmatic Mode
+
+The `-p` flag lets you run Copilot CLI directly from your terminal without entering interactive mode. Copy and paste the following script into your terminal (not inside Copilot) from the repository root to review all Python files in the book app.
+
+```bash
+# Review all Python files in the book app
+for file in samples/book-app-project/*.py; do
+ echo "Reviewing $file..."
+ copilot --allow-all -p "Quick code quality review of @$file - critical issues only"
+done
+```
+
+**PowerShell (Windows):**
+
+```powershell
+# Review all Python files in the book app
+Get-ChildItem samples/book-app-project/*.py | ForEach-Object {
+ $relativePath = "samples/book-app-project/$($_.Name)";
+ Write-Host "Reviewing $relativePath...";
+ copilot --allow-all -p "Quick code quality review of @$relativePath - critical issues only"
+}
+```
+
+---
+
+After completing the demos, try these variations:
+
+1. **Interactive Challenge**: Start `copilot` and explore the book app. Ask about `@samples/book-app-project/books.py` and request improvements 3 times in a row.
+
+2. **Plan Mode Challenge**: Run `/plan Add rating and review features to the book app`. Read the plan carefully. Does it make sense?
+
+3. **Programmatic Challenge**: Run `copilot --allow-all -p "List all functions in @samples/book-app-project/book_app.py and describe what each does"`. Did it work on the first try?
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Improve the Book App Utilities
+
+The hands-on examples focused on reviewing and refactoring `book_app.py`. Now practice the same skills on a different file, `utils.py`:
+
+1. Start an interactive session: `copilot`
+2. Ask Copilot CLI to summarize the file: `@samples/book-app-project/utils.py What does each function in this file do?`
+3. Ask it to add input validation: "Add validation to `get_user_choice()` so it handles empty input and non-numeric entries"
+4. Ask it to improve error handling: "What happens if `get_book_details()` receives an empty string for the title? Add guards for that."
+5. Ask for a docstring: "Add a comprehensive docstring to `get_book_details()` with parameter descriptions and return values"
+6. Observe how context carries between prompts. Each improvement builds on the last
+7. Exit with `/exit`
+
+**Success criteria**: You should have an improved `utils.py` with input validation, error handling, and a docstring, all built through a multi-turn conversation.
+
+
+💡 Hints (click to expand)
+
+**Sample prompts to try:**
+```bash
+> @samples/book-app-project/utils.py What does each function in this file do?
+> Add validation to get_user_choice() so it handles empty input and non-numeric entries
+> What happens if get_book_details() receives an empty string for the title? Add guards for that.
+> Add a comprehensive docstring to get_book_details() with parameter descriptions and return values
+```
+
+**Common issues:**
+- If Copilot CLI asks clarifying questions, just answer them naturally
+- The context carries forward, so each prompt builds on the previous
+- Use `/clear` if you want to start over
+
+
+
+### Bonus Challenge: Compare the Modes
+
+The examples used `/plan` for a search feature and `-p` for batch reviews. Now try all three modes on a single new task: adding a `list_by_year()` method to the `BookCollection` class:
+
+1. **Interactive**: `copilot` → ask it to design and build the method step by step
+2. **Plan**: `/plan Add a list_by_year(start, end) method to BookCollection that filters books by publication year range`
+3. **Programmatic**: `copilot --allow-all -p "@samples/book-app-project/books.py Add a list_by_year(start, end) method that returns books published between start and end year inclusive"`
+
+**Reflection**: Which mode felt most natural? When would you use each?
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| 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?"` |
+
+### Troubleshooting
+
+**"Model not available"** - Your subscription may not include all models. Use `/model` to see what's available.
+
+**"Context too long"** - Your conversation has used the full context window. Use `/clear` to reset, or start a new session.
+
+**"Rate limit exceeded"** - Wait a few minutes and try again. Consider using programmatic mode for batch operations with delays.
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+1. **Interactive mode** is for exploration and iteration - context carries forward. It's like having a conversation with someone who remembers what you've said up to that point.
+2. **Plan mode** is normally for more involved tasks. Review before implementation.
+3. **Programmatic mode** is for automation. No interaction needed.
+4. **Four essential commands** (`/help`, `/clear`, `/plan`, `/exit`) cover most daily use.
+
+> 📋 **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.
+
+---
+
+## ➡️ What's Next
+
+Now that you understand the three modes, let's learn how to give Copilot CLI context about your code.
+
+In **[Chapter 02: Context and Conversations](../02-context-and-conversations/)**, you'll learn:
+
+- The `@` syntax for referencing files and directories
+- Session management with `--resume` and `--continue`
+- How context management makes Copilot CLI truly powerful
+
+---
+
+**[← Back to Course Home](../)** | **[Continue to Chapter 02 →](../02-context-and-conversations/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/02-context-and-conversations.md b/website/src/content/docs/learning-hub/cli-for-beginners/02-context-and-conversations.md
new file mode 100644
index 000000000..5d0d9ee38
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/02-context-and-conversations.md
@@ -0,0 +1,881 @@
+---
+title: '02 · Context and Conversations'
+description: 'Learn how to give Copilot CLI richer context and build stronger multi-turn conversations.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **What if AI could see your entire codebase, not just one file at a time?**
+
+In this chapter, you'll unlock the real power of GitHub Copilot CLI: context. You'll learn to use the `@` syntax to reference files and directories, giving Copilot CLI deep understanding of your codebase. You'll discover how to maintain conversations across sessions, resume work days later exactly where you left off, and see how cross-file analysis catches bugs that single-file reviews miss entirely.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Use the `@` syntax to reference files, directories, and images
+- Resume previous sessions with `--resume` and `--continue`
+- Understand how [context windows](https://github.com/github/copilot-cli-for-beginners/blob/main/GLOSSARY.md#context-window) work
+- Write effective multi-turn conversations
+- Manage directory permissions for multi-project workflows
+
+> ⏱️ **Estimated Time**: ~50 minutes (20 min reading + 30 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: Working with a Colleague
+
+
+
+*Just like your colleagues, Copilot CLI isn't a mind reader. Providing more information helps humans and Copilot alike provide targeted support!*
+
+Imagine explaining a bug to a colleague:
+
+> **Without context**: "The book app doesn't work."
+
+> **With context**: "Look at `books.py`, especially the `find_book_by_title` function. It's not doing case-insensitive matching."
+
+To provide context to Copilot CLI use *the `@` syntax* to point Copilot CLI at specific files.
+
+---
+
+# Essential: Basic Context
+
+
+
+This section covers everything you need to work effectively with context. Master these basics first.
+
+---
+
+## The @ Syntax
+
+The `@` symbol references files and directories in your prompts. It's how you tell Copilot CLI "look at this file."
+
+> 💡 **Note**: All examples in this course use the `samples/` folder included in this repository, so you can try every command directly.
+
+### Try It Now (No Setup Required)
+
+You can try this with any file on your computer:
+
+```bash
+copilot
+
+# Point at any file you have
+> Explain what @package.json does
+> Summarize @README.md
+> What's in @.gitignore and why?
+```
+
+> 💡 **Don't have a project handy?** Create a quick test file:
+> ```bash
+> echo "def greet(name): return 'Hello ' + name" > test.py
+> copilot
+> > What does @test.py do?
+> ```
+
+### Basic @ Patterns
+
+| Pattern | What It Does | Example Use |
+|---------|--------------|-------------|
+| `@file.py` | Reference a single file | `Review @samples/book-app-project/books.py` |
+| `@folder/` | Reference all files in a directory | `Review @samples/book-app-project/` |
+| `@file1.py @file2.py` | Reference multiple files | `Compare @samples/book-app-project/book_app.py @samples/book-app-project/books.py` |
+
+### Reference a Single File
+
+```bash
+copilot
+
+> Explain what @samples/book-app-project/utils.py does
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### Reference Multiple Files
+
+```bash
+copilot
+
+> Compare @samples/book-app-project/book_app.py and @samples/book-app-project/books.py for consistency
+```
+
+### Reference an Entire Directory
+
+```bash
+copilot
+
+> Review all files in @samples/book-app-project/ for error handling
+```
+
+---
+
+## Cross-File Intelligence
+
+This is where context becomes a superpower. Single-file analysis is useful. Cross-file analysis is transformative.
+
+
+
+### Demo: Find Bugs That Span Multiple Files
+
+```bash
+copilot
+
+> @samples/book-app-project/book_app.py @samples/book-app-project/books.py
+>
+> How do these files work together? What's the data flow?
+```
+
+> 💡 **Advanced Option**: For security-focused cross-file analysis, try the Python security examples:
+> ```bash
+> > @samples/buggy-code/python/user_service.py @samples/buggy-code/python/payment_processor.py
+> > Find security vulnerabilities that span BOTH files
+> ```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**What Copilot CLI discovers**:
+
+```
+Cross-Module Analysis
+=====================
+
+1. DATA FLOW PATTERN
+ book_app.py creates BookCollection instance and calls methods
+ books.py defines BookCollection class and manages data persistence
+
+ Flow: book_app.py (UI) → books.py (business logic) → data.json (storage)
+
+2. DUPLICATE DISPLAY FUNCTIONS
+ book_app.py:9-21 show_books() function
+ utils.py:28-36 print_books() function
+
+ Impact: Two nearly identical functions doing the same thing. If you update
+ one (like changing the format), you must remember to update the other.
+
+3. INCONSISTENT ERROR HANDLING
+ book_app.py handles ValueError from year conversion
+ books.py silently returns None/False on errors
+
+ Pattern: No unified approach to error handling across modules
+```
+
+**Why this matters**: A single-file review would miss the bigger picture. Only cross-file analysis reveals:
+- **Duplicate code** that should be consolidated
+- **Data flow patterns** showing how components interact
+- **Architectural issues** that affect maintainability
+
+---
+
+### Demo: Understand a Codebase in 60 Seconds
+
+
+
+New to a project? Learn about it quickly using Copilot CLI.
+
+```bash
+copilot
+
+> @samples/book-app-project/
+>
+> In one paragraph, what does this app do and what are its biggest quality issues?
+```
+
+**What you get**:
+```
+This is a CLI book collection manager that lets users add, list, remove, and
+search books stored in a JSON file. The biggest quality issues are:
+
+1. Duplicate display logic - show_books() and print_books() do the same thing
+2. Inconsistent error handling - some errors raise exceptions, others return False
+3. No input validation - year can be 0, empty strings accepted for title/author
+4. Missing tests - no test coverage for critical functions like find_book_by_title
+
+Priority fix: Consolidate duplicate display functions and add input validation.
+```
+
+**Result**: What takes an hour of code reading compressed into 10 seconds. You know exactly where to focus.
+
+---
+
+## Practical Examples
+
+### Example 1: Code Review with Context
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Review this file for potential bugs
+
+# Copilot CLI now has the full file content and can give specific feedback:
+# "Line 49: Case-sensitive comparison may miss books..."
+# "Line 29: JSON decode errors are caught but data corruption isn't logged..."
+
+> What about @samples/book-app-project/book_app.py?
+
+# Now reviewing book_app.py, but still aware of books.py context
+```
+
+### Example 2: Understanding a Codebase
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py What does this module do?
+
+# Copilot CLI reads books.py and understands the BookCollection class
+
+> @samples/book-app-project/ Give me an overview of the code structure
+
+# Copilot CLI scans the directory and summarizes
+
+> How does the app save and load books?
+
+# Copilot CLI can trace through the code it's already seen
+```
+
+
+🎬 See a multi-turn conversation in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+### Example 3: Multi-File Refactoring
+
+```bash
+copilot
+
+> @samples/book-app-project/book_app.py @samples/book-app-project/utils.py
+> I see duplicate display functions: show_books() and print_books(). Help me consolidate these.
+
+# Copilot CLI sees both files and can suggest how to merge the duplicate code
+```
+
+---
+
+## Session Management
+
+Sessions are automatically saved as you work. You can resume previous sessions to continue where you left off.
+
+### Sessions Auto-Save
+
+Every conversation is automatically saved. Just exit normally:
+
+```bash
+copilot
+
+> @samples/book-app-project/ Let's improve error handling across all modules
+
+[... do some work ...]
+
+> /exit
+```
+
+### Resume the Most Recent Session
+
+```bash
+# Continue where you left off
+copilot --continue
+```
+
+### Resume a Specific Session
+
+```bash
+# Pick from a list of sessions interactively
+copilot --resume
+
+# Or resume a specific session by ID
+copilot --resume abc123
+```
+
+> 💡 **How do I find a session ID?** You don't need to memorize them. Running `copilot --resume` without an ID shows an interactive list of your previous sessions, their names, IDs, and when they were last active. Just pick the one you want.
+>
+> **What about multiple terminals?** Each terminal window is its own session with its own context. If you have Copilot CLI open in three terminals, that's three separate sessions. Running `--resume` from any terminal lets you browse all of them. The `--continue` flag grabs whichever session was closed most recently, no matter which terminal it was in.
+>
+> **Can I switch sessions without restarting?** Yes. Use the `/resume` slash command from inside an active session:
+> ```
+> > /resume
+> # Shows a list of sessions to switch to
+> ```
+
+### Organize Your Sessions
+
+Give sessions meaningful names so you can find them later:
+
+```bash
+copilot
+
+> /rename book-app-review
+# Session renamed for easier identification
+```
+
+### Check and Manage Context
+
+As you add files and conversation, Copilot CLI's [context window](https://github.com/github/copilot-cli-for-beginners/blob/main/GLOSSARY.md#context-window) fills up. Two commands help you stay in control:
+
+```bash
+copilot
+
+> /context
+Context usage: 45,000 / 128,000 tokens (35%)
+
+> /clear
+# Wipes context and starts fresh. Use when switching topics
+```
+
+> 💡 **When to use `/clear`**: If you've been reviewing `books.py` and want to switch to discussing `utils.py`, run `/clear` first. Otherwise stale context from the old topic may confuse responses.
+
+---
+
+### Pick Up Where You Left Off
+
+
+
+*Sessions auto-save when you exit. Resume days later with full context: files, issues, and progress all remembered.*
+
+Imagine this workflow across multiple days:
+
+```bash
+# Monday: Start book app review
+copilot
+
+> /rename book-app-review
+> @samples/book-app-project/books.py
+> Review and number all code quality issues
+
+Quality Issues Found:
+1. Duplicate display functions (book_app.py & utils.py) - MEDIUM
+2. No input validation for empty strings - MEDIUM
+3. Year can be 0 or negative - LOW
+4. No type hints on all functions - LOW
+5. Missing error logging - LOW
+
+> Fix issue #1 (duplicate functions)
+# Work on the fix...
+
+> /exit
+```
+
+```bash
+# Wednesday: Resume exactly where you left off
+copilot --continue
+
+> What issues remain unfixed from our book app review?
+
+Remaining issues from our book-app-review session:
+2. No input validation for empty strings - MEDIUM
+3. Year can be 0 or negative - LOW
+4. No type hints on all functions - LOW
+5. Missing error logging - LOW
+
+Issue #1 (duplicate functions) was fixed on Monday.
+
+> Let's tackle issue #2 next
+```
+
+**What makes this powerful**: Days later, Copilot CLI remembers:
+- The exact file you were working on
+- The numbered list of issues
+- Which ones you've already addressed
+- The context of your conversation
+
+No re-explaining. No re-reading files. Just continue working.
+
+---
+
+**🎉 You now know the essentials!** The `@` syntax, session management (`--continue`/`--resume`/`/rename`), and context commands (`/context`/`/clear`) are enough to be highly productive. Everything below is optional. Return to it when you're ready.
+
+---
+
+# Optional: Going Deeper
+
+
+
+These topics build on the essentials above. **Pick what interests you, or skip ahead to [Practice](#practice).**
+
+| I want to learn about... | Jump to |
+|---|---|
+| Wildcard patterns and advanced session commands | [Additional @ Patterns & Session Commands](#additional-patterns) |
+| Building on context across multiple prompts | [Context-Aware Conversations](#context-aware-conversations) |
+| Token limits and `/compact` | [Understanding Context Windows](#understanding-context-windows) |
+| How to pick the right files to reference | [Choosing What to Reference](#choosing-what-to-reference) |
+| Analyzing screenshots and mockups | [Working with Images](#working-with-images) |
+
+
+Additional @ Patterns & Session Commands
+
+
+### Additional @ Patterns
+
+For power users, Copilot CLI supports wildcard patterns and image references:
+
+| Pattern | What It Does |
+|---------|--------------|
+| `@folder/*.py` | All .py files in folder |
+| `@**/test_*.py` | Recursive wildcard: find all test files anywhere |
+| `@image.png` | Image file for UI review |
+
+```bash
+copilot
+
+> Find all TODO comments in @samples/book-app-project/**/*.py
+```
+
+### View Session Info
+
+```bash
+copilot
+
+> /session
+# Shows current session details and workspace summary
+
+> /usage
+# Shows session metrics and statistics
+```
+
+### Share Your Session
+
+```bash
+copilot
+
+> /share file ./my-session.md
+# Exports session as a markdown file
+
+> /share gist
+# Creates a GitHub gist with the session
+```
+
+
+
+
+Context-Aware Conversations
+
+
+### Context-Aware Conversations
+
+The magic happens when you have multi-turn conversations that build on each other.
+
+#### Example: Progressive Enhancement
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Review the BookCollection class
+
+Copilot CLI: "The class looks functional, but I notice:
+1. Missing type hints on some methods
+2. No validation for empty title/author
+3. Could benefit from better error handling"
+
+> Add type hints to all methods
+
+Copilot CLI: "Here's the class with complete type hints..."
+[Shows typed version]
+
+> Now improve error handling
+
+Copilot CLI: "Building on the typed version, here's improved error handling..."
+[Adds validation and proper exceptions]
+
+> Generate tests for this final version
+
+Copilot CLI: "Based on the class with types and error handling..."
+[Generates comprehensive tests]
+```
+
+Notice how each prompt builds on the previous work. This is the power of context.
+
+
+
+
+Understanding Context Windows
+
+
+### Understanding Context Windows
+
+You already know `/context` and `/clear` from the essentials. Here's the deeper picture of how context windows work.
+
+Every AI has a "context window," which is the amount of text it can consider at once.
+
+
+
+*The context window is like a desk: it can only hold so much at once. Files, conversation history, and system prompts all take space.*
+
+#### What Happens at the Limit
+
+```bash
+copilot
+
+> /context
+
+Context usage: 45,000 / 128,000 tokens (35%)
+
+# As you add more files and conversation, this grows
+
+> @large-codebase/
+
+Context usage: 120,000 / 128,000 tokens (94%)
+
+# Warning: Approaching context limit
+
+> @another-large-file.py
+
+Context limit reached. Older context will be summarized.
+```
+
+#### The `/compact` Command
+
+When your context is getting full but you don't want to lose the conversation, `/compact` summarizes your history to free up tokens:
+
+```bash
+copilot
+
+> /compact
+# Summarizes conversation history, freeing up context space
+# Your key findings and decisions are preserved
+```
+
+#### Context Efficiency Tips
+
+| Situation | Action | Why |
+|-----------|--------|-----|
+| Starting new topic | `/clear` | Removes irrelevant context |
+| Long conversation | `/compact` | Summarizes history, frees tokens |
+| Need specific file | `@file.py` not `@folder/` | Loads only what you need |
+| Hitting limits | Start new session | Fresh 128K context |
+| Multiple topics | Use `/rename` per topic | Easy to resume right session |
+
+#### Best Practices for Large Codebases
+
+1. **Be specific**: `@samples/book-app-project/books.py` instead of `@samples/book-app-project/`
+2. **Clear between topics**: Use `/clear` when switching focus
+3. **Use `/compact`**: Summarize conversation to free up context
+4. **Use multiple sessions**: One session per feature or topic
+
+
+
+
+Choosing What to Reference
+
+
+### Choosing What to Reference
+
+Not all files are equal when it comes to context. Here's how to choose wisely:
+
+#### File Size Considerations
+
+| File Size | Approximate [Tokens](https://github.com/github/copilot-cli-for-beginners/blob/main/GLOSSARY.md#token) | Strategy |
+|-----------|-------------------|----------|
+| Small (<100 lines) | ~500-1,500 tokens | Reference freely |
+| Medium (100-500 lines) | ~1,500-7,500 tokens | Reference specific files |
+| Large (500+ lines) | 7,500+ tokens | Be selective, use specific files |
+| Very Large (1000+ lines) | 15,000+ tokens | Consider splitting or targeting sections |
+
+**Concrete examples:**
+- The book app's 4 Python files combined ≈ 2,000-3,000 tokens
+- A typical Python module (200 lines) ≈ 3,000 tokens
+- A Flask API file (400 lines) ≈ 6,000 tokens
+- Your package.json ≈ 200-500 tokens
+- A short prompt + response ≈ 500-1,500 tokens
+
+> 💡 **Quick estimate for code:** Multiply lines of code by ~15 to get approximate tokens. Keep in mind this is only an estimate.
+
+#### What to Include vs. Exclude
+
+**High value** (include these):
+- Entry points (`book_app.py`, `main.py`, `app.py`)
+- The specific files you're asking about
+- Files directly imported by your target file
+- Configuration files (`requirements.txt`, `pyproject.toml`)
+- Data models or dataclasses
+
+**Lower value** (consider excluding):
+- Generated files (compiled output, bundled assets)
+- Node modules or vendor directories
+- Large data files or fixtures
+- Files unrelated to your question
+
+#### The Specificity Spectrum
+
+```
+Less specific ────────────────────────► More specific
+@samples/book-app-project/ @samples/book-app-project/books.py:47-52
+ │ │
+ └─ Scans everything └─ Just what you need
+ (uses more context) (preserves context)
+```
+
+**When to go broad** (`@samples/book-app-project/`):
+- Initial codebase exploration
+- Finding patterns across many files
+- Architecture reviews
+
+**When to go specific** (`@samples/book-app-project/books.py`):
+- Debugging a particular issue
+- Code review of a specific file
+- Asking about a single function
+
+#### Practical Example: Staged Context Loading
+
+```bash
+copilot
+
+# Step 1: Start with structure
+> @package.json What frameworks does this project use?
+
+# Step 2: Narrow based on answer
+> @samples/book-app-project/ Show me the project structure
+
+# Step 3: Focus on what matters
+> @samples/book-app-project/books.py Review the BookCollection class
+
+# Step 4: Add related files only as needed
+> @samples/book-app-project/book_app.py @samples/book-app-project/books.py How does the CLI use the BookCollection?
+```
+
+This staged approach keeps context focused and efficient.
+
+
+
+
+Working with Images
+
+
+### Working with Images
+
+You can include images in your conversations using the `@` syntax, or simply **paste from your clipboard** (Cmd+V / Ctrl+V). Copilot CLI can analyze screenshots, mockups, and diagrams to help with UI debugging, design implementation, and error analysis.
+
+```bash
+copilot
+
+> @images/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.
+```
+
+> 📖 **Learn more**: See [Additional Context Features](https://github.com/github/copilot-cli-for-beginners/blob/main/appendices/additional-context.md#working-with-images) for supported formats, practical use cases, and tips for combining images with code.
+
+
+
+---
+
+# Practice
+
+
+
+Time to apply your context and session management skills.
+
+---
+
+## ▶️ Try It Yourself
+
+### Full Project Review
+
+The course includes sample files you can review directly. Start copilot and run the prompt shown next:
+
+```bash
+copilot
+
+> @samples/book-app-project/ Give me a code quality review of this project
+
+# Copilot CLI will identify issues like:
+# - Duplicate display functions
+# - Missing input validation
+# - Inconsistent error handling
+```
+
+> 💡 **Want to try with your own files?** Create a small Python project (`mkdir -p my-project/src`), add some .py files, then use `@my-project/src/` to review them. You can ask copilot to create sample code for you if you'd like!
+
+### Session Workflow
+
+```bash
+copilot
+
+> /rename book-app-review
+> @samples/book-app-project/books.py Let's add input validation for empty titles
+
+[Copilot CLI suggests validation approach]
+
+> Implement that fix
+> Now consolidate the duplicate display functions in @samples/book-app-project/
+> /exit
+
+# Later - resume where you left off
+copilot --continue
+
+> Generate tests for the changes we made
+```
+
+---
+
+After completing the demos, try these variations:
+
+1. **Cross-File Challenge**: Analyze how book_app.py and books.py work together:
+ ```bash
+ copilot
+ > @samples/book-app-project/book_app.py @samples/book-app-project/books.py
+ > What's the relationship between these files? Are there any code smells?
+ ```
+
+2. **Session Challenge**: Start a session, name it with `/rename my-first-session`, work on something, exit with `/exit`, then run `copilot --continue`. Does it remember what you were doing?
+
+3. **Context Challenge**: Run `/context` mid-session. How many tokens are you using? Try `/compact` and check again. (See [Understanding Context Windows](#understanding-context-windows) in Going Deeper for more on `/compact`.)
+
+**Self-Check**: You understand context when you can explain why `@folder/` is more powerful than opening each file individually.
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Trace the Data Flow
+
+The hands-on examples focused on code quality reviews and input validation. Now practice the same context skills on a different task, tracing how data moves through the app:
+
+1. Start an interactive session: `copilot`
+2. Reference `books.py` and `book_app.py` together:
+ `@samples/book-app-project/books.py @samples/book-app-project/book_app.py Trace how a book goes from user input to being saved in data.json. What functions are involved at each step?`
+3. Bring in the data file for additional context:
+ `@samples/book-app-project/data.json What happens if this JSON file is missing or corrupted? Which functions would fail?`
+4. Ask for a cross-file improvement:
+ `@samples/book-app-project/books.py @samples/book-app-project/utils.py Suggest a consistent error-handling strategy that works across both files.`
+5. Rename the session: `/rename data-flow-analysis`
+6. Exit with `/exit`, then resume with `copilot --continue` and ask a follow-up question about the data flow
+
+**Success criteria**: You can trace data across multiple files, resume a named session, and get cross-file suggestions.
+
+
+💡 Hints (click to expand)
+
+**Getting started:**
+```bash
+cd /path/to/copilot-cli-for-beginners
+copilot
+> @samples/book-app-project/books.py @samples/book-app-project/book_app.py Trace how a book goes from user input to being saved in data.json.
+> @samples/book-app-project/data.json What happens if this file is missing or corrupted?
+> /rename data-flow-analysis
+> /exit
+```
+
+Then resume with: `copilot --continue`
+
+**Useful commands:**
+- `@file.py` - Reference a single file
+- `@folder/` - Reference all files in a folder (note the trailing `/`)
+- `/context` - Check how much context you're using
+- `/rename ` - Name your session for easy resuming
+
+
+
+### Bonus Challenge: Context Limits
+
+1. Reference all the book app files at once with `@samples/book-app-project/`
+2. Ask several detailed questions about different files (`books.py`, `utils.py`, `book_app.py`, `data.json`)
+3. Run `/context` to see usage. How quickly does it fill up?
+4. Practice using `/compact` to reclaim space, then continue the conversation
+5. Try being more specific with file references (e.g., `@samples/book-app-project/books.py` instead of the whole folder) and see how it affects context usage
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Forgetting `@` before filenames | Copilot CLI treats "books.py" as plain text | Use `@samples/book-app-project/books.py` to reference files |
+| Expecting sessions to persist automatically | Starting `copilot` fresh loses all previous context | Use `--continue` (last session) or `--resume` (pick a session) |
+| Referencing files outside current directory | "Permission denied" or "File not found" errors | Use `/add-dir /path/to/directory` to grant access |
+| Not using `/clear` when switching topics | Old context confuses responses about the new topic | Run `/clear` before starting a different task |
+
+### Troubleshooting
+
+**"File not found" errors** - Make sure you're in the correct directory:
+
+```bash
+pwd # Check current directory
+ls # List files
+
+# Then start copilot and use relative paths
+copilot
+
+> Review @samples/book-app-project/books.py
+```
+
+**"Permission denied"** - Add the directory to your allowed list:
+
+```bash
+copilot --add-dir /path/to/directory
+
+# Or in a session:
+> /add-dir /path/to/directory
+```
+
+**Context fills up too quickly**:
+- Be more specific with file references
+- Use `/clear` between different topics
+- Split work across multiple sessions
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+1. **`@` syntax** gives Copilot CLI context about files, directories, and images
+2. **Multi-turn conversations** build on each other as context accumulates
+3. **Sessions auto-save**: use `--continue` or `--resume` to pick up where you left off
+4. **Context windows** have limits: manage them with `/context`, `/clear`, and `/compact`
+5. **Permission flags** (`--add-dir`, `--allow-all`) control multi-directory access. Use them wisely!
+6. **Image references** (`@screenshot.png`) help debug UI issues visually
+
+> 📚 **Official Documentation**: [Use Copilot CLI](https://docs.github.com/copilot/how-tos/copilot-cli/use-copilot-cli) for the complete reference on context, sessions, and working with files.
+
+> 📋 **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.
+
+---
+
+## ➡️ What's Next
+
+Now that you can give Copilot CLI context, let's put it to work on real development tasks. The context techniques you just learned (file references, cross-file analysis, and session management) are the foundation for the powerful workflows in the next chapter.
+
+In **[Chapter 03: Development Workflows](../03-development-workflows/)**, you'll learn:
+
+- Code review workflows
+- Refactoring patterns
+- Debugging assistance
+- Test generation
+- Git integration
+
+---
+
+**[← Back to Chapter 01](../01-setup-and-first-steps/)** | **[Continue to Chapter 03 →](../03-development-workflows/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/03-development-workflows.md b/website/src/content/docs/learning-hub/cli-for-beginners/03-development-workflows.md
new file mode 100644
index 000000000..2905d9f81
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/03-development-workflows.md
@@ -0,0 +1,966 @@
+---
+title: '03 · Development Workflows'
+description: 'Mirror the source development workflow chapter covering review, debugging, testing, and git support.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **What if the AI could find bugs you didn't even know to ask about?**
+
+In this chapter, GitHub Copilot CLI becomes your daily driver. You'll use it inside the workflows you already rely on every day: testing, refactoring, debugging, and Git.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Run comprehensive code reviews with Copilot CLI
+- Refactor legacy code safely
+- Debug issues with AI assistance
+- Generate tests automatically
+- Integrate Copilot CLI with your git workflow
+
+> ⏱️ **Estimated Time**: ~60 minutes (15 min reading + 45 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: A Carpenter's Workflow
+
+A carpenter doesn't just know how to use tools, they have *workflows* for different jobs:
+
+
+
+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.
+
+---
+
+# The Five Workflows
+
+
+
+Each workflow below is self-contained. Pick the ones that match your current needs, or work through them all.
+
+---
+
+## Choose Your Own Adventure
+
+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.
+
+
+
+| I want to... | Jump to |
+|---|---|
+| Review code before merging | [Workflow 1: Code Review](#workflow-1-code-review) |
+| Clean up messy or legacy code | [Workflow 2: Refactoring](#workflow-2-refactoring) |
+| Track down and fix a bug | [Workflow 3: Debugging](#workflow-3-debugging) |
+| Generate tests for my code | [Workflow 4: Test Generation](#workflow-4-test-generation) |
+| Write better commits and PRs | [Workflow 5: Git Integration](#workflow-5-git-integration) |
+| Research before coding | [Quick Tip: Research Before You Plan or Code](#quick-tip-research-before-you-plan-or-code) |
+| See a full bug-fix workflow end to end | [Putting It All Together](#putting-it-all-together-bug-fix-workflow) |
+
+**Select a workflow below to expand it** and see how GitHub Copilot CLI can enhance your development process in that area.
+
+---
+
+
+
+Workflow 1: Code Review - Review files, use the /review agent, create severity checklists
+
+
+
+### Basic Review
+
+This example uses the `@` symbol to reference a file, giving Copilot CLI direct access to its contents for review.
+
+```bash
+copilot
+
+> Review @samples/book-app-project/book_app.py for code quality
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### Input Validation Review
+
+Ask Copilot CLI to focus its review on a specific concern (here, input validation) by listing the categories you care about in the prompt.
+
+```text
+copilot
+
+> Review @samples/book-app-project/utils.py for input validation issues. Check for: missing validation, error handling gaps, and edge cases
+```
+
+
+### Cross-File Project Review
+
+Reference an entire directory with `@` to let Copilot CLI scan every file in the project at once.
+
+```bash
+copilot
+
+> @samples/book-app-project/ Review this entire project. Create a markdown checklist of issues found, categorized by severity
+```
+
+### Interactive Code Review
+
+Use a multi-turn conversation to drill deeper. Start with a broad review, then ask follow-up questions without restarting.
+
+```bash
+copilot
+
+> @samples/book-app-project/book_app.py Review this file for:
+> - Input validation
+> - Error handling
+> - Code style and best practices
+
+# Copilot CLI provides detailed review
+
+> The user input handling - are there any edge cases I'm missing?
+
+# Copilot CLI shows potential issues with empty strings, special characters
+
+> Create a checklist of all issues found, prioritized by severity
+
+# Copilot CLI generates prioritized action items
+```
+
+### Review Checklist Template
+
+Ask Copilot CLI to structure its output in a specific format (here, a severity-categorized markdown checklist you can paste into an issue).
+
+```bash
+copilot
+
+> Review @samples/book-app-project/ and create a markdown checklist of issues found, categorized by:
+> - Critical (data loss risks, crashes)
+> - High (bugs, incorrect behavior)
+> - Medium (performance, maintainability)
+> - Low (style, minor improvements)
+```
+
+### Understanding Git Changes (Important for /review)
+
+Before using the `/review` command, you need to understand two types of changes in git:
+
+| Change Type | What It Means | How to See |
+|-------------|---------------|------------|
+| **Staged changes** | Files you've marked for the next commit with `git add` | `git diff --staged` |
+| **Unstaged changes** | Files you've modified but haven't added yet | `git diff` |
+
+```bash
+# Quick reference
+git status # Shows both staged and unstaged
+git add file.py # Stage a file for commit
+git diff # Shows unstaged changes
+git diff --staged # Shows staged changes
+```
+
+### Using the /review Command
+
+The `/review` command invokes the built-in **code-review agent**, which is optimized for analyzing staged and unstaged changes with high signal-to-noise output. Use a slash command to trigger a specialized built-in agent instead of writing a free-form prompt.
+
+```bash
+copilot
+
+> /review
+# Invokes the code-review agent on staged/unstaged changes
+# Provides focused, actionable feedback
+
+> /review Check for security issues in authentication
+# Run review with specific focus area
+```
+
+> 💡 **Tip**: The code-review agent works best when you have pending changes. Stage your files with `git add` for more focused reviews.
+
+
+
+---
+
+
+
+Workflow 2: Refactoring - Restructure code, separate concerns, improve error handling
+
+
+
+### Simple Refactoring
+
+> **Try this first:** `@samples/book-app-project/book_app.py The command handling uses if/elif chains. Refactor it to use a dictionary dispatch pattern.`
+
+Start with straightforward improvements. Try these on the book app. Each prompt uses an `@` file reference paired with a specific refactoring instruction so Copilot CLI knows exactly what to change.
+
+```bash
+copilot
+
+> @samples/book-app-project/book_app.py The command handling uses if/elif chains. Refactor it to use a dictionary dispatch pattern.
+
+> @samples/book-app-project/utils.py Add type hints to all functions
+
+> @samples/book-app-project/book_app.py Extract the book display logic into utils.py for better separation of concerns
+```
+
+> 💡 **New to refactoring?** Start with simple requests like adding type hints or improving variable names before tackling complex transformations.
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### Separate Concerns
+
+Reference multiple files with `@` in a single prompt so Copilot CLI can move code between them as part of the refactor.
+
+```bash
+copilot
+
+> @samples/book-app-project/utils.py @samples/book-app-project/book_app.py
+> The utils.py file has print statements mixed with logic. Refactor to separate display functions from data processing.
+```
+
+### Improve Error Handling
+
+Provide two related files and describe the cross-cutting concern so Copilot CLI can suggest a consistent fix across both.
+
+```bash
+copilot
+
+> @samples/book-app-project/utils.py @samples/book-app-project/books.py
+> These files have inconsistent error handling. Suggest a unified approach using custom exceptions.
+```
+
+### Add Documentation
+
+Use a detailed bullet list to specify exactly what each docstring should contain.
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Add comprehensive docstrings to all methods:
+> - Include parameter types and descriptions
+> - Document return values
+> - Note any exceptions raised
+> - Add usage examples
+```
+
+### Safe Refactoring with Tests
+
+Chain two related requests in a multi-turn conversation. First generate tests, then refactor with those tests as a safety net.
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Before refactoring, generate tests for current behavior
+
+# Get tests first
+
+> Now refactor the BookCollection class to use a context manager for file operations
+
+# Refactor with confidence - tests verify behavior is preserved
+```
+
+
+
+---
+
+
+
+Workflow 3: Debugging - Track down bugs, security audits, trace issues across files
+
+
+
+### Simple Debugging
+
+> **Try this first:** `@samples/book-app-buggy/books_buggy.py Users report that searching for "The Hobbit" returns no results even though it's in the data. Debug why.`
+
+Start by describing what's wrong. Here are common debugging patterns you can try with the buggy book app. Each prompt pairs an `@` file reference with a clear symptom description so Copilot CLI can locate and diagnose the bug.
+
+```bash
+copilot
+
+# Pattern: "Expected X but got Y"
+> @samples/book-app-buggy/books_buggy.py Users report that searching for "The Hobbit" returns no results even though it's in the data. Debug why.
+
+# Pattern: "Unexpected behavior"
+> @samples/book-app-buggy/book_app_buggy.py When I remove a book that doesn't exist, the app says it was removed. Help me find why.
+
+# Pattern: "Wrong results"
+> @samples/book-app-buggy/books_buggy.py When I mark one book as read, ALL books get marked. What's the bug?
+```
+
+> 💡 **Debugging tip**: Describe the *symptom* (what you see) and the *expectation* (what should happen). Copilot CLI figures out the rest.
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### The "Bug Detective" - AI Finds RELATED Bugs
+
+This is where context-aware debugging shines. Try this scenario with the buggy book app. Provide the whole file via `@` and describe only the user-reported symptom. Copilot CLI will trace the root cause and may spot additional bugs nearby.
+
+```bash
+copilot
+
+> @samples/book-app-buggy/books_buggy.py
+>
+> Users report: "Finding books by author name doesn't work for partial names"
+> Debug why this happens
+```
+
+**What Copilot CLI does**:
+```
+Root Cause: Line 80 uses exact match (==) instead of partial match (in).
+
+Line 80: return [b for b in self.books if b.author == author]
+
+The find_by_author function requires an exact match. Searching for "Tolkien"
+won't find books by "J.R.R. Tolkien".
+
+Fix: Change to case-insensitive partial match:
+return [b for b in self.books if author.lower() in b.author.lower()]
+```
+
+**Why this matters**: Copilot CLI reads the whole file, understands the context of your bug report, and gives you a specific fix with a clear explanation.
+
+> 💡 **Bonus**: Because Copilot CLI analyzes the entire file, it often discovers *other* issues you didn't ask about. For example, while fixing the author search, Copilot CLI might also notice the case-sensitivity bug in `find_book_by_title`!
+
+### Real-World Security Sidebar
+
+While debugging your own code is important, understanding security vulnerabilities in production applications is critical. Try this example: Point Copilot CLI at an unfamiliar file and ask it to audit for security issues.
+
+```bash
+copilot
+
+> @samples/buggy-code/python/user_service.py Find all security vulnerabilities in this Python user service
+```
+
+This file demonstrates real-world security patterns you'll encounter in production apps.
+
+> 💡 **Common security terms you'll encounter:**
+> - **SQL Injection**: When user input is put directly into a database query, allowing attackers to run malicious commands
+> - **Parameterized queries**: The safe alternative - placeholders (`?`) separate user data from SQL commands
+> - **Race condition**: When two operations happen at the same time and interfere with each other
+> - **XSS (Cross-Site Scripting)**: When attackers inject malicious scripts into web pages
+
+---
+
+### Understanding an Error
+
+Paste a stack trace directly into your prompt along with an `@` file reference so Copilot CLI can map the error to the source code.
+
+```bash
+copilot
+
+> I'm getting this error:
+> AttributeError: 'NoneType' object has no attribute 'title'
+> at show_books (book_app.py:19)
+>
+> @samples/book-app-project/book_app.py Explain why and how to fix it
+```
+
+### Debugging with Test Case
+
+Describe the exact input and observed output to give Copilot CLI a concrete, reproducible test case to reason about.
+
+```bash
+copilot
+
+> @samples/book-app-buggy/books_buggy.py The remove_book function has a bug. When I try to remove "Dune",
+> it also removes "Dune Messiah". Debug this: explain the root cause and provide a fix.
+```
+
+### Trace an Issue Through Code
+
+Reference multiple files and ask Copilot CLI to follow the data flow across them to locate where the issue originates.
+
+```bash
+copilot
+
+> Users report that the book list numbering starts at 0 instead of 1.
+> @samples/book-app-buggy/book_app_buggy.py @samples/book-app-buggy/books_buggy.py
+> Trace through the list display flow and identify where the issue occurs
+```
+
+### Understanding Data Issues
+
+Include a data file alongside the code that reads it so Copilot CLI understands the full picture when suggesting error-handling improvements.
+
+```bash
+copilot
+
+> @samples/book-app-project/data.json @samples/book-app-project/books.py
+> Sometimes the JSON file gets corrupted and the app crashes. How should we handle this gracefully?
+```
+
+
+
+---
+
+
+
+Workflow 4: Test Generation - Generate comprehensive tests and edge cases automatically
+
+
+
+> **Try this first:** `@samples/book-app-project/books.py Generate pytest tests for all functions including edge cases`
+
+### The "Test Explosion" - 2 Tests vs 15+ Tests
+
+Manually writing tests, developers typically create 2-3 basic tests:
+- Test valid input
+- Test invalid input
+- Test an edge case
+
+Watch what happens when you ask Copilot CLI to generate comprehensive tests! This prompt uses a structured bullet list with an `@` file reference to guide Copilot CLI toward thorough test coverage:
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Generate comprehensive pytest tests. Include tests for:
+> - Adding books
+> - Removing books
+> - Finding by title
+> - Finding by author
+> - Marking as read
+> - Edge cases with empty data
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+**What you get**: 15+ comprehensive tests including:
+
+```python
+class TestBookCollection:
+ # Happy path
+ def test_add_book_creates_new_book(self):
+ ...
+ def test_list_books_returns_all_books(self):
+ ...
+
+ # Find operations
+ def test_find_book_by_title_case_insensitive(self):
+ ...
+ def test_find_book_by_title_returns_none_when_not_found(self):
+ ...
+ def test_find_by_author_partial_match(self):
+ ...
+ def test_find_by_author_case_insensitive(self):
+ ...
+
+ # Edge cases
+ def test_add_book_with_empty_title(self):
+ ...
+ def test_remove_nonexistent_book(self):
+ ...
+ def test_mark_as_read_nonexistent_book(self):
+ ...
+
+ # Data persistence
+ def test_save_books_persists_to_json(self):
+ ...
+ def test_load_books_handles_missing_file(self):
+ ...
+ def test_load_books_handles_corrupted_json(self):
+ ...
+
+ # Special characters
+ def test_add_book_with_unicode_characters(self):
+ ...
+ def test_find_by_author_with_special_characters(self):
+ ...
+```
+
+**Result**: In 30 seconds, you get edge case tests that would take an hour to think through and write.
+
+---
+
+### Unit Tests
+
+Target a single function and enumerate the input categories you want tested so Copilot CLI generates focused, thorough unit tests.
+
+```bash
+copilot
+
+> @samples/book-app-project/utils.py Generate comprehensive pytest tests for get_book_details covering:
+> - Valid input
+> - Empty strings
+> - Invalid year formats
+> - Very long titles
+> - Special characters in author names
+```
+
+### Running Tests
+
+Ask Copilot CLI a plain-English question about your toolchain. It can generate the right shell command for you.
+
+```bash
+copilot
+
+> How do I run the tests? Show me the pytest command.
+
+# Copilot CLI responds:
+# cd samples/book-app-project && python -m pytest tests/
+# Or for verbose output: python -m pytest tests/ -v
+# To see print statements: python -m pytest tests/ -s
+```
+
+### Test for Specific Scenarios
+
+List advanced or tricky scenarios you want covered so Copilot CLI goes beyond the happy path.
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Generate tests for these scenarios:
+> - Adding duplicate books (same title and author)
+> - Removing a book by partial title match
+> - Finding books when collection is empty
+> - File permission errors during save
+> - Concurrent access to the book collection
+```
+
+### Add Tests to Existing File
+
+Ask for *additional* tests for a single function so Copilot CLI generates new cases that complement what you already have.
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py
+> Generate additional tests for the find_by_author function with edge cases:
+> - Author name with hyphens (e.g., "Jean-Paul Sartre")
+> - Author with multiple first names
+> - Empty string as author
+> - Author name with accented characters
+```
+
+
+
+---
+
+
+
+Workflow 5: Git Integration - Commit messages, PR descriptions, /pr, /delegate, and /diff
+
+
+
+> 💡 **This workflow assumes basic git familiarity** (staging, committing, branches). If git is new to you, try the other four workflows first.
+
+### Generate Commit Messages
+
+> **Try this first:** `copilot -p "Generate a conventional commit message for: $(git diff --staged)"` — stage some changes, then run this to see Copilot CLI write your commit message.
+
+This example uses the `-p` inline prompt flag with shell command substitution to pipe `git diff` output directly into Copilot CLI for a one-shot commit message. The `$(...)` syntax runs the command inside the parentheses and inserts its output into the outer command.
+
+```bash
+
+# See what changed
+git diff --staged
+
+# Generate commit message using [Conventional Commit](https://github.com/github/copilot-cli-for-beginners/blob/main/GLOSSARY.md#conventional-commit) format
+# (structured messages like "feat(books): add search" or "fix(data): handle empty input")
+copilot -p "Generate a conventional commit message for: $(git diff --staged)"
+
+# Output: "feat(books): add partial author name search
+#
+# - Update find_by_author to support partial matches
+# - Add case-insensitive comparison
+# - Improve user experience when searching authors"
+```
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### Explain Changes
+
+Pipe the output of `git show` into a `-p` prompt to get a plain-English summary of the last commit.
+
+```bash
+# What did this commit change?
+copilot -p "Explain what this commit does: $(git show HEAD --stat)"
+```
+
+### PR Description
+
+Combine `git log` output with a structured prompt template to auto-generate a complete pull request description.
+
+```bash
+# Generate PR description from branch changes
+copilot -p "Generate a pull request description for these changes:
+$(git log main..HEAD --oneline)
+
+Include:
+- Summary of changes
+- Why these changes were made
+- Testing done
+- Breaking changes? (yes/no)"
+```
+
+### Using /pr in Interactive Mode for the Current Branch
+
+If you're working with a branch in Copilot CLI's interactive mode, you can use the `/pr` command to work with pull requests. Use `/pr` to view a PR, create a new PR, fix an existing PR, or let Copilot CLI auto-decide based on the branch state.
+
+```bash
+copilot
+
+> /pr [view|create|fix|auto]
+```
+
+### Review Before Push
+
+Use `git diff main..HEAD` inside a `-p` prompt for a quick pre-push sanity check across all branch changes.
+
+```bash
+# Last check before pushing
+copilot -p "Review these changes for issues before I push:
+$(git diff main..HEAD)"
+```
+
+### Using /delegate for Background Tasks
+
+The `/delegate` command hands off work to the Copilot coding agent on GitHub. Use the `/delegate` slash command (or the `&` shortcut) to offload a well-defined task to a background agent.
+
+```bash
+copilot
+
+> /delegate Add input validation to the login form
+
+# Or use the & prefix shortcut:
+> & Fix the typo in the README header
+
+# Copilot CLI:
+# 1. Commits your changes to a new branch
+# 2. Opens a draft pull request
+# 3. Works in the background on GitHub
+# 4. Requests your review when done
+```
+
+This is great for well-defined tasks you want completed while you focus on other work.
+
+### 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.
+
+```bash
+copilot
+
+# After making some changes...
+> /diff
+
+# Shows a visual diff of all files modified in this session
+# Great for reviewing before committing
+```
+
+
+
+---
+
+## Quick Tip: Research Before You Plan or Code
+
+When you need to investigate a library, understand best practices, or explore an unfamiliar topic, use `/research` to run a deep research investigation before writing any code:
+
+```bash
+copilot
+
+> /research What are the best Python libraries for validating user input in CLI apps?
+```
+
+Copilot searches GitHub repositories and web sources, then returns a summary with references. This is useful when you're about to start a new feature and want to make informed decisions first. You can share the results using `/share`.
+
+> 💡 **Tip**: `/research` works well *before* `/plan`. Research the approach, then plan the implementation.
+
+---
+
+## Putting It All Together: Bug Fix Workflow
+
+Here's a complete workflow for fixing a reported bug:
+
+```bash
+
+# 1. Understand the bug report
+copilot
+
+> Users report: 'Finding books by author name doesn't work for partial names'
+> @samples/book-app-project/books.py Analyze and identify the likely cause
+
+# 2. Debug the issue (continuing in same session)
+> Based on the analysis, show me the find_by_author function and explain the issue
+
+> Fix the find_by_author function to handle partial name matches
+
+# 3. Generate tests for the fix
+> @samples/book-app-project/books.py Generate pytest tests specifically for:
+> - Full author name match
+> - Partial author name match
+> - Case-insensitive matching
+> - Author name not found
+
+# 4. Generate commit message
+copilot -p "Generate commit message for: $(git diff --staged)"
+
+# Output: "fix(books): support partial author name search"
+```
+
+### Bug Fix Workflow Summary
+
+| Step | Action | Copilot Command |
+|------|--------|-----------------|
+| 1 | Understand the bug | `> [describe bug] @relevant-file.py Analyze the likely cause` |
+| 2 | Get detailed analysis | `> Show me the function and explain the issue` |
+| 3 | Implement the fix | `> Fix the [specific issue]` |
+| 4 | Generate tests | `> Generate tests for [specific scenarios]` |
+| 5 | Commit | `copilot -p "Generate commit message for: $(git diff --staged)"` |
+
+---
+
+# Practice
+
+
+
+Now it's your turn to apply these workflows.
+
+---
+
+## ▶️ Try It Yourself
+
+After completing the demos, try these variations:
+
+1. **Bug Detective Challenge**: Ask Copilot CLI to debug the `mark_as_read` function in `samples/book-app-buggy/books_buggy.py`. Did it explain why the function marks ALL books as read instead of just one?
+
+2. **Test Challenge**: Generate tests for the `add_book` function in the book app. Count how many edge cases Copilot CLI includes that you wouldn't have thought of.
+
+3. **Commit Message Challenge**: Make any small change to a book app file, stage it (`git add .`), then run:
+ ```bash
+ copilot -p "Generate a conventional commit message for: $(git diff --staged)"
+ ```
+ Is the message better than what you would have written quickly?
+
+**Self-Check**: You understand development workflows when you can explain why "debug this bug" is more powerful than "find bugs" (context matters!).
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Refactor, Test, and Ship
+
+The hands-on examples focused on `find_book_by_title` and code reviews. Now practice the same workflow skills on different functions in `book-app-project`:
+
+1. **Review**: Ask Copilot CLI to review `remove_book()` in `books.py` for edge cases and potential issues:
+ `@samples/book-app-project/books.py Review the remove_book() function. What happens if the title partially matches another book (e.g., "Dune" vs "Dune Messiah")? Are there any edge cases not handled?`
+2. **Refactor**: Ask Copilot CLI to improve `remove_book()` to handle edge cases like case-insensitive matching and returning useful feedback when a book isn't found
+3. **Test**: Generate pytest tests specifically for the improved `remove_book()` function, covering:
+ - Removing a book that exists
+ - Case-insensitive title matching
+ - A book that doesn't exist returns appropriate feedback
+ - Removing from an empty collection
+4. **Review**: Stage your changes and run `/review` to check for any remaining issues
+5. **Commit**: Generate a conventional commit message:
+ `copilot -p "Generate a conventional commit message for: $(git diff --staged)"`
+
+
+💡 Hints (click to expand)
+
+**Sample prompts for each step:**
+
+```bash
+copilot
+
+# Step 1: Review
+> @samples/book-app-project/books.py Review the remove_book() function. What edge cases are not handled?
+
+# Step 2: Refactor
+> Improve remove_book() to use case-insensitive matching and return a clear message when the book isn't found. Show me the before and after code.
+
+# Step 3: Test
+> Generate pytest tests for the improved remove_book() function, including:
+> - Removing a book that exists
+> - Case-insensitive matching ("dune" should remove "Dune")
+> - Book not found returns appropriate response
+> - Removing from an empty collection
+
+# Step 4: Review
+> /review
+
+# Step 5: Commit
+> Generate a conventional commit message for this refactor
+```
+
+**Tip:** After improving `remove_book()`, try asking Copilot CLI: "Are there any other functions in this file that could benefit from the same improvements?". It may suggest similar changes to `find_book_by_title()` or `find_by_author()`.
+
+
+
+### Bonus Challenge: Create an application with the Copilot CLI
+
+> 💡 **Note**: This GitHub Skills exercise uses **Node.js** rather than Python. The GitHub Copilot CLI techniques you'll practice - creating issues, generating code, and collaborating from the terminal - apply to any language.
+
+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)
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Using vague prompts like "Review this code" | Generic feedback that misses specific issues | Be specific: "Review for SQL injection, XSS, and auth issues" |
+| Not using `/review` for code reviews | Missing the optimized code-review agent | Use `/review` which is tuned for high signal-to-noise output |
+| Asking to "find bugs" without context | Copilot CLI doesn't know what bug you're experiencing | Describe the symptom: "Users report X happens when Y" |
+| Generating tests without specifying framework | Tests may use wrong syntax or assertion library | Specify: "Generate tests using Jest" or "using pytest" |
+
+### Troubleshooting
+
+**Review seems incomplete** - Be more specific about what to look for:
+
+```bash
+copilot
+
+# Instead of:
+> Review @samples/book-app-project/book_app.py
+
+# Try:
+> Review @samples/book-app-project/book_app.py for input validation, error handling, and edge cases
+```
+
+**Tests don't match my framework** - Specify the framework:
+
+```bash
+copilot
+
+> @samples/book-app-project/books.py Generate tests using pytest (not unittest)
+```
+
+**Refactoring changes behavior** - Ask Copilot CLI to preserve behavior:
+
+```bash
+copilot
+
+> @samples/book-app-project/book_app.py Refactor command handling to use dictionary dispatch. IMPORTANT: Maintain identical external behavior - no breaking changes
+```
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+
+
+1. **Code review** becomes comprehensive with specific prompts
+2. **Refactoring** is safer when you generate tests first
+3. **Debugging** benefits from showing Copilot CLI the error AND the code
+4. **Test generation** should include edge cases and error scenarios
+5. **Git integration** automates commit messages and PR descriptions
+
+> 📋 **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.
+
+---
+
+## ✅ Checkpoint: You've Mastered the Essentials
+
+**Congratulations!** You now have all the core skills to be productive with GitHub Copilot CLI:
+
+| Skill | Chapter | You Can Now... |
+|-------|---------|----------------|
+| Basic Commands | Ch 01 | Use interactive mode, plan mode, programmatic mode (-p), and slash commands |
+| Context | Ch 02 | Reference files with `@`, manage sessions, understand context windows |
+| Workflows | Ch 03 | Review code, refactor, debug, generate tests, integrate with git |
+
+Chapters 04-06 cover additional features that add even more power and are worthwhile to learn.
+
+---
+
+## 🛠️ Building Your Personal Workflow
+
+There's no single "right" way to use GitHub Copilot CLI. Here are a few tips as you develop your own patterns:
+
+> 📚 **Official Documentation**: [Copilot CLI best practices](https://docs.github.com/copilot/how-tos/copilot-cli/cli-best-practices) for recommended workflows and tips from GitHub.
+
+- **Start with `/plan`** for anything non-trivial. Refine the plan before execution - a good plan leads to better results.
+- **Save prompts that work well.** When Copilot CLI makes a mistake, note what went wrong. Over time, this becomes your personal playbook.
+- **Experiment freely.** Some developers prefer long, detailed prompts. Others prefer short prompts with follow-ups. Try different approaches and notice what feels natural.
+
+> 💡 **Coming up**: In Chapters 04 and 05, you'll learn how to codify your best practices into custom instructions and skills that Copilot CLI loads automatically.
+
+---
+
+## ➡️ What's Next
+
+The remaining chapters cover additional features that extend Copilot CLI's capabilities:
+
+| Chapter | What It Covers | When You'll Want It |
+|---------|----------------|---------------------|
+| Ch 04: Agents | Create specialized AI personas | When you want domain experts (frontend, security) |
+| Ch 05: Skills | Auto-load instructions for tasks | When you repeat the same prompts often |
+| Ch 06: MCP | Connect external services | When you need live data from GitHub, databases |
+
+**Recommendation**: Try the core workflows for a week, then return to Chapters 04-06 when you have specific needs.
+
+---
+
+## Continue to Additional Topics
+
+In **[Chapter 04: Agents and Custom Instructions](../04-agents-and-custom-instructions/)**, you'll learn:
+
+- Using built-in agents (`/plan`, `/review`)
+- Creating specialized agents (frontend expert, security auditor) with `.agent.md` files
+- Multi-agent collaboration patterns
+- Custom instruction files for project standards
+
+---
+
+**[← Back to Chapter 02](../02-context-and-conversations/)** | **[Continue to Chapter 04 →](../04-agents-and-custom-instructions/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md b/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md
new file mode 100644
index 000000000..0512ed473
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/04-agents-and-custom-instructions.md
@@ -0,0 +1,791 @@
+---
+title: '04 · Create Specialized AI Assistants'
+description: 'Mirror the source chapter on custom agents and custom instructions for GitHub Copilot CLI.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **What if you could hire a Python code reviewer, testing expert, and security reviewer... all in one tool?**
+
+In Chapter 03, you mastered the essential workflows: code review, refactoring, debugging, test generation, and git integration. Those make you highly productive with GitHub Copilot CLI. Now, let's take it further.
+
+So far, you've been using Copilot CLI as a general-purpose assistant. Agents let you give it a specific persona with built-in standards, like a code reviewer that enforces type hints and PEP 8, or a testing helper that writes pytest cases. You'll see how the same prompt gets noticeably better results when handled by an agent with targeted instructions.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Use built-in agents: Plan (`/plan`), Code-review (`/review`), and understand automatic agents (Explore, Task)
+- Create specialized agents using agent files (`.agent.md`)
+- Use agents for domain-specific tasks
+- Switch between agents using `/agent` and `--agent`
+- Write custom instruction files for project-specific standards
+
+> ⏱️ **Estimated Time**: ~55 minutes (20 min reading + 35 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: Hiring Specialists
+
+When you need help with your house, you don't call one "general helper." You call specialists:
+
+| Problem | Specialist | Why |
+|---------|------------|-----|
+| Leaky pipe | Plumber | Knows plumbing codes, has specialized tools |
+| Rewiring | Electrician | Understands safety requirements, up to code |
+| New roof | Roofer | Knows materials, local weather considerations |
+
+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.
+
+
+
+---
+
+# Using Agents
+
+Get started with built-in and custom agents right away.
+
+---
+
+## *New to Agents?* Start Here!
+Never used or made an agent? Here's all you need to know to get started for this course.
+
+1. **Try a *built-in* agent right now:**
+ ```bash
+ copilot
+ > /plan Add input validation for book year in the book app
+ ```
+ This invokes the Plan agent to create a step-by-step implementation plan.
+
+2. **See one of our custom agent examples:** It's simple to define an agent's instructions, look at our provided [python-reviewer.agent.md](https://github.com/github/copilot-cli-for-beginners/blob/main/github/agents/python-reviewer.agent.md) file to see the pattern.
+
+3. **Understand the core concept:** Agents are like consulting a specialist instead of a generalist. A "frontend agent" will focus on accessibility and component patterns automatically, you don't have to remind it because it is already specified in the agent's instructions.
+
+
+## Built-in Agents
+
+**You've already used some built-in agents in Chapter 03 Development Workflow!**
+
`/plan` and `/review` are actually built-in agents. Now you know what's happening under the hood. Here's the full list:
+
+| Agent | How to Invoke | What It Does |
+|-------|---------------|--------------|
+| **Plan** | `/plan` or `Shift+Tab` (cycle modes) | Creates step-by-step implementation plans before coding |
+| **Code-review** | `/review` | Reviews staged/unstaged changes with focused, actionable feedback |
+| **Init** | `/init` | Generates project configuration files (instructions, agents) |
+| **Explore** | *Automatic* | Used internally when you ask Copilot to explore or analyze the codebase |
+| **Task** | *Automatic* | Executes commands like tests, builds, lints, and dependency installs |
+
+
+
+**Built-in agents in action** - Examples of invoking Plan, Code-review, Explore, and Task
+
+```bash
+copilot
+
+# Invoke the Plan agent to create an implementation plan
+> /plan Add input validation for book year in the book app
+
+# Invoke the Code-review agent on your changes
+> /review
+
+# Explore and Task agents are invoked automatically when relevant:
+> Run the test suite # Uses Task agent
+
+> Explore how book data is loaded # Uses Explore agent
+```
+
+What about the Task Agent? It works behind the scenes to manage and track what is going on and to report back in a clean and clear format:
+
+| Outcome | What You See |
+|---------|--------------|
+| ✅ **Success** | Brief summary (e.g., "All 247 tests passed", "Build succeeded") |
+| ❌ **Failure** | Full output with stack traces, compiler errors, and detailed logs |
+
+
+> 📚 **Official Documentation**: [GitHub Copilot CLI Agents](https://docs.github.com/copilot/how-tos/use-copilot-agents/use-copilot-cli#use-custom-agents)
+
+---
+
+# Adding Agents to Copilot CLI
+
+You can simply define your own agents to be part of your workflow! Define once, then direct!
+
+
+
+## 🗂️ Add your agents
+
+Agent files are markdown files with a `.agent.md` extension. They have two parts: YAML frontmatter (metadata) and markdown instructions.
+
+> 💡 **New to YAML frontmatter?** It's a small block of settings at the top of the file, surrounded by `---` markers. YAML is just `key: value` pairs. The rest of the file is regular markdown.
+
+Here's a minimal agent:
+
+```markdown
+---
+name: my-reviewer
+description: Code reviewer focused on bugs and security issues
+---
+
+# Code Reviewer
+
+You are a code reviewer focused on finding bugs and security issues.
+
+When reviewing code, always check for:
+- SQL injection vulnerabilities
+- Missing error handling
+- Hardcoded secrets
+```
+
+> 💡 **Required vs Optional**: The `description` field is required. Other fields like `name`, `tools`, and `model` are optional.
+
+## Where to put agent files
+
+| Location | Scope | Best For |
+|----------|-------|----------|
+| `.github/agents/` | Project-specific | Team-shared agents with project conventions |
+| `~/.copilot/agents/` | Global (all projects) | Personal agents you use everywhere |
+
+**This project includes sample agent files in the [.github/agents/](../.github/agents/) folder**. You can write your own, or customize the ones already provided.
+
+
+📂 See the sample agents in this course
+
+| File | Description |
+|------|-------------|
+| `hello-world.agent.md` | Minimal example - start here |
+| `python-reviewer.agent.md` | Python code quality reviewer |
+| `pytest-helper.agent.md` | Pytest testing specialist |
+
+```bash
+# Or copy one to your personal agents folder (available in every project)
+cp .github/agents/python-reviewer.agent.md ~/.copilot/agents/
+```
+
+For more community agents, see [github/awesome-copilot](https://github.com/github/awesome-copilot)
+
+
+
+
+## 🚀 Two ways to use custom agents
+
+### Interactive mode
+Inside interactive mode, list agents using `/agent` and select the agent to start working with.
+Select an agent to continue your conversation with.
+
+```bash
+copilot
+> /agent
+```
+
+To change to a different agent, or to return to default mode, use the `/agent` command again.
+
+### Programmatic mode
+
+Launch straight into a new session with an agent.
+
+```bash
+copilot --agent python-reviewer
+> Review @samples/book-app-project/books.py
+```
+
+> 💡 **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**.
+
+---
+
+# Going Deeper with Agents
+
+
+
+> 💡 **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.
+
+Each topic below is self-contained. **Pick what interests you - you don't need to read them all at once.**
+
+| I want to... | Jump to |
+|---|---|
+| See why agents beat generic prompts | [Specialist vs Generic](#specialist-vs-generic-see-the-difference) |
+| Combine agents on a feature | [Working with Multiple Agents](#working-with-multiple-agents) |
+| Organize, name, and share agents | [Organizing & Sharing Agents](#organizing--sharing-agents) |
+| Set up always-on project context | [Configuring Your Project for Copilot](#configuring-your-project-for-copilot) |
+| Look up YAML properties and tools | [Agent File Reference](#agent-file-reference) |
+
+Select a scenario below to expand it.
+
+---
+
+
+
+Specialist vs Generic: See the Difference - Why agents produce better output than generic prompts
+
+## Specialist vs Generic: See the Difference
+
+This is where agents prove their value. Watch the difference:
+
+### Without an Agent (Generic Copilot)
+
+```bash
+copilot
+
+> Add a function to search books by year range in the book app
+```
+
+**Generic output**:
+```python
+def search_by_year_range(books, start_year, end_year):
+ results = []
+ for book in books:
+ if book['year'] >= start_year and book['year'] <= end_year:
+ results.append(book)
+ return results
+```
+
+Basic. Works. But missing a lot.
+
+---
+
+### With the Python Reviewer Agent
+
+```bash
+copilot
+
+> /agent
+# Select "python-reviewer"
+
+> Add a function to search books by year range in the book app
+```
+
+**Specialist output**:
+```python
+from typing import List, Dict, Any
+
+def search_by_year_range(
+ books: List[Dict[str, Any]],
+ start_year: int,
+ end_year: int
+) -> List[Dict[str, Any]]:
+ """
+ Search for books within a specified year range.
+
+ Args:
+ books: List of book dictionaries
+ start_year: Starting year (inclusive)
+ end_year: Ending year (inclusive)
+
+ Returns:
+ List of books published within the year range
+
+ Raises:
+ ValueError: If start_year is greater than end_year
+ TypeError: If year values are not integers
+ """
+ if not isinstance(start_year, int) or not isinstance(end_year, int):
+ raise TypeError("Year values must be integers")
+
+ if start_year > end_year:
+ raise ValueError(f"Start year ({start_year}) cannot be greater than end year ({end_year})")
+
+ return [
+ book for book in books
+ if isinstance(book.get('year'), int)
+ and start_year <= book['year'] <= end_year
+ ]
+```
+
+**What the python-reviewer agent automatically includes**:
+- ✅ Type hints on all parameters and return values
+- ✅ Comprehensive docstring with Args/Returns/Raises
+- ✅ Input validation with proper error handling
+- ✅ List comprehension for better performance
+- ✅ Edge case handling (missing/invalid year values)
+- ✅ PEP 8 compliant formatting
+- ✅ Defensive programming practices
+
+**The difference**: Same prompt, dramatically better output. The agent brings expertise you'd forget to ask for.
+
+
+
+---
+
+
+
+Working with Multiple Agents - Combine specialists, switch mid-session, agent-as-tools
+
+## Working with Multiple Agents
+
+The real power comes when specialists work together on a feature.
+
+### Example: Building a Simple Feature
+
+```bash
+copilot
+
+> I want to add a "search by year range" feature to the book app
+
+# Use python-reviewer for design
+> /agent
+# Select "python-reviewer"
+
+> @samples/book-app-project/books.py Design a find_by_year_range method. What's the best approach?
+
+# Switch to pytest-helper for test design
+> /agent
+# Select "pytest-helper"
+
+> @samples/book-app-project/tests/test_books.py Design test cases for a find_by_year_range method.
+> What edge cases should we cover?
+
+# Synthesize both designs
+> Create an implementation plan that includes the method implementation and comprehensive tests.
+```
+
+**The key insight**: You're the architect directing specialists. They handle the details, you handle the vision.
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies - your model, tools, and responses will differ from what's shown here.*
+
+
+
+### Agent as Tools
+
+When agents are configured, Copilot can also call them as tools during complex tasks. If you ask for a full-stack feature, Copilot may automatically delegate parts to the appropriate specialist agents.
+
+
+
+---
+
+
+
+Organizing & Sharing Agents - Naming, file placement, instruction files, and team sharing
+
+## Organizing & Sharing Agents
+
+### Naming Your Agents
+
+When you create agent files, the name matters. It's what you'll type after `/agent` or `--agent`, and what your teammates will see in the agent list.
+
+| ✅ Good Names | ❌ Avoid |
+|--------------|----------|
+| `frontend` | `my-agent` |
+| `backend-api` | `agent1` |
+| `security-reviewer` | `helper` |
+| `react-specialist` | `code` |
+| `python-backend` | `assistant` |
+
+**Naming conventions:**
+- Use lowercase with hyphens: `my-agent-name.agent.md`
+- Include the domain: `frontend`, `backend`, `devops`, `security`
+- Be specific when needed: `react-typescript` vs just `frontend`
+
+---
+
+### Sharing with Your Team
+
+Place agent files in `.github/agents/` and they're version controlled. Push to your repo and every team member gets them automatically. But agents are just one type of file Copilot reads from your project. It also supports **instruction files** that apply automatically to every session, without anyone needing to run `/agent`.
+
+Think of it this way: agents are specialists you call on, and instruction files are team rules that are always active.
+
+### Where to Put Your 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:
+
+
+
+**Start simple:** Create a single `*.agent.md` file in your project folder. Move it to a permanent location once you're happy with it.
+
+Beyond agent files, Copilot also reads **project-level instruction files** automatically, no `/agent` needed. See [Configuring Your Project for Copilot](#configuring-your-project-for-copilot) below for `AGENTS.md`, `.instructions.md`, and `/init`.
+
+
+
+---
+
+
+
+Configuring Your Project for Copilot - AGENTS.md, instruction files, and /init setup
+
+## Configuring Your Project for Copilot
+
+Agents are specialists you invoke on demand. **Project configuration files** are different: Copilot reads them automatically in every session to understand your project's conventions, tech stack, and rules. No one needs to run `/agent`; the context is always active for everyone working in the repo.
+
+### Quick Setup with /init
+
+The fastest way to get started is to let Copilot generate configuration files for you:
+
+```bash
+copilot
+> /init
+```
+
+Copilot will scan your project and create tailored instruction files. You can edit them afterwards.
+
+### Instruction File Formats
+
+| File | Scope | Notes |
+|------|-------|-------|
+| `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 |
+| `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.
+
+### AGENTS.md
+
+`AGENTS.md` is the recommended format. It's an [open standard](https://agents.md/) that works across Copilot and other AI coding tools. Place it in your repository root and Copilot reads it automatically. This project's own [AGENTS.md](https://github.com/github/copilot-cli-for-beginners/blob/main/AGENTS.md) is a working example.
+
+A typical `AGENTS.md` describes your project context, code style, security requirements, and testing standards. Use `/init` to generate one, or write your own following the pattern in our example file.
+
+### Custom Instruction Files (.instructions.md)
+
+For teams that want more granular control, split instructions into topic-specific files. Each file covers one concern and applies automatically:
+
+```
+.github/
+└── instructions/
+ ├── python-standards.instructions.md
+ ├── security-checklist.instructions.md
+ └── api-design.instructions.md
+```
+
+> 💡 **Note**: Instruction files work with any language. This example uses Python to match our course project, but you can create similar files for TypeScript, Go, Rust, or any technology your team uses.
+
+**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
+
+If you need Copilot to ignore all project-specific configurations (useful for debugging or comparing behavior):
+
+```bash
+copilot --no-custom-instructions
+```
+
+
+
+---
+
+
+
+Agent File Reference - YAML properties, tool aliases, and complete examples
+
+## Agent File Reference
+
+### A More Complete Example
+
+You've seen the [minimal agent format](#-add-your-agents) above. Here's a more comprehensive agent that uses the `tools` property. Create `~/.copilot/agents/python-reviewer.agent.md`:
+
+```markdown
+---
+name: python-reviewer
+description: Python code quality specialist for reviewing Python projects
+tools: ["read", "edit", "search", "execute"]
+---
+
+# Python Code Reviewer
+
+You are a Python specialist focused on code quality and best practices.
+
+**Your focus areas:**
+- Code quality (PEP 8, type hints, docstrings)
+- Performance optimization (list comprehensions, generators)
+- Error handling (proper exception handling)
+- Maintainability (DRY principles, clear naming)
+
+**Code style requirements:**
+- Use Python 3.10+ features (dataclasses, type hints, pattern matching)
+- Follow PEP 8 naming conventions
+- Use context managers for file I/O
+- All functions must have type hints and docstrings
+
+**When reviewing code, always check:**
+- Missing type hints on function signatures
+- Mutable default arguments
+- Proper error handling (no bare except)
+- Input validation completeness
+```
+
+### YAML Properties
+
+| Property | Required | Description |
+|----------|----------|-------------|
+| `name` | No | Display name (defaults to filename) |
+| `description` | **Yes** | What the agent does - helps Copilot understand when to suggest it |
+| `tools` | No | List of allowed tools (omit = all tools available). See tool aliases below. |
+| `target` | No | Limit to `vscode` or `github-copilot` only |
+
+### Tool Aliases
+
+Use these names in the `tools` list:
+- `read` - Read file contents
+- `edit` - Edit files
+- `search` - Search files (grep/glob)
+- `execute` - Run shell commands (also: `shell`, `Bash`)
+- `agent` - Invoke other custom agents
+
+> 📖 **Official docs**: [Custom agents configuration](https://docs.github.com/copilot/reference/custom-agents-configuration)
+>
+> ⚠️ **VS Code Only**: The `model` property (for selecting AI models) works in VS Code but is not supported in GitHub Copilot CLI. You can safely include it for cross-platform agent files. GitHub Copilot CLI will ignore it.
+
+### More Agent Templates
+
+> 💡 **Note for beginners**: The examples below are templates. **Replace the specific technologies with whatever your project uses.** The important thing is the *structure* of the agent, not the specific technologies mentioned.
+
+This project includes working examples in the [.github/agents/](../.github/agents/) folder:
+- [hello-world.agent.md](https://github.com/github/copilot-cli-for-beginners/blob/main/github/agents/hello-world.agent.md) - Minimal example, start here
+- [python-reviewer.agent.md](https://github.com/github/copilot-cli-for-beginners/blob/main/github/agents/python-reviewer.agent.md) - Python code quality reviewer
+- [pytest-helper.agent.md](https://github.com/github/copilot-cli-for-beginners/blob/main/github/agents/pytest-helper.agent.md) - Pytest testing specialist
+
+For community agents, see [github/awesome-copilot](https://github.com/github/awesome-copilot).
+
+
+
+---
+
+# Practice
+
+
+
+Create your own agents and see them in action.
+
+---
+
+## ▶️ Try It Yourself
+
+```bash
+
+# Create the agents directory (if it doesn't exist)
+mkdir -p .github/agents
+
+# Create a code reviewer agent
+cat > .github/agents/reviewer.agent.md << 'EOF'
+---
+name: reviewer
+description: Senior code reviewer focused on security and best practices
+---
+
+# Code Reviewer Agent
+
+You are a senior code reviewer focused on code quality.
+
+**Review priorities:**
+1. Security vulnerabilities
+2. Performance issues
+3. Maintainability concerns
+4. Best practice violations
+
+**Output format:**
+Provide issues as a numbered list with severity tags:
+[CRITICAL], [HIGH], [MEDIUM], [LOW]
+EOF
+
+# Create a documentation agent
+cat > .github/agents/documentor.agent.md << 'EOF'
+---
+name: documentor
+description: Technical writer for clear and complete documentation
+---
+
+# Documentation Agent
+
+You are a technical writer who creates clear documentation.
+
+**Documentation standards:**
+- Start with a one-sentence summary
+- Include usage examples
+- Document parameters and return values
+- Note any gotchas or limitations
+EOF
+
+# Now use them
+copilot --agent reviewer
+> Review @samples/book-app-project/books.py
+
+# Or switch agents
+copilot
+> /agent
+# Select "documentor"
+> Document @samples/book-app-project/books.py
+```
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Build a Specialized Agent Team
+
+The hands-on example created `reviewer` and `documentor` agents. Now practice creating and using agents for a different task - improving data validation in the book app:
+
+1. Create 3 agent files (`.agent.md`) tailored to the book app, one per agent, placed in `.github/agents/`
+2. Your agents:
+ - **data-validator**: checks `data.json` for missing or malformed data (empty authors, year=0, missing fields)
+ - **error-handler**: reviews Python code for inconsistent error handling and suggests a unified approach
+ - **doc-writer**: generates or updates docstrings and README content
+3. Use each agent on the book app:
+ - `data-validator` → audit `@samples/book-app-project/data.json`
+ - `error-handler` → review `@samples/book-app-project/books.py` and `@samples/book-app-project/utils.py`
+ - `doc-writer` → add docstrings to `@samples/book-app-project/books.py`
+4. Collaborate: use `error-handler` to identify error-handling gaps, then `doc-writer` to document the improved approach
+
+**Success criteria**: You have 3 working agents that produce consistent, high-quality output and you can switch between them with `/agent`.
+
+
+💡 Hints (click to expand)
+
+**Starter templates**: create one file per agent in `.github/agents/`:
+
+`data-validator.agent.md`:
+```markdown
+---
+description: Analyzes JSON data files for missing or malformed entries
+---
+
+You analyze JSON data files for missing or malformed entries.
+
+**Focus areas:**
+- Empty or missing author fields
+- Invalid years (year=0, future years, negative years)
+- Missing required fields (title, author, year, read)
+- Duplicate entries
+```
+
+`error-handler.agent.md`:
+```markdown
+---
+description: Reviews Python code for error handling consistency
+---
+
+You review Python code for error handling consistency.
+
+**Standards:**
+- No bare except clauses
+- Use custom exceptions where appropriate
+- All file operations use context managers
+- Consistent return types for success/failure
+```
+
+`doc-writer.agent.md`:
+```markdown
+---
+description: Technical writer for clear Python documentation
+---
+
+You are a technical writer who creates clear Python documentation.
+
+**Standards:**
+- Google-style docstrings
+- Include parameter types and return values
+- Add usage examples for public methods
+- Note any exceptions raised
+```
+
+**Testing your agents:**
+
+> 💡 **Note:** You should already have `samples/book-app-project/data.json` in your local copy of this repo. If it is missing, download the original version from the source repo:
+> [data.json](https://github.com/github/copilot-cli-for-beginners/blob/main/samples/book-app-project/data.json)
+
+```bash
+copilot
+> /agent
+# Select "data-validator" from the list
+> @samples/book-app-project/data.json Check for books with empty author fields or invalid years
+```
+
+**Tip:** The `description` field in the YAML frontmatter is required for agents to work.
+
+
+
+### Bonus Challenge: Instruction Library
+
+You've built agents you invoke on demand. Now try the other side: **instruction files** that Copilot reads automatically in every session, no `/agent` needed.
+
+Create a `.github/instructions/` folder with at least 3 instruction files:
+- `python-style.instructions.md` for enforcing PEP 8 and type hint conventions
+- `test-standards.instructions.md` for enforcing pytest conventions in test files
+- `data-quality.instructions.md` for validating JSON data entries
+
+Test each instruction file on the book app code.
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Missing `description` in agent frontmatter | Agent won't load or won't be discoverable | Always include `description:` in YAML frontmatter |
+| Wrong file location for agents | Agent not found when you try to use it | Place in `~/.copilot/agents/` (personal) or `.github/agents/` (project) |
+| Using `.md` instead of `.agent.md` | File may not be recognized as an agent | Name files like `python-reviewer.agent.md` |
+| Overly long agent prompts | May hit the 30,000 character limit | Keep agent definitions focused; use skills for detailed instructions |
+
+### Troubleshooting
+
+**Agent not found** - Check that the agent file exists in one of these locations:
+- `~/.copilot/agents/`
+- `.github/agents/`
+
+List available agents:
+
+```bash
+copilot
+> /agent
+# Shows all available agents
+```
+
+**Agent not following instructions** - Be explicit in your prompts and add more detail to agent definitions:
+- Specific frameworks/libraries with versions
+- Team conventions
+- Example code patterns
+
+**Custom instructions not loading** - Run `/init` in your project to set up project-specific instructions:
+
+```bash
+copilot
+> /init
+```
+
+Or check if they're disabled:
+```bash
+# Don't use --no-custom-instructions if you want them loaded
+copilot # This loads custom instructions by default
+```
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+1. **Built-in agents**: `/plan` and `/review` are directly invoked; Explore and Task work automatically
+2. **Custom agents** are specialists defined in `.agent.md` files
+3. **Good agents** have clear expertise, standards, and output formats
+4. **Multi-agent collaboration** solves complex problems by combining expertise
+5. **Instruction files** (`.instructions.md`) encode team standards for automatic application
+6. **Consistent output** comes from well-defined agent instructions
+
+> 📋 **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.
+
+---
+
+## ➡️ What's Next
+
+Agents change *how Copilot approaches and takes targeted actions* in your code. Next, you'll learn about **skills** - which change *what steps* it follows. Wondering how agents and skills differ? Chapter 05 covers that head-on.
+
+In **[Chapter 05: Skills System](../05-skills/)**, you'll learn:
+
+- How skills auto-trigger from your prompts (no slash command needed)
+- Installing community skills
+- Creating custom skills with SKILL.md files
+- The difference between agents, skills, and MCP
+- When to use each one
+
+---
+
+**[← Back to Chapter 03](../03-development-workflows/)** | **[Continue to Chapter 05 →](../05-skills/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/05-skills.md b/website/src/content/docs/learning-hub/cli-for-beginners/05-skills.md
new file mode 100644
index 000000000..6cbe76177
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/05-skills.md
@@ -0,0 +1,872 @@
+---
+title: '05 · Automate Repetitive Tasks'
+description: 'Mirror the source chapter on skills that load automatically for repeated GitHub Copilot CLI workflows.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **What if Copilot could automatically apply your team's best practices without you having to explain them every time?**
+
+In this chapter, you'll learn about Agent Skills: folders of instructions that Copilot automatically loads when relevant to your task. While agents change *how* Copilot thinks, skills teach Copilot *specific ways to complete tasks*. You'll create a security audit skill that Copilot applies whenever you ask about security, build team-standard review criteria that ensure consistent code quality, and learn how skills work across Copilot CLI, VS Code, and the Copilot coding agent.
+
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Understand how Agent Skills work and when to use them
+- Create custom skills with SKILL.md files
+- Use community skills from shared repositories
+- Know when to use skills vs agents vs MCP
+
+> ⏱️ **Estimated Time**: ~55 minutes (20 min reading + 35 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: Power Tools
+
+A general-purpose drill is useful, but specialized attachments make it powerful.
+
+
+
+Skills work the same way. Just like swapping drill bits for different jobs, you can add skills to Copilot for different tasks:
+
+| Skill Attachment | Purpose |
+|------------|---------|
+| `commit` | Generate consistent commit messages |
+| `security-audit` | Check for OWASP vulnerabilities |
+| `generate-tests` | Create comprehensive pytest tests |
+| `code-checklist` | Apply team code quality standards |
+
+
+
+*Skills are specialized attachments that extend what Copilot can do*
+
+---
+
+# How Skills Work
+
+
+
+Learn what skills are, why they matter, and how they differ from agents and MCP.
+
+---
+
+## *New to Skills?* Start Here!
+
+1. **See what skills are already available:**
+ ```bash
+ copilot
+ > /skills list
+ ```
+ This shows all skills Copilot can find in your project and personal folders.
+
+2. **Look at a real skill file:** Check out our provided [code-checklist SKILL.md](https://github.com/github/copilot-cli-for-beginners/blob/main/github/skills/code-checklist/SKILL.md) to see the pattern. It's just YAML frontmatter plus markdown instructions.
+
+3. **Understand the core concept:** Skills are task-specific instructions that Copilot loads *automatically* when your prompt matches the skill's description. You don't need to activate them, just ask naturally.
+
+
+## Understanding Skills
+
+Agent Skills are folders containing instructions, scripts, and resources that Copilot **automatically loads when relevant** to your task. Copilot reads your prompt, checks if any skills match, and applies the relevant instructions automatically.
+
+```bash
+copilot
+
+> Check books.py against our quality checklist
+# Copilot detects this matches your "code-checklist" skill
+# and automatically applies its Python quality checklist
+
+> Generate tests for the BookCollection class
+# Copilot loads your "pytest-gen" skill
+# and applies your preferred test structure
+
+> What are the code quality issues in this file?
+# Copilot loads your "code-checklist" skill
+# and checks against your team's standards
+```
+
+> 💡 **Key Insight**: Skills are **automatically triggered** based on your prompt matching the skill's description. Just ask naturally and Copilot applies relevant skills behind the scenes. You can also invoke skills directly as well which you'll learn about next.
+
+> 🧰 **Ready-to-use templates**: Check out the [.github/skills](../.github/skills/) folder for simple copy-paste skills you can try out.
+
+### Direct Slash Command Invocation
+
+While auto-triggering is the primary way skills work, you can also **invoke skills directly** using their name as a slash command:
+
+```bash
+> /generate-tests Create tests for the user authentication module
+
+> /code-checklist Check books.py for code quality issues
+
+> /security-audit Check the API endpoints for vulnerabilities
+```
+
+This gives you explicit control when you want to ensure a specific skill is used.
+
+> 📝 **Skills vs Agents Invocation**: Don't confuse skill invocation with agent invocation:
+> - **Skills**: `/skill-name `, e.g., `/code-checklist Check this file`
+> - **Agents**: `/agent` (select from list) or `copilot --agent ` (command line)
+>
+> If you have both a skill and an agent with the same name (e.g., "code-reviewer"), typing `/code-reviewer` invokes the **skill**, not the agent.
+
+### How Do I Know a Skill Was Used?
+
+You can ask Copilot directly:
+
+```bash
+> What skills did you use for that response?
+
+> What skills do you have available for security reviews?
+```
+
+### Skills vs Agents vs MCP
+
+Skills are just one piece of GitHub Copilot's extensibility model. Here's how they compare to agents and MCP servers.
+
+> *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.*
+
+
+
+| Feature | What It Does | When to Use |
+|---------|--------------|-------------|
+| **Agents** | Changes how AI thinks | Need specialized expertise across many tasks |
+| **Skills** | Provides task-specific instructions | Specific, repeatable tasks with detailed steps |
+| **MCP** | Connects external services | Need live data from APIs |
+
+Use agents for broad expertise, skills for specific task instructions, and MCP for external data. An agent can use one or more skills during a conversation. For example, when you ask an agent to check your code, it might apply both a `security-audit` skill and a `code-checklist` skill automatically.
+
+> 📚 **Learn More**: See the official [About Agent Skills](https://docs.github.com/copilot/concepts/agents/about-agent-skills) documentation for the complete reference on skill formats and best practices.
+
+---
+
+## From Manual Prompts to Automatic Expertise
+
+Before diving into how to create skills, let's see *why* they're worth learning. Once you see the consistency gains, the "how" will make more sense.
+
+### Before Skills: Inconsistent Reviews
+
+Every code review, you might forget something:
+
+```bash
+copilot
+
+> Review this code for issues
+# Generic review - might miss your team's specific concerns
+```
+
+Or you write a long prompt every time:
+
+```bash
+> Review this code checking for bare except clauses, missing type hints,
+> mutable default arguments, missing context managers for file I/O,
+> functions over 50 lines, print statements in production code...
+```
+
+Time: **30+ seconds** to type. Consistency: **varies by memory**.
+
+### After Skills: Automatic Best Practices
+
+With a `code-checklist` skill installed, just ask naturally:
+
+```bash
+copilot
+
+> Check the book collection code for quality issues
+```
+
+**What happens behind the scenes**:
+1. Copilot sees "code quality" and "issues" in your prompt
+2. Checks skill descriptions, finds your `code-checklist` skill matches
+3. Automatically loads your team's quality checklist
+4. Applies all checks without you listing them
+
+
+
+*Just ask naturally. Copilot matches your prompt to the right skill and applies it automatically.*
+
+**Output**:
+```
+## Code Checklist: books.py
+
+### Code Quality
+- [PASS] All functions have type hints
+- [PASS] No bare except clauses
+- [PASS] No mutable default arguments
+- [PASS] Context managers used for file I/O
+- [PASS] Functions are under 50 lines
+- [PASS] Variable and function names follow PEP 8
+
+### Input Validation
+- [FAIL] User input is not validated - add_book() accepts any year value
+- [FAIL] Edge cases not fully handled - empty strings accepted for title/author
+- [PASS] Error messages are clear and helpful
+
+### Testing
+- [FAIL] No corresponding pytest tests found
+
+### Summary
+3 items need attention before merge
+```
+
+**The difference**: Your team's standards are applied automatically, every time, without typing them out.
+
+---
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+## Consistency at Scale: Team PR Review Skill
+
+Imagine your team has a 10-point PR checklist. Without a skill, every developer must remember all 10 points, and someone always forgets one of them. With a `pr-review` skill, the entire team gets consistent reviews:
+
+```bash
+copilot
+
+> Can you review this PR?
+```
+
+Copilot automatically loads your team's `pr-review` skill and checks all 10 points:
+
+```
+PR Review: feature/user-auth
+
+## Security ✅
+- No hardcoded secrets
+- Input validation present
+- No bare except clauses
+
+## Code Quality ⚠️
+- [WARN] print statement on line 45 - remove before merge
+- [WARN] TODO on line 78 missing issue reference
+- [WARN] Missing type hints on public functions
+
+## Testing ✅
+- New tests added
+- Edge cases covered
+
+## Documentation ❌
+- [FAIL] Breaking change not documented in CHANGELOG
+- [FAIL] API changes need OpenAPI spec update
+```
+
+**The power**: Every team member applies the same standards automatically. New hires don't need to memorize the checklist because the skill handles it.
+
+---
+
+# Creating Custom Skills
+
+
+
+Build your own skills from SKILL.md files.
+
+---
+
+## Skill Locations
+
+Skills are stored in `.github/skills/` (project-specific) or `~/.copilot/skills/` (user level).
+
+### How Copilot Finds Skills
+
+Copilot automatically scans these locations for skills:
+
+| Location | Scope |
+|----------|-------|
+| `.github/skills/` | Project-specific (shared with team via git) |
+| `~/.copilot/skills/` | User-specific (your personal skills) |
+
+### Skill Structure
+
+Each skill lives in its own folder with a `SKILL.md` file. You can optionally include scripts, examples, or other resources:
+
+```
+.github/skills/
+└── my-skill/
+ ├── SKILL.md # Required: Skill definition and instructions
+ ├── examples/ # Optional: Example files Copilot can reference
+ │ └── sample.py
+ └── scripts/ # Optional: Scripts the skill can use
+ └── validate.sh
+```
+
+> 💡 **Tip**: The directory name should match the `name` in your SKILL.md frontmatter (lowercase with hyphens).
+
+### SKILL.md Format
+
+Skills use a simple markdown format with YAML frontmatter:
+
+```markdown
+---
+name: code-checklist
+description: Comprehensive code quality checklist with security, performance, and maintainability checks
+license: MIT
+---
+
+# Code Checklist
+
+When checking code, look for:
+
+## Security
+- SQL injection vulnerabilities
+- XSS vulnerabilities
+- Authentication/authorization issues
+- Sensitive data exposure
+
+## Performance
+- N+1 query problems (running one query per item instead of one query for all items)
+- Unnecessary loops or computations
+- Memory leaks
+- Blocking operations
+
+## Maintainability
+- Function length (flag functions > 50 lines)
+- Code duplication
+- Missing error handling
+- Unclear naming
+
+## Output Format
+Provide issues as a numbered list with severity:
+- [CRITICAL] - Must fix before merge
+- [HIGH] - Should fix before merge
+- [MEDIUM] - Should address soon
+- [LOW] - Nice to have
+```
+
+**YAML Properties:**
+
+| Property | Required | Description |
+|----------|----------|-------------|
+| `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 |
+
+> 📖 **Official docs**: [About Agent Skills](https://docs.github.com/copilot/concepts/agents/about-agent-skills)
+
+### Creating Your First Skill
+
+Let's build a security audit skill that checks for OWASP Top 10 vulnerabilities:
+
+```bash
+# Create skill directory
+mkdir -p .github/skills/security-audit
+
+# Create the SKILL.md file
+cat > .github/skills/security-audit/SKILL.md << 'EOF'
+---
+name: security-audit
+description: Security-focused code review checking OWASP (Open Web Application Security Project) Top 10 vulnerabilities
+---
+
+# Security Audit
+
+Perform a security audit checking for:
+
+## Injection Vulnerabilities
+- SQL injection (string concatenation in queries)
+- Command injection (unsanitized shell commands)
+- LDAP injection
+- XPath injection
+
+## Authentication Issues
+- Hardcoded credentials
+- Weak password requirements
+- Missing rate limiting
+- Session management flaws
+
+## Sensitive Data
+- Plaintext passwords
+- API keys in code
+- Logging sensitive information
+- Missing encryption
+
+## Access Control
+- Missing authorization checks
+- Insecure direct object references
+- Path traversal vulnerabilities
+
+## Output
+For each issue found, provide:
+1. File and line number
+2. Vulnerability type
+3. Severity (CRITICAL/HIGH/MEDIUM/LOW)
+4. Recommended fix
+EOF
+
+# Test your skill (skills load automatically based on your prompt)
+copilot
+
+> @samples/book-app-project/ Check this code for security vulnerabilities
+# Copilot detects "security vulnerabilities" matches your skill
+# and automatically applies its OWASP checklist
+```
+
+**Expected output** (your results will vary):
+
+```
+Security Audit: book-app-project
+
+[HIGH] Hardcoded file path (book_app.py, line 12)
+ File path is hardcoded rather than configurable
+ Fix: Use environment variable or config file
+
+[MEDIUM] No input validation (book_app.py, line 34)
+ User input passed directly to function without sanitization
+ Fix: Add input validation before processing
+
+✅ No SQL injection found
+✅ No hardcoded credentials found
+```
+
+---
+
+## Writing Good Skill Descriptions
+
+The `description` field in your SKILL.md is crucial! It's how Copilot decides whether to load your skill:
+
+```markdown
+---
+name: security-audit
+description: Use for security reviews, vulnerability scanning,
+ checking for SQL injection, XSS, authentication issues,
+ OWASP Top 10 vulnerabilities, and security best practices
+---
+```
+
+> 💡 **Tip**: Include keywords that match how you naturally ask questions. If you say "security review," include "security review" in the description.
+
+### Combining Skills with Agents
+
+Skills and agents work together. The agent provides expertise, the skill provides specific instructions:
+
+```bash
+# Start with a code-reviewer agent
+copilot --agent code-reviewer
+
+> Check the book app for quality issues
+# code-reviewer agent's expertise combines
+# with your code-checklist skill's checklist
+```
+
+---
+
+# Managing and Sharing Skills
+
+Discover installed skills, find community skills, and share your own.
+
+
+
+---
+
+## Managing Skills with the `/skills` Command
+
+Use the `/skills` command to manage your installed skills:
+
+| Command | What It Does |
+|---------|--------------|
+| `/skills list` | Show all installed skills |
+| `/skills info ` | Get details about a specific skill |
+| `/skills add ` | Enable a skill (from a repository or marketplace) |
+| `/skills remove ` | Disable or uninstall a skill |
+| `/skills reload` | Reload skills after editing SKILL.md files |
+
+> 💡 **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
+copilot
+
+> /skills 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
+...
+
+> /skills info security-audit
+
+Skill: security-audit
+Source: Project
+Location: .github/skills/security-audit/SKILL.md
+Description: Security-focused code review checking OWASP Top 10 vulnerabilities
+```
+
+---
+
+
+See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+### When to Use `/skills reload`
+
+After creating or editing a skill's SKILL.md file, run `/skills reload` to pick up the changes without restarting Copilot:
+
+```bash
+# Edit your skill file
+# Then in Copilot:
+> /skills reload
+Skills reloaded successfully.
+```
+
+> 💡 **Good to know**: Skills remain effective even after using `/compact` to summarize your conversation history. No need to reload after compacting.
+
+---
+
+## Finding and Using Community Skills
+
+### Using Plugins to Install Skills
+
+> 💡 **What are plugins?** Plugins are installable packages that can bundle skills, agents, and MCP server configurations together. Think of them as "app store" extensions for Copilot CLI.
+
+The `/plugin` command lets you browse and install these packages:
+
+```bash
+copilot
+
+> /plugin list
+# Shows installed plugins
+
+> /plugin marketplace
+# Browse available plugins
+
+> /plugin install
+# Install a plugin from the marketplace
+```
+
+Plugins can bundle multiple capabilities together - a single plugin might include related skills, agents, and MCP server configurations that work together.
+
+### Community Skill Repositories
+
+Pre-made skills are also available from community repositories:
+
+- **[Awesome Copilot](https://github.com/github/awesome-copilot)** - Official GitHub Copilot resources including skills documentation and examples
+
+### Installing a Community Skill Manually
+
+If you find a skill in a GitHub repository, copy its folder into your skills directory:
+
+```bash
+# Clone the awesome-copilot repository
+git clone https://github.com/github/awesome-copilot.git /tmp/awesome-copilot
+
+# Copy a specific skill to your project
+cp -r /tmp/awesome-copilot/skills/code-checklist .github/skills/
+
+# Or for personal use across all projects
+cp -r /tmp/awesome-copilot/skills/code-checklist ~/.copilot/skills/
+```
+
+> ⚠️ **Review before installing**: Always read a skill's `SKILL.md` before copying it into your project. Skills control what Copilot does, and a malicious skill could instruct it to run harmful commands or modify code in unexpected ways.
+
+---
+
+# Practice
+
+
+
+Apply what you've learned by building and testing your own skills.
+
+---
+
+## ▶️ Try It Yourself
+
+### Build More Skills
+
+Here are two more skills showing different patterns. Follow the same `mkdir` + `cat` workflow from "Creating Your First Skill" above or copy and paste the skills into the proper location. More examples are available in [.github/skills](../.github/skills).
+
+### pytest Test Generation Skill
+
+A skill that ensures consistent pytest structure across your codebase:
+
+```bash
+mkdir -p .github/skills/pytest-gen
+
+cat > .github/skills/pytest-gen/SKILL.md << 'EOF'
+---
+name: pytest-gen
+description: Generate comprehensive pytest tests with fixtures and edge cases
+---
+
+# pytest Test Generation
+
+Generate pytest tests that include:
+
+## Test Structure
+- Use pytest conventions (test_ prefix)
+- One assertion per test when possible
+- Clear test names describing expected behavior
+- Use fixtures for setup/teardown
+
+## Coverage
+- Happy path scenarios
+- Edge cases: None, empty strings, empty lists
+- Boundary values
+- Error scenarios with pytest.raises()
+
+## Fixtures
+- Use @pytest.fixture for reusable test data
+- Use tmpdir/tmp_path for file operations
+- Mock external dependencies with pytest-mock
+
+## Output
+Provide complete, runnable test file with proper imports.
+EOF
+```
+
+### Team PR Review Skill
+
+A skill that enforces consistent PR review standards across your team:
+
+```bash
+mkdir -p .github/skills/pr-review
+
+cat > .github/skills/pr-review/SKILL.md << 'EOF'
+---
+name: pr-review
+description: Team-standard PR review checklist
+---
+
+# PR Review
+
+Review code changes against team standards:
+
+## Security Checklist
+- [ ] No hardcoded secrets or API keys
+- [ ] Input validation on all user data
+- [ ] No bare except clauses
+- [ ] No sensitive data in logs
+
+## Code Quality
+- [ ] Functions under 50 lines
+- [ ] No print statements in production code
+- [ ] Type hints on public functions
+- [ ] Context managers for file I/O
+- [ ] No TODOs without issue references
+
+## Testing
+- [ ] New code has tests
+- [ ] Edge cases covered
+- [ ] No skipped tests without explanation
+
+## Documentation
+- [ ] API changes documented
+- [ ] Breaking changes noted
+- [ ] README updated if needed
+
+## Output Format
+Provide results as:
+- ✅ PASS: Items that look good
+- ⚠️ WARN: Items that could be improved
+- ❌ FAIL: Items that must be fixed before merge
+EOF
+```
+
+### Go Further
+
+1. **Skill Creation Challenge**: Create a `quick-review` skill that does a 3-point checklist:
+ - Bare except clauses
+ - Missing type hints
+ - Unclear variable names
+
+ Test it by asking: "Do a quick review of books.py"
+
+2. **Skill Comparison**: Time yourself writing a detailed security review prompt manually. Then just ask "Check for security issues in this file" and let your security-audit skill load automatically. How much time did the skill save?
+
+3. **Team Skill Challenge**: Think about your team's code review checklist. Could you encode it as a skill? Write down 3 things the skill should always check.
+
+**Self-Check**: You understand skills when you can explain why the `description` field matters (it's how Copilot decides whether to load your skill).
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Build a Book Summary Skill
+
+The examples above created `pytest-gen` and `pr-review` skills. Now practice creating a completely different kind of skill: one for generating formatted output from data.
+
+1. List your current skills: Run Copilot and pass it `/skills list`. You can also use `ls .github/skills/` to see project skills or `ls ~/.copilot/skills/` for personal skills.
+2. Create a `book-summary` skill at `.github/skills/book-summary/SKILL.md` that generates a formatted markdown summary of the book collection
+3. Your skill should have:
+ - Clear name and description (description is crucial for matching!)
+ - Specific formatting rules (e.g., markdown table with title, author, year, read status)
+ - Output conventions (e.g., use ✅/❌ for read status, sort by year)
+4. Test the skill: `@samples/book-app-project/data.json Summarize the books in this collection`
+5. Verify the skill auto-triggers by checking `/skills list`
+6. Try invoking it directly with `/book-summary Summarize the books in this collection`
+
+**Success criteria**: You have a working `book-summary` skill that Copilot automatically applies when you ask about the book collection.
+
+
+💡 Hints (click to expand)
+
+**Starter template**: Create `.github/skills/book-summary/SKILL.md`:
+
+```markdown
+---
+name: book-summary
+description: Generate a formatted markdown summary of a book collection
+---
+
+# Book Summary Generator
+
+Generate a summary of the book collection following these rules:
+
+1. Output a markdown table with columns: Title, Author, Year, Status
+2. Use ✅ for read books and ❌ for unread books
+3. Sort by year (oldest first)
+4. Include a total count at the bottom
+5. Flag any data issues (missing authors, invalid years)
+
+Example:
+| Title | Author | Year | Status |
+|-------|--------|------|--------|
+| 1984 | George Orwell | 1949 | ✅ |
+| Dune | Frank Herbert | 1965 | ❌ |
+
+**Total: 2 books (1 read, 1 unread)**
+```
+
+**Test it:**
+```bash
+copilot
+> @samples/book-app-project/data.json Summarize the books in this collection
+# The skill should auto-trigger based on the description match
+```
+
+**If it doesn't trigger:** Try `/skills reload` then ask again.
+
+
+
+### Bonus Challenge: Commit Message Skill
+
+1. Create a `commit-message` skill that generates conventional commit messages with a consistent format
+2. Test it by staging a change and asking: "Generate a commit message for my staged changes"
+3. Document your skill and share it on GitHub with the `copilot-skill` topic
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Naming the file something other than `SKILL.md` | Skill won't be recognized | The file must be named exactly `SKILL.md` |
+| Vague `description` field | Skill never gets loaded automatically | Description is the PRIMARY discovery mechanism. Use specific trigger words |
+| Missing `name` or `description` in frontmatter | Skill fails to load | Add both fields in YAML frontmatter |
+| Wrong folder location | Skill not found | Use `.github/skills/skill-name/` (project) or `~/.copilot/skills/skill-name/` (personal) |
+
+### Troubleshooting
+
+**Skill not being used** - If Copilot isn't using your skill when expected:
+
+1. **Check the description**: Does it match how you're asking?
+ ```markdown
+ # Bad: Too vague
+ description: Reviews code
+
+ # Good: Includes trigger words
+ description: Use for code reviews, checking code quality,
+ finding bugs, security issues, and best practice violations
+ ```
+
+2. **Verify the file location**:
+ ```bash
+ # Project skills
+ ls .github/skills/
+
+ # User skills
+ ls ~/.copilot/skills/
+ ```
+
+3. **Check SKILL.md format**: Frontmatter is required:
+ ```markdown
+ ---
+ name: skill-name
+ description: What the skill does and when to use it
+ ---
+
+ # Instructions here
+ ```
+
+**Skill not appearing** - Verify the folder structure:
+```
+.github/skills/
+└── my-skill/ # Folder name
+ └── SKILL.md # Must be exactly SKILL.md (case-sensitive)
+```
+
+Run `/skills reload` after creating or editing skills to ensure changes are picked up.
+
+**Testing if a skill loads** - Ask Copilot directly:
+```bash
+> What skills do you have available for checking code quality?
+# Copilot will describe relevant skills it found
+```
+
+**How do I know my skill is actually working?**
+
+1. **Check the output format**: If your skill specifies an output format (like `[CRITICAL]` tags), look for that in the response
+2. **Ask directly**: After getting a response, ask "Did you use any skills for that?"
+3. **Compare with/without**: Try the same prompt with `--no-custom-instructions` to see the difference:
+ ```bash
+ # With skills
+ copilot --allow-all -p "Review @file.py for security issues"
+
+ # Without skills (baseline comparison)
+ copilot --allow-all -p "Review @file.py for security issues" --no-custom-instructions
+ ```
+4. **Check for specific checks**: If your skill includes specific checks (like "functions over 50 lines"), see if those appear in the output
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+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
+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
+
+> 📋 **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.
+
+---
+
+## ➡️ What's Next
+
+Skills extend what Copilot can do with auto-loaded instructions. But what about connecting to external services? That's where MCP comes in.
+
+In **[Chapter 06: MCP Servers](../06-mcp-servers/)**, you'll learn:
+
+- What MCP (Model Context Protocol) is
+- Connecting to GitHub, filesystem, and documentation services
+- Configuring MCP servers
+- Multi-server workflows
+
+---
+
+**[← Back to Chapter 04](../04-agents-and-custom-instructions/)** | **[Continue to Chapter 06 →](../06-mcp-servers/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md b/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md
new file mode 100644
index 000000000..391ba25f2
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/06-mcp-servers.md
@@ -0,0 +1,942 @@
+---
+title: '06 · Connect to GitHub, Databases & APIs'
+description: 'Mirror the source chapter on MCP servers and external integrations for GitHub Copilot CLI.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **What if Copilot could read your GitHub issues, check your database, and create PRs... all from the terminal?**
+
+So far, Copilot can only work with what you give it directly: files you reference with `@`, conversation history, and its own training data. But what if it could reach out on its own to check your GitHub repository, browse your project files, or look up the latest documentation for a library?
+
+That's what MCP (Model Context Protocol) does. It's a way to connect Copilot to external services so it has access to live, real-world data. Each service Copilot connects to is called an "MCP server." In this chapter, you'll set up a few of these connections and see how they make Copilot dramatically more useful.
+
+> 💡 **Already familiar with MCP?** [Jump to the quick start](#-use-the-built-in-github-mcp) to confirm it's working and start configuring servers.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Understand what MCP is and why it matters
+- Manage MCP servers using `/mcp` commands
+- Configure MCP servers for GitHub, filesystem, and documentation
+- Use MCP-powered workflows with the book app project
+- Know when and how to build a custom MCP server (optional)
+
+> ⏱️ **Estimated Time**: ~50 minutes (15 min reading + 35 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: 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:
+
+| Browser Extension | What It Connects To | MCP Equivalent |
+|-------------------|---------------------|----------------|
+| Password manager | Your password vault | **GitHub MCP** → your repos, issues, PRs |
+| Grammarly | Writing analysis service | **Context7 MCP** → library documentation |
+| File manager | Cloud storage | **Filesystem MCP** → local project files |
+
+Without extensions, your browser is still useful, but with them, it becomes a powerhouse. MCP servers do the same for Copilot. They connect it to real, live data sources so it can read your GitHub issues, explore your file system, fetch up-to-date documentation, and more.
+
+***MCP servers connect Copilot to the outside world: GitHub, repositories, documentation, and more***
+
+> 💡 **Key insight**: Without MCP, Copilot can only see files you explicitly share with `@`. With MCP, it can proactively explore your project, check your GitHub repo, and look up documentation, all automatically.
+
+---
+
+
+
+# Quick Start: MCP in 30 Seconds
+
+## Get started with the built-in GitHub MCP server
+Let's see MCP in action right now, before configuring anything.
+The GitHub MCP server is included by default. Try this:
+
+```bash
+copilot
+> List the recent commits in this repository
+```
+
+If Copilot returns real commit data, you've just seen MCP in action. That's the GitHub MCP server reaching out to GitHub on your behalf. But GitHub is just *one* server. This chapter shows you how to add more (filesystem access, up-to-date documentation, and others) so Copilot can do even more.
+
+---
+
+## The `/mcp show` Command
+
+Use `/mcp show` to see which MCP servers are configured and whether they're enabled:
+
+```bash
+copilot
+
+> /mcp show
+
+MCP Servers:
+✓ github (enabled) - GitHub integration
+✓ filesystem (enabled) - File system access
+```
+
+> 💡 **Only seeing the GitHub server?** That's expected! If you haven't added any additional MCP servers yet, GitHub is the only one listed. You'll add more in the next section.
+
+> 📚 **Want to see all `/mcp` commands?** There are additional commands for adding, editing, enabling, and deleting servers. See the [full command reference](#-additional-mcp-commands) at the end of this chapter.
+
+
+🎬 See it in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+---
+
+## What Changes with MCP?
+
+Here's the difference MCP makes in practice:
+
+**Without MCP:**
+```bash
+> What's in GitHub issue #42?
+
+"I don't have access to GitHub. You'll need to copy and paste the issue content."
+```
+
+**With MCP:**
+```bash
+> What's in GitHub issue #42 of this repository?
+
+Issue #42: Login fails with special characters
+Status: Open
+Labels: bug, priority-high
+Description: Users report that passwords containing...
+```
+
+MCP makes Copilot aware of your actual development environment.
+
+> 📚 **Official Documentation**: [About MCP](https://docs.github.com/copilot/concepts/context/mcp) for a deeper look at how MCP works with GitHub Copilot.
+
+---
+
+# Configuring MCP Servers
+
+
+
+Now that you've seen MCP in action, let's set up additional servers. This section covers the configuration file format and how to add new servers.
+
+---
+
+## MCP Configuration File
+
+MCP servers are configured in `~/.copilot/mcp-config.json` (user-level, applies to all projects) or `.vscode/mcp.json` (project-level, applies to just the current workspace).
+
+```json
+{
+ "mcpServers": {
+ "server-name": {
+ "type": "local",
+ "command": "npx",
+ "args": ["@package/server-name"],
+ "tools": ["*"]
+ }
+ }
+}
+```
+
+*Most MCP servers are distributed as npm packages and run via the `npx` command.*
+
+
+💡 New to JSON? Click here to learn what each field means
+
+| Field | What It Means |
+|-------|---------------|
+| `"mcpServers"` | Container for all your MCP server configurations |
+| `"server-name"` | A name you choose (e.g., "github", "filesystem") |
+| `"type": "local"` | The server runs on your machine |
+| `"command": "npx"` | The program to run (npx runs npm packages) |
+| `"args": [...]` | Arguments passed to the command |
+| `"tools": ["*"]` | Allow all tools from this server |
+
+**Important JSON rules:**
+- Use double quotes `"` for strings (not single quotes)
+- No trailing commas after the last item
+- File must be valid JSON (use a [JSON validator](https://jsonlint.com/) if unsure)
+
+
+
+---
+
+## Adding MCP Servers
+
+The GitHub MCP server is built-in and requires no setup. Below are additional servers you can add. **Pick what interests you, or work through them in order.**
+
+| I want to... | Jump to |
+|---|---|
+| Let Copilot browse my project files | [Filesystem Server](#filesystem-server) |
+| Get up-to-date library documentation | [Context7 Server](#context7-server-documentation) |
+| Explore optional extras (custom servers, web_fetch) | [Beyond the Basics](#beyond-the-basics) |
+
+
+Filesystem Server - Let Copilot explore your project files
+
+
+### Filesystem Server
+
+```json
+{
+ "mcpServers": {
+ "filesystem": {
+ "type": "local",
+ "command": "npx",
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
+ "tools": ["*"]
+ }
+ }
+}
+```
+
+> 💡 **The `.` path**: The `.` means "current directory". Copilot can access files relative to where you launched it. In a Codespace, this is your workspace root. You can also use an absolute path like `/workspaces/copilot-cli-for-beginners` if you prefer.
+
+Add this to your `~/.copilot/mcp-config.json` and restart Copilot.
+
+
+
+
+Context7 Server - Get up-to-date library docs
+
+
+### Context7 Server (Documentation)
+
+Context7 gives Copilot access to up-to-date documentation for popular frameworks and libraries. Instead of relying on training data that might be outdated, Copilot fetches the actual current documentation.
+
+```json
+{
+ "mcpServers": {
+ "context7": {
+ "type": "local",
+ "command": "npx",
+ "args": ["-y", "@upstash/context7-mcp"],
+ "tools": ["*"]
+ }
+ }
+}
+```
+
+- ✅ **No API key required**
+- ✅ **No account needed**
+- ✅ **Your code stays local**
+
+Add this to your `~/.copilot/mcp-config.json` and restart Copilot.
+
+
+
+
+Beyond the Basics - Custom servers and web access (optional)
+
+
+These are optional extras for when you're comfortable with the core servers above.
+
+### Microsoft Learn MCP Server
+
+Every MCP server you've seen so far (filesystem, Context7) runs locally on your machine. But MCP servers can also run remotely, meaning you just point Copilot CLI at a URL and it handles the rest. No `npx` or `python`, no local process, no dependencies to install.
+
+The [Microsoft Learn MCP Server](https://github.com/microsoftdocs/mcp) is a good example. It gives Copilot CLI direct access to official Microsoft documentation (Azure, Microsoft Foundry and other AI topics, .NET, Microsoft 365, and much more) so it can search docs, fetch full pages, and find official code samples instead of relying on a model's training data.
+
+- ✅ **No API key required**
+- ✅ **No account needed**
+- ✅ **No local install required**
+
+**Quick install with `/plugin install`:**
+
+Instead of editing your JSON config file manually, you can install it in one command:
+
+```bash
+copilot
+
+> /plugin install microsoftdocs/mcp
+```
+
+This adds the server and its associated agent skills automatically. The skills installed include:
+
+- **microsoft-docs**: Concepts, tutorials, and factual lookups
+- **microsoft-code-reference**: API lookups, code samples, and troubleshooting
+- **microsoft-skill-creator**: A meta-skill for generating custom skills about Microsoft technologies
+
+**Usage:**
+```bash
+copilot
+
+> What's the recommended way to deploy a Python app to Azure App Service? Search Microsoft Learn.
+```
+
+📚 Learn more: [Microsoft Learn MCP Server overview](https://learn.microsoft.com/training/support/mcp-get-started)
+
+### Web Access with `web_fetch`
+
+Copilot CLI includes a built-in `web_fetch` tool that can fetch content from any URL. This is useful for pulling in READMEs, API docs, or release notes without leaving your terminal. No MCP server needed.
+
+You can control which URLs are accessible via `~/.copilot/config.json` (general Copilot settings), which is separate from `~/.copilot/mcp-config.json` (MCP server definitions).
+
+```json
+{
+ "permissions": {
+ "allowedUrls": [
+ "https://api.github.com/**",
+ "https://docs.github.com/**",
+ "https://*.npmjs.org/**"
+ ],
+ "blockedUrls": [
+ "http://**"
+ ]
+ }
+}
+```
+
+**Usage:**
+```bash
+copilot
+
+> Fetch and summarize the README from https://github.com/facebook/react
+```
+
+### Building a Custom MCP Server
+
+Want to connect Copilot to your own APIs, databases, or internal tools? You can build a custom MCP server in Python. This is completely optional since the pre-built servers (GitHub, filesystem, Context7) cover most use cases.
+
+📖 See the [Custom MCP Server Guide](https://github.com/github/copilot-cli-for-beginners/blob/main/06-mcp-servers/mcp-custom-server.md) for a complete walkthrough using the book app as an example.
+
+📚 For more background, see the [MCP for Beginners course](https://github.com/microsoft/mcp-for-beginners).
+
+
+
+
+
+### Complete Configuration File
+
+Here's a full `mcp-config.json` with filesystem and Context7 servers:
+
+> 💡 **Note:** GitHub MCP is built-in. You don't need to add it to your config file.
+
+```json
+{
+ "mcpServers": {
+ "filesystem": {
+ "type": "local",
+ "command": "npx",
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
+ "tools": ["*"]
+ },
+ "context7": {
+ "type": "local",
+ "command": "npx",
+ "args": ["-y", "@upstash/context7-mcp"],
+ "tools": ["*"]
+ }
+ }
+}
+```
+
+Save this as `~/.copilot/mcp-config.json` for global access or `.vscode/mcp.json` for project-specific configuration.
+
+---
+
+# Using MCP Servers
+
+Now that you have MCP servers configured, let's see what they can do.
+
+
+
+---
+
+## Server Usage Examples
+
+**Pick a server to explore, or work through them in order.**
+
+| I want to try... | Jump to |
+|---|---|
+| GitHub repos, issues, and PRs | [GitHub Server](#github-server-built-in) |
+| Browsing project files | [Filesystem Server Usage](#filesystem-server-usage) |
+| Library documentation lookup | [Context7 Server Usage](#context7-server-usage) |
+| Custom server, Microsoft Learn MCP and web_fetch usage | [Beyond the Basics Usage](#beyond-the-basics-usage) |
+
+
+GitHub Server (Built-in) - Access repos, issues, PRs, and more
+
+
+### GitHub Server (Built-in)
+
+The GitHub MCP server is **built-in**. If you logged into Copilot (which you did during initial setup), it already works. No configuration needed!
+
+> 💡 **Not working?** Run `/login` to re-authenticate with GitHub.
+
+
+Authentication in Dev Containers
+
+- **GitHub Codespaces** (recommended): Authentication is automatic. The `gh` CLI inherits your Codespace token. No action needed.
+- **Local dev container (Docker)**: Run `gh auth login` after the container starts, then restart Copilot.
+
+**Troubleshooting authentication:**
+```bash
+# Check if you're authenticated
+gh auth status
+
+# If not, log in
+gh auth login
+
+# Verify GitHub MCP is connected
+copilot
+> /mcp show
+```
+
+
+
+| Feature | Example |
+|---------|----------|
+| **Repository info** | View commits, branches, contributors |
+| **Issues** | List, create, search, and comment on issues |
+| **Pull requests** | View PRs, diffs, create PRs, check status |
+| **Code search** | Search code across repositories |
+| **Actions** | Query workflow runs and status |
+
+```bash
+copilot
+
+# See recent activity in this repo
+> List the last 5 commits in this repository
+
+Recent commits:
+1. abc1234 - Update chapter 05 skills examples (2 days ago)
+2. def5678 - Add book app test fixtures (3 days ago)
+3. ghi9012 - Fix typo in chapter 03 README (4 days ago)
+...
+
+# Explore the repo structure
+> What branches exist in this repository?
+
+Branches:
+- main (default)
+- chapter6 (current)
+
+# Search for code patterns across the repo
+> Search this repository for files that import pytest
+
+Found 1 file:
+- samples/book-app-project/tests/test_books.py
+```
+
+> 💡 **Working on your own fork?** If you forked this course repo, you can also try write operations like creating issues and pull requests. We'll practice that in the exercises below.
+
+> ⚠️ **Don't see results?** The GitHub MCP operates on the repository's remote (on github.com), not just local files. Make sure your repo has a remote: run `git remote -v` to check.
+
+
+
+
+Filesystem Server - Browse and analyze project files
+
+
+### Filesystem Server
+
+Once configured, the filesystem MCP provides tools that Copilot can use automatically:
+
+```bash
+copilot
+
+> How many Python files are in the book-app-project directory?
+
+Found 3 Python files in samples/book-app-project/:
+- book_app.py
+- books.py
+- utils.py
+
+> What's the total size of the data.json file?
+
+samples/book-app-project/data.json: 2.4 KB
+
+> Find all functions that don't have type hints in the book app
+
+Found 2 functions without type hints:
+- samples/book-app-project/utils.py:10 - get_user_choice()
+- samples/book-app-project/utils.py:14 - get_book_details()
+```
+
+
+
+
+Context7 Server - Look up library documentation
+
+
+### Context7 Server
+
+```bash
+copilot
+
+> What are the best practices for using pytest fixtures?
+
+From pytest Documentation:
+
+Fixtures - Use fixtures to provide a fixed baseline for tests:
+
+ import pytest
+
+ @pytest.fixture
+ def sample_books():
+ return [
+ {"title": "1984", "author": "George Orwell", "year": 1949},
+ {"title": "Dune", "author": "Frank Herbert", "year": 1965},
+ ]
+
+ def test_find_by_author(sample_books):
+ # fixture is automatically passed as argument
+ results = [b for b in sample_books if "Orwell" in b["author"]]
+ assert len(results) == 1
+
+Best practices:
+- Use fixtures instead of setup/teardown methods
+- Use tmp_path fixture for temporary files
+- Use monkeypatch for modifying environment
+- Scope fixtures appropriately (function, class, module, session)
+
+> How can I apply this to the book app's test file?
+
+# Copilot now knows the official pytest patterns
+# and can apply them to samples/book-app-project/tests/test_books.py
+```
+
+
+
+
+Beyond the Basics - Custom server and web_fetch usage
+
+
+### Beyond the Basics
+
+**Custom MCP Server**: If you built the book-lookup server from the [Custom MCP Server Guide](https://github.com/github/copilot-cli-for-beginners/blob/main/06-mcp-servers/mcp-custom-server.md), you can query your book collection directly:
+
+```bash
+copilot
+
+> Look up information about "1984" using the book lookup server. Search for books by George Orwell
+```
+
+**Microsoft Learn MCP**: If you installed the [Microsoft Learn MCP server](#microsoft-learn-mcp-server), you can look up official Microsoft documentation directly:
+
+```bash
+copilot
+
+> How do I configure managed identity for an Azure Function? Search Microsoft Learn.
+```
+
+**Web Fetch**: Use the built-in `web_fetch` tool to pull in content from any URL:
+
+```bash
+copilot
+
+> Fetch and summarize the README from https://github.com/facebook/react
+```
+
+
+
+---
+
+## Multi-Server Workflows
+
+These workflows show why developers say "I never want to work without this again." Each example combines multiple MCP servers in a single session.
+
+
+
+*Complete MCP workflow: GitHub MCP retrieves repo data, Filesystem MCP finds code, Context7 MCP provides best practices, and Copilot handles analysis*
+
+Each example below is self-contained. **Pick one that interests you, or read them all.**
+
+| I want to see... | Jump to |
+|---|---|
+| Multiple servers working together | [Multi-Server Exploration](#multi-server-exploration) |
+| Going from issue to PR in one session | [Issue-to-PR Workflow](#issue-to-pr-workflow) |
+| A quick project health check | [Health Dashboard](#health-dashboard) |
+
+
+Multi-Server Exploration - Combine filesystem, GitHub, and Context7 in one session
+
+
+#### Exploring the Book App with Multiple MCP Servers
+
+```bash
+copilot
+
+# Step 1: Use filesystem MCP to explore the book app
+> List all Python files in samples/book-app-project/ and summarize
+> what each file does
+
+Found 3 Python files:
+- book_app.py: CLI entry point with command routing (list, add, remove, find)
+- books.py: BookCollection class with data persistence via JSON
+- utils.py: Helper functions for user input and display
+
+# Step 2: Use GitHub MCP to check recent changes
+> What were the last 3 commits that touched files in samples/book-app-project/?
+
+Recent commits affecting book app:
+1. abc1234 - Add test fixtures for BookCollection (2 days ago)
+2. def5678 - Add find_by_author method (5 days ago)
+3. ghi9012 - Initial book app setup (1 week ago)
+
+# Step 3: Use Context7 MCP for best practices
+> What are Python best practices for JSON data persistence?
+
+From Python Documentation:
+- Use context managers (with statements) for file I/O
+- Handle JSONDecodeError for corrupted files
+- Use dataclasses for structured data
+- Consider atomic writes to prevent data corruption
+
+# Step 4: Synthesize a recommendation
+> Based on the book app code and these best practices,
+> what improvements would you suggest?
+
+Suggestions:
+1. Add input validation in add_book() for empty strings and invalid years
+2. Consider atomic writes in save_books() to prevent data corruption
+3. Add type hints to utils.py functions (get_user_choice, get_book_details)
+```
+
+
+🎬 See the MCP workflow in action!
+
+
+
+*Demo output varies. Your model, tools, and responses will differ from what's shown here.*
+
+
+
+**The result**: Code exploration → history review → best practices lookup → improvement plan. **All from one terminal session, using three MCP servers together.**
+
+
+
+
+Issue-to-PR Workflow - Go from a GitHub issue to a pull request without leaving the terminal
+
+
+#### The Issue-to-PR Workflow (On Your Own Repo)
+
+This works best on your own fork or repository where you have write access:
+
+> 💡 **Don't worry if you can't try this right now.** If you're on a read-only clone, you'll practice this in the assignment. For now, just read through to understand the flow.
+
+```bash
+copilot
+
+> Get the details of GitHub issue #1
+
+Issue #1: Add input validation for book year
+Status: Open
+Description: The add_book function accepts any year value...
+
+> @samples/book-app-project/books.py Fix the issue described in issue #1
+
+[Copilot implements year validation in add_book()]
+
+> Run the tests to make sure the fix works
+
+All 8 tests passed ✓
+
+> Create a pull request titled "Add year validation to book app"
+
+✓ Created PR #2: Add year validation to book app
+```
+
+**Zero copy-paste. Zero context switching. One terminal session.**
+
+
+
+
+Health Dashboard - Get a quick project health check using multiple servers
+
+
+#### Book App Health Dashboard
+
+```bash
+copilot
+
+> Give me a health report for the book app project:
+> 1. List all functions across the Python files in samples/book-app-project/
+> 2. Check which functions have type hints and which don't
+> 3. Show what tests exist in samples/book-app-project/tests/
+> 4. Check the recent commit history for this directory
+
+Book App Health Report
+======================
+
+📊 Functions Found:
+- books.py: 8 methods in BookCollection (all have type hints ✓)
+- book_app.py: 6 functions (4 have type hints, 2 missing)
+- utils.py: 3 functions (1 has type hints, 2 missing)
+
+🧪 Test Coverage:
+- test_books.py: 8 test functions covering BookCollection
+- Missing: no tests for book_app.py CLI functions
+- Missing: no tests for utils.py helper functions
+
+📝 Recent Activity:
+- 3 commits in the last week
+- Most recent: added test fixtures
+
+Recommendations:
+- Add type hints to utils.py functions
+- Add tests for book_app.py CLI handlers
+- All files well-sized (<100 lines) - good structure!
+```
+
+**The result**: Multiple data sources aggregated in seconds. Manually, this would mean running grep, counting lines, checking git log, and browsing test files. Easily 15+ minutes of work.
+
+
+
+---
+
+# 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.
+
+---
+
+## ▶️ Try It Yourself
+
+Now it's your turn! Complete these exercises to practice using MCP servers with the book app project.
+
+### Exercise 1: Check Your MCP Status
+
+Start by seeing what MCP servers are available:
+
+```bash
+copilot
+
+> /mcp show
+```
+
+You should see the GitHub server listed as enabled. If not, run `/login` to authenticate.
+
+---
+
+### Exercise 2: Explore the Book App with Filesystem MCP
+
+If you've configured the filesystem server, use it to explore the book app:
+
+```bash
+copilot
+
+> How many Python files are in samples/book-app-project/?
+> What functions are defined in each file?
+```
+
+**Expected result**: Copilot lists `book_app.py`, `books.py`, and `utils.py` with their functions.
+
+> 💡 **Don't have filesystem MCP configured yet?** Create the config file from the [Complete Configuration](#complete-configuration-file) section above. Then restart Copilot.
+
+---
+
+### Exercise 3: Query Repository History with GitHub MCP
+
+Use the built-in GitHub MCP to explore this course repository:
+
+```bash
+copilot
+
+> List the last 5 commits in this repository
+
+> What branches exist in this repository?
+```
+
+**Expected result**: Copilot shows recent commit messages and branch names from the GitHub remote.
+
+> ⚠️ **In a Codespace?** This works automatically. Authentication is inherited. If you're on a local clone, make sure `gh auth status` shows you're logged in.
+
+---
+
+### Exercise 4: Combine Multiple MCP Servers
+
+Now combine filesystem and GitHub MCP in a single session:
+
+```bash
+copilot
+
+> Read samples/book-app-project/data.json and tell me what books are
+> in the collection. Then check the recent commits to see when this
+> file was last modified.
+```
+
+**Expected result**: Copilot reads the JSON file (filesystem MCP), lists the 5 books including "The Hobbit", "1984", "Dune", "To Kill a Mockingbird", and "Mysterious Book", then queries GitHub for commit history.
+
+**Self-Check**: You understand MCP when you can explain why "Check my repo's commit history" is better than manually running `git log` and pasting the output into your prompt.
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: Book App MCP Exploration
+
+Practice using MCP servers together on the book app project. Complete these steps in a single Copilot session:
+
+1. **Verify MCP is working**: Run `/mcp show` and confirm at least the GitHub server is enabled
+2. **Set up filesystem MCP** (if not already done): Create `~/.copilot/mcp-config.json` with the filesystem server configuration
+3. **Explore the code**: Ask Copilot to use the filesystem server to:
+ - List all functions in `samples/book-app-project/books.py`
+ - Check which functions in `samples/book-app-project/utils.py` are missing type hints
+ - Read `samples/book-app-project/data.json` and identify any data quality issues (hint: look at the last entry)
+4. **Check repository activity**: Ask Copilot to use GitHub MCP to:
+ - List recent commits that touched files in `samples/book-app-project/`
+ - Check if there are any open issues or pull requests
+5. **Combine servers**: In a single prompt, ask Copilot to:
+ - Read the test file at `samples/book-app-project/tests/test_books.py`
+ - Compare the tested functions against all functions in `books.py`
+ - Summarize what test coverage is missing
+
+**Success criteria**: You can seamlessly combine filesystem and GitHub MCP data in a single Copilot session, and you can explain what each MCP server contributed to the response.
+
+
+💡 Hints (click to expand)
+
+**Step 1: Verify MCP**
+```bash
+copilot
+> /mcp show
+# Should show "github" as enabled
+# If not, run: /login
+```
+
+**Step 2: Create the config file**
+
+Use the JSON from the [Complete Configuration](#complete-configuration-file) section above and save it as `~/.copilot/mcp-config.json`.
+
+**Step 3: Data quality issue to look for**
+
+The last book in `data.json` is:
+```json
+{
+ "title": "Mysterious Book",
+ "author": "",
+ "year": 0,
+ "read": false
+}
+```
+An empty author and year of 0. That's the data quality issue!
+
+**Step 5: Test coverage comparison**
+
+The tests in `test_books.py` cover: `add_book`, `mark_as_read`, `remove_book`, `get_unread_books`, and `find_book_by_title`. Functions like `load_books`, `save_books`, and `list_books` don't have direct tests. The CLI functions in `book_app.py` and helpers in `utils.py` have no tests at all.
+
+**If MCP isn't working:** Restart Copilot after editing the config file.
+
+
+
+### Bonus Challenge: Build a Custom MCP Server
+
+Ready to go deeper? Follow the [Custom MCP Server Guide](https://github.com/github/copilot-cli-for-beginners/blob/main/06-mcp-servers/mcp-custom-server.md) to build your own MCP server in Python that connects to any API.
+
+---
+
+
+🔧 Common Mistakes & Troubleshooting (click to expand)
+
+### Common Mistakes
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Not knowing GitHub MCP is built-in | Trying to install/configure it manually | GitHub MCP is included by default. Just try: "List the recent commits in this repo" |
+| Looking for config in wrong location | Can't find or edit MCP settings | User-level config is in `~/.copilot/mcp-config.json`, project-level is `.vscode/mcp.json` |
+| Invalid JSON in config file | MCP servers fail to load | Use `/mcp show` to check configuration; validate JSON syntax |
+| Forgetting to authenticate MCP servers | "Authentication failed" errors | Some MCPs need separate auth. Check each server's requirements |
+
+### Troubleshooting
+
+**"MCP server not found"** - Check that:
+1. The npm package exists: `npm view @modelcontextprotocol/server-github`
+2. Your configuration is valid JSON
+3. The server name matches your config
+
+Use `/mcp show` to see the current configuration.
+
+**"GitHub authentication failed"** - The built-in GitHub MCP uses your `/login` credentials. Try:
+
+```bash
+copilot
+> /login
+```
+
+This will re-authenticate you with GitHub. If issues persist, check that your GitHub account has the necessary permissions for the repository you're accessing.
+
+**"MCP server failed to start"** - Check the server logs:
+```bash
+# Run the server command manually to see errors
+npx -y @modelcontextprotocol/server-github
+```
+
+**MCP tools not available** - Make sure the server is enabled:
+```bash
+copilot
+
+> /mcp show
+# Check if server is listed and enabled
+```
+
+If a server is disabled, see the [additional `/mcp` commands](#-additional-mcp-commands) below for how to re-enable it.
+
+
+
+---
+
+
+📚 Additional /mcp Commands (click to expand)
+
+
+Beyond `/mcp show`, there are several other commands for managing your MCP servers:
+
+| Command | What It Does |
+|---------|--------------|
+| `/mcp show` | Show all configured MCP servers and their status |
+| `/mcp add` | Interactive setup for adding a new server |
+| `/mcp edit ` | Edit an existing server configuration |
+| `/mcp enable ` | Enable a disabled server |
+| `/mcp disable ` | Temporarily disable a server |
+| `/mcp delete ` | Remove a server permanently |
+
+For most of this course, `/mcp show` is all you need. The other commands become useful as you manage more servers over time.
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+1. **MCP** connects Copilot to external services (GitHub, filesystem, documentation)
+2. **GitHub MCP is built-in** - no configuration needed, just `/login`
+3. **Filesystem and Context7** are configured via `~/.copilot/mcp-config.json`
+4. **Multi-server workflows** combine data from multiple sources in a single session
+5. **Check server status** with `/mcp show` (additional commands available for managing servers)
+6. **Custom servers** let you connect any API (optional, covered in the appendix guide)
+
+> 📋 **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.
+
+---
+
+## ➡️ What's Next
+
+You now have all the building blocks: modes, context, workflows, agents, skills, and MCP. Time to put them all together.
+
+In **[Chapter 07: Putting It All Together](../07-putting-it-all-together/)**, you'll learn:
+
+- Combining agents, skills, and MCP in unified workflows
+- Complete feature development from idea to merged PR
+- Automation with hooks
+- Best practices for team environments
+
+---
+
+**[← Back to Chapter 05](../05-skills/)** | **[Continue to Chapter 07 →](../07-putting-it-all-together/)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/07-putting-it-all-together.md b/website/src/content/docs/learning-hub/cli-for-beginners/07-putting-it-all-together.md
new file mode 100644
index 000000000..94b0210a4
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/07-putting-it-all-together.md
@@ -0,0 +1,520 @@
+---
+title: '07 · Putting It All Together'
+description: 'Mirror the source capstone chapter that combines the GitHub Copilot CLI workflow end to end.'
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+> **Everything you learned combines here. Go from idea to merged PR in a single session.**
+
+In this chapter, you'll bring together everything you've learned into complete workflows. You'll build features using multi-agent collaboration, set up pre-commit hooks that catch security issues before they're committed, integrate Copilot into CI/CD pipelines, and go from feature idea to merged PR in a single terminal session. This is where GitHub Copilot CLI becomes a genuine force multiplier.
+
+> 💡 **Note**: This chapter shows how to combine everything you've learned. **You don't need agents, skills, or MCP to be productive (although they can be very helpful).** The core workflow — describe, plan, implement, test, review, ship — works with just the built-in features from Chapters 00-03.
+
+## 🎯 Learning Objectives
+
+By the end of this chapter, you'll be able to:
+
+- Combine agents, skills, and MCP (Model Context Protocol) in unified workflows
+- Build complete features using multi-tool approaches
+- Set up basic automation with hooks
+- Apply best practices for professional development
+
+> ⏱️ **Estimated Time**: ~75 minutes (15 min reading + 60 min hands-on)
+
+---
+
+## 🧩 Real-World Analogy: The Orchestra
+
+
+
+A symphony orchestra has many sections:
+- **Strings** provide the foundation (like your core workflows)
+- **Brass** adds power (like agents with specialized expertise)
+- **Woodwinds** add color (like skills that extend capabilities)
+- **Percussion** keeps rhythm (like MCP connecting to external systems)
+
+Individually, each section sounds limited. Together, conducted well, they create something magnificent.
+
+**That's what this chapter teaches!**
+*Like a conductor with an orchestra, you orchestrate agents, skills, and MCP into unified workflows*
+
+Let's start by walking through a scenario that modifies code, generates tests, reviews it, and creates a PR - all in one session.
+
+---
+
+## Idea to Merged PR in One Session
+
+Instead of switching between your editor, terminal, test runner, and GitHub UI and losing context each time, you can combine all your tools in one terminal session. We'll break down this pattern in the [Integration Pattern](#the-integration-pattern-for-power-users) section below.
+
+```bash
+# Start Copilot in interactive mode
+copilot
+
+> I need to add a "list unread" command to the book app that shows only
+> books where read is False. What files need to change?
+
+# Copilot creates high-level plan...
+
+# SWITCH TO PYTHON-REVIEWER AGENT
+> /agent
+# Select "python-reviewer"
+
+> @samples/book-app-project/books.py Design a get_unread_books method.
+> What is the best approach?
+
+# Python-reviewer agent produces:
+# - Method signature and return type
+# - Filter implementation using list comprehension
+# - Edge case handling for empty collections
+
+# SWITCH TO PYTEST-HELPER AGENT
+> /agent
+# Select "pytest-helper"
+
+> @samples/book-app-project/tests/test_books.py Design test cases for
+> filtering unread books.
+
+# Pytest-helper agent produces:
+# - Test cases for empty collections
+# - Test cases with mixed read/unread books
+# - Test cases with all books read
+
+# IMPLEMENT
+> Add a get_unread_books method to BookCollection in books.py
+> Add a "list unread" command option in book_app.py
+> Update the help text in the show_help function
+
+# TEST
+> Generate comprehensive tests for the new feature
+
+# Multiple tests are generated similar to the following:
+# - Happy path (3 tests) — filters correctly, excludes read, includes unread
+# - Edge cases (4 tests) — empty collection, all read, none read, single book
+# - Parametrized (5 cases) — varying read/unread ratios via @pytest.mark.parametrize
+# - Integration (4 tests) — interplay with mark_as_read, remove_book, add_book, and data integrity
+
+# Review the changes
+> /review
+
+# If review passes, use /pr to operate on the pull request for the current branch
+> /pr [view|create|fix|auto]
+
+# Or ask naturally if you want Copilot to draft it from the terminal
+> Create a pull request titled "Feature: Add list unread books command"
+```
+
+**Traditional approach**: Switching between editor, terminal, test runner, docs, and GitHub UI. Each switch causes context loss and friction.
+
+**The key insight**: You directed specialists like an architect. They handled the details. You handled the vision.
+
+> 💡 **Going further**: For large multi-step plans like this, try `/fleet` to let Copilot run independent subtasks in parallel. See the [official docs](https://docs.github.com/copilot/concepts/agents/copilot-cli/fleet) for details.
+
+---
+
+# Additional Workflows
+
+
+
+For power users who completed Chapters 04-06, these workflows show how agents, skills, and MCP multiply your effectiveness.
+
+## The Integration Pattern
+
+Here's the mental model for combining everything:
+
+
+
+---
+
+## Workflow 1: Bug Investigation and Fix
+
+Real-world bug fixing with full tool integration:
+
+```bash
+copilot
+
+# PHASE 1: Understand the bug from GitHub (MCP provides this)
+> Get the details of issue #1
+
+# Learn: "find_by_author doesn't work with partial names"
+
+# PHASE 2: Research best practice (deep research with web + GitHub sources)
+> /research Best practices for Python case-insensitive string matching
+
+# PHASE 3: Find related code
+> @samples/book-app-project/books.py Show me the find_by_author method
+
+# PHASE 4: Get expert analysis
+> /agent
+# Select "python-reviewer"
+
+> Analyze this method for issues with partial name matching
+
+# Agent identifies: Method uses exact equality instead of substring matching
+
+# PHASE 5: Fix with agent guidance
+> Implement the fix using lowercase comparison and 'in' operator
+
+# PHASE 6: Generate tests
+> /agent
+# Select "pytest-helper"
+
+> Generate pytest tests for find_by_author with partial matches
+> Include test cases: partial name, case variations, no matches
+
+# PHASE 7: Commit and PR
+> Generate a commit message for this fix
+
+> Create a pull request linking to issue #1
+```
+
+---
+
+## Workflow 2: Code Review Automation (Optional)
+
+> 💡 **This section is optional.** Pre-commit hooks are useful for teams but not required to be productive. Skip this if you're just getting started.
+>
+> ⚠️ **Performance note**: This hook calls `copilot -p` for each staged file, which takes several seconds per file. For large commits, consider limiting to critical files or running reviews manually with `/review` instead.
+
+A **git hook** is a script that Git runs automatically at certain points, For example, right before a commit. You can use this to run automated checks on your code. Here's how to set up an automated Copilot review on your commits:
+
+```bash
+# Create a pre-commit hook
+cat > .git/hooks/pre-commit << 'EOF'
+#!/bin/bash
+
+# Get staged files (Python files only)
+STAGED=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.py$')
+
+if [ -n "$STAGED" ]; then
+ echo "Running Copilot review on staged files..."
+
+ for file in $STAGED; do
+ echo "Reviewing $file..."
+
+ # Use timeout to prevent hanging (60 seconds per file)
+ # --allow-all auto-approves file reads/writes so the hook can run unattended.
+ # Only use this in automated scripts. In interactive sessions, let Copilot ask for permission.
+ REVIEW=$(timeout 60 copilot --allow-all -p "Quick security review of @$file - critical issues only" 2>/dev/null)
+
+ # Check if timeout occurred
+ if [ $? -eq 124 ]; then
+ echo "Warning: Review timed out for $file (skipping)"
+ continue
+ fi
+
+ if echo "$REVIEW" | grep -qi "CRITICAL"; then
+ echo "Critical issues found in $file:"
+ echo "$REVIEW"
+ exit 1
+ fi
+ done
+
+ echo "Review passed"
+fi
+EOF
+
+chmod +x .git/hooks/pre-commit
+```
+
+> ⚠️ **macOS users**: The `timeout` command is not included by default on macOS. Install it with `brew install coreutils` or replace `timeout 60` with a simple invocation without a timeout guard.
+
+> 📚 **Official Documentation**: [Use hooks](https://docs.github.com/copilot/how-tos/copilot-cli/use-hooks) and [Hooks configuration reference](https://docs.github.com/copilot/reference/hooks-configuration) for the complete hooks API.
+>
+> 💡 **Built-in alternative**: Copilot CLI also has a built-in hooks system (`copilot hooks`) that can run automatically on events like pre-commit. The manual git hook above gives you full control, while the built-in system is simpler to configure. See the docs above to decide which approach fits your workflow.
+
+Now every commit gets a quick security review:
+
+```bash
+git add samples/book-app-project/books.py
+git commit -m "Update book collection methods"
+
+# Output:
+# Running Copilot review on staged files...
+# Reviewing samples/book-app-project/books.py...
+# Critical issues found in samples/book-app-project/books.py:
+# - Line 15: File path injection vulnerability in load_from_file
+#
+# Fix the issue and try again.
+```
+
+---
+
+## Workflow 3: Onboarding to a New Codebase
+
+When joining a new project, combine context, agents, and MCP to ramp up fast:
+
+```bash
+# Start Copilot in interactive mode
+copilot
+
+# PHASE 1: Get the big picture with context
+> @samples/book-app-project/ Explain the high-level architecture of this codebase
+
+# PHASE 2: Understand a specific flow
+> @samples/book-app-project/book_app.py Walk me through what happens
+> when a user runs "python book_app.py add"
+
+# PHASE 3: Get expert analysis with an agent
+> /agent
+# Select "python-reviewer"
+
+> @samples/book-app-project/books.py Are there any design issues,
+> missing error handling, or improvements you would recommend?
+
+# PHASE 4: Find something to work on (MCP provides GitHub access)
+> List open issues labeled "good first issue"
+
+# PHASE 5: Start contributing
+> Pick the simplest open issue and outline a plan to fix it
+```
+
+This workflow combines `@` context, agents, and MCP into a single onboarding session, exactly the integration pattern from earlier in this chapter.
+
+---
+
+# Best Practices & Automation
+
+Patterns and habits that make your workflows more effective.
+
+---
+
+## Best Practices
+
+### 1. Start with Context Before Analysis
+
+Always gather context before asking for analysis:
+
+```bash
+# Good
+> Get the details of issue #42
+> /agent
+# Select python-reviewer
+> Analyze this issue
+
+# Less effective
+> /agent
+# Select python-reviewer
+> Fix login bug
+# Agent doesn't have issue context
+```
+
+### 2. Know the Difference: Agents, Skills, and Custom Instructions
+
+Each tool has a sweet spot:
+
+```bash
+# Agents: Specialized personas you explicitly activate
+> /agent
+# Select python-reviewer
+> Review this authentication code for security issues
+
+# Skills: Modular capabilities that auto-activate when your prompt
+# matches the skill's description (you must create them first — see Ch 05)
+> Generate comprehensive tests for this code
+# If you have a testing skill configured, it activates automatically
+
+# Custom instructions (.github/copilot-instructions.md): Always-on
+# guidance that applies to every session without switching or triggering
+```
+
+> 💡 **Key point**: Agents and skills can both analyze AND generate code. The real difference is **how they activate** — agents are explicit (`/agent`), skills are automatic (prompt-matched), and custom instructions are always on.
+
+### 3. Keep Sessions Focused
+
+Use `/rename` to label your session (makes it easy to find in history) and `/exit` to end it cleanly:
+
+```bash
+# Good: One feature per session
+> /rename list-unread-feature
+# Work on list unread
+> /exit
+
+copilot
+> /rename export-csv-feature
+# Work on CSV export
+> /exit
+
+# Less effective: Everything in one long session
+```
+
+### 4. Make Workflows Reusable with Copilot
+
+Instead of just documenting workflows in a wiki, encode them directly in your repo where Copilot can use them:
+
+- **Custom instructions** (`.github/copilot-instructions.md`): Always-on guidance for coding standards, architecture rules, and build/test/deploy steps. Every session follows them automatically.
+- **Prompt files** (`.github/prompts/`): Reusable, parameterized prompts your team can share — like templates for code reviews, component generation, or PR descriptions.
+- **Custom agents** (`.github/agents/`): Encode specialized personas (e.g., a security reviewer or a docs writer) that anyone on the team can activate with `/agent`.
+- **Custom skills** (`.github/skills/`): Package step-by-step workflow instructions that auto-activate when relevant.
+
+> 💡 **The payoff**: New team members get your workflows for free — they're built into the repo, not locked in someone's head.
+
+---
+
+## Bonus: Production Patterns
+
+These patterns are optional but valuable for professional environments.
+
+### PR Description Generator
+
+```bash
+# Generate comprehensive PR descriptions
+BRANCH=$(git branch --show-current)
+COMMITS=$(git log main..$BRANCH --oneline)
+
+copilot -p "Generate a PR description for:
+Branch: $BRANCH
+Commits:
+$COMMITS
+
+Include: Summary, Changes Made, Testing Done, Screenshots Needed"
+```
+
+### CI/CD Integration
+
+For teams with existing CI/CD pipelines, you can automate Copilot reviews on every pull request using GitHub Actions. This includes posting review comments automatically and filtering for critical issues.
+
+> 📖 **Learn more**: See [CI/CD Integration](https://github.com/github/copilot-cli-for-beginners/blob/main/appendices/ci-cd-integration.md) for complete GitHub Actions workflows, configuration options, and troubleshooting tips.
+
+---
+
+# Practice
+
+
+
+Put the complete workflow into practice.
+
+---
+
+## ▶️ Try It Yourself
+
+After completing the demos, try these variations:
+
+1. **End-to-End Challenge**: Pick a small feature (e.g., "list unread books" or "export to CSV"). Use the full workflow:
+ - Plan with `/plan`
+ - Design with agents (python-reviewer, pytest-helper)
+ - Implement
+ - Generate tests
+ - Create PR
+
+2. **Automation Challenge**: Set up the pre-commit hook from the Code Review Automation workflow. Make a commit with an intentional file path vulnerability. Does it get blocked?
+
+3. **Your Production Workflow**: Design your own workflow for a common task you do. Write it down as a checklist. What parts could be automated with skills, agents, or hooks?
+
+**Self-Check**: You've completed the course when you can explain to a colleague how agents, skills, and MCP work together - and when to use each.
+
+---
+
+## 📝 Assignment
+
+### Main Challenge: End-to-End Feature
+
+The hands-on examples walked through building a "list unread books" feature. Now practice the full workflow on a different feature: **search books by year range**:
+
+1. Start Copilot and gather context: `@samples/book-app-project/books.py`
+2. Plan with `/plan Add a "search by year" command that lets users find books published between two years`
+3. Implement a `find_by_year_range(start_year, end_year)` method in `BookCollection`
+4. Add a `handle_search_year()` function in `book_app.py` that prompts the user for start and end years
+5. Generate tests: `@samples/book-app-project/books.py @samples/book-app-project/tests/test_books.py Generate tests for find_by_year_range() including edge cases like invalid years, reversed range, and no results.`
+6. Review with `/review`
+7. Update the README: `@samples/book-app-project/README.md Add documentation for the new "search by year" command.`
+8. Generate a commit message
+
+Document your workflow as you go.
+
+**Success criteria**: You've completed the feature from idea to commit using Copilot CLI, including planning, implementation, tests, documentation, and review.
+
+> 💡 **Bonus**: If you have agents set up from Chapter 04, try creating and using custom agents. For example, an error-handler agent for implementation review and a doc-writer agent for the README update.
+
+
+💡 Hints (click to expand)
+
+**Follow the pattern from the ["Idea to Merged PR"](#idea-to-merged-pr-in-one-session) example** at the top of this chapter. The key steps are:
+
+1. Gather context with `@samples/book-app-project/books.py`
+2. Plan with `/plan Add a "search by year" command`
+3. Implement the method and command handler
+4. Generate tests with edge cases (invalid input, empty results, reversed range)
+5. Review with `/review`
+6. Update README with `@samples/book-app-project/README.md`
+7. Generate commit message with `-p`
+
+**Edge cases to think about:**
+- What if the user enters "2000" and "1990" (reversed range)?
+- What if no books match the range?
+- What if the user enters non-numeric input?
+
+**The key is practicing the full workflow** from idea → context → plan → implement → test → document → commit.
+
+
+
+---
+
+
+🔧 Common Mistakes (click to expand)
+
+| Mistake | What Happens | Fix |
+|---------|--------------|-----|
+| Jumping straight to implementation | Miss design issues that are costly to fix later | Use `/plan` first to think through the approach |
+| Using one tool when multiple would help | Slower, less thorough results | Combine: Agent for analysis → Skill for execution → MCP for integration |
+| Not reviewing before committing | Security issues or bugs slip through | Always run `/review` or use a [pre-commit hook](#workflow-2-code-review-automation-optional) |
+| Forgetting to share workflows with team | Each person reinvents the wheel | Document patterns in shared agents, skills, and instructions |
+
+
+
+---
+
+# Summary
+
+## 🔑 Key Takeaways
+
+1. **Integration > Isolation**: Combine tools for maximum impact
+2. **Context first**: Always gather required context before analysis
+3. **Agents analyze, Skills execute**: Use the right tool for the job
+4. **Automate repetition**: Hooks and scripts multiply your effectiveness
+5. **Document workflows**: Shareable patterns benefit the whole team
+
+> 📋 **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.
+
+---
+
+## 🎓 Course Complete!
+
+Congratulations! You've learned:
+
+| Chapter | What You Learned |
+|---------|-------------------|
+| 00 | Copilot CLI installation and Quick Start |
+| 01 | Three modes of interaction |
+| 02 | Context management with @ syntax |
+| 03 | Development workflows |
+| 04 | Specialized agents |
+| 05 | Extensible skills |
+| 06 | External connections with MCP |
+| 07 | Unified production workflows |
+
+You're now equipped to use GitHub Copilot CLI as a genuine force multiplier in your development workflow.
+
+## ➡️ What's Next
+
+Your learning doesn't stop here:
+
+1. **Practice daily**: Use Copilot CLI for real work
+2. **Build custom tools**: Create agents and skills for your specific needs
+3. **Share knowledge**: Help your team adopt these workflows
+4. **Stay updated**: Follow GitHub Copilot updates for new features
+
+### Resources
+
+- [GitHub Copilot CLI Documentation](https://docs.github.com/copilot/concepts/agents/about-copilot-cli)
+- [MCP Server Registry](https://github.com/modelcontextprotocol/servers)
+- [Community Skills](https://github.com/topics/copilot-skill)
+
+---
+
+**Great job! Now go build something amazing.**
+
+**[← Back to Chapter 06](../06-mcp-servers/)** | **[Return to Course Home →](../)**
diff --git a/website/src/content/docs/learning-hub/cli-for-beginners/index.md b/website/src/content/docs/learning-hub/cli-for-beginners/index.md
new file mode 100644
index 000000000..7b35e72ec
--- /dev/null
+++ b/website/src/content/docs/learning-hub/cli-for-beginners/index.md
@@ -0,0 +1,99 @@
+---
+title: "GitHub Copilot CLI for Beginners"
+description: "A source-faithful mirror of the companion GitHub Copilot CLI for Beginners course."
+authors:
+ - GitHub Copilot Learning Hub Team
+lastUpdated: 2026-03-20
+---
+
+
+
+# GitHub Copilot CLI for Beginners
+
+> **✨ Learn to supercharge your development workflow with AI-powered command-line assistance.**
+
+GitHub Copilot CLI brings AI assistance directly to your terminal. Instead of switching to a browser or code editor, you can ask questions, generate full-featured applications, review code, generate tests, and debug issues without leaving your command line.
+
+Think of it as having a knowledgeable colleague available 24/7 who can read your code, explain confusing patterns, and help you work faster!
+
+This course is designed for:
+
+- **Software Developers** who want to use AI from the command line
+- **Terminal users** who prefer keyboard-driven workflows over IDE integrations
+- **Teams looking to standardize** AI-assisted code review and development practices
+
+
+
+
+
+
+
+## 🎯 What You'll Learn
+
+This hands-on course takes you from zero to productive with GitHub Copilot CLI. You'll work with a single Python book collection app throughout all chapters, progressively improving it using AI-assisted workflows. By the end, you'll confidently use AI to review code, generate tests, debug issues, and automate workflows: all from your terminal.
+
+**No AI experience required.** If you can use a terminal, you can learn this.
+
+**Perfect for:** Developers, students, and anyone who has experience with software development.
+
+## ✅ Prerequisites
+
+Before starting, ensure you have:
+
+- **GitHub account**: [Create one free](https://github.com/signup)
+- **GitHub Copilot access**: [Free offering](https://github.com/features/copilot/plans), [Monthly subscription](https://github.com/features/copilot/plans), or [Free for students/teachers](https://education.github.com/pack)
+- **Terminal basics**: Comfortable with `cd`, `ls`, running commands
+
+## 🤖 Understanding the GitHub Copilot Family
+
+GitHub Copilot has evolved into a family of AI-powered tools. Here's where each one lives:
+
+| Product | Where It Runs | Description |
+| ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | -------------------------------------------------------- |
+| [**GitHub Copilot CLI**](https://docs.github.com/copilot/how-tos/copilot-cli/cli-getting-started)
(this course) | Your terminal | Terminal-native AI coding assistant |
+| [**GitHub Copilot**](https://docs.github.com/copilot) | VS Code, Visual Studio, JetBrains, etc. | Agent mode, chat, inline suggestions |
+| [**Copilot on GitHub.com**](https://github.com/copilot) | GitHub | Immersive chat about your repos, create agents, and more |
+| [**GitHub Copilot coding agent**](https://docs.github.com/copilot/using-github-copilot/using-copilot-coding-agent-to-work-on-tasks) | GitHub | Assign issues to agents, get PRs back |
+
+This course focuses on **GitHub Copilot CLI**, bringing AI assistance directly to your terminal.
+
+## 📚 Course Structure
+
+
+
+| Chapter | Title | What You'll Build |
+| :-----: | --------------------------------------------------------------------------- | ------------------------------------ |
+| 00 | 🚀 [Quick Start](./00-quick-start/) | Installation and verification |
+| 01 | 👋 [First Steps](./01-setup-and-first-steps/) | Live demos + three interaction modes |
+| 02 | 🔍 [Context and Conversations](./02-context-and-conversations/) | Multi-file project analysis |
+| 03 | ⚡ [Development Workflows](./03-development-workflows/) | Code review, debug, test generation |
+| 04 | 🤖 [Create Specialized AI Assistants](./04-agents-and-custom-instructions/) | Custom agents for your workflow |
+| 05 | 🛠️ [Automate Repetitive Tasks](./05-skills/) | Skills that load automatically |
+| 06 | 🔌 [Connect to GitHub, Databases & APIs](./06-mcp-servers/) | MCP server integration |
+| 07 | 🎯 [Putting It All Together](./07-putting-it-all-together/) | Complete feature workflows |
+
+## 📖 How This Course Works
+
+Each chapter follows the same pattern:
+
+1. **Real-World Analogy**: Understand the concept through familiar comparisons
+2. **Core Concepts**: Learn the essential knowledge
+3. **Hands-On Examples**: Run actual commands and see results
+4. **Assignment**: Practice what you learned
+5. **What's Next**: Preview of the following chapter
+
+**Code examples are runnable.** Every copilot text block in this course can be copied and run in your terminal.
+
+## 📋 GitHub Copilot CLI Command Reference
+
+The **[GitHub Copilot CLI command reference](https://docs.github.com/en/copilot/reference/cli-command-reference)** helps you find commands and keyboard shortcuts to help you use Copilot CLI effectively.
+
+## 🙋 Getting Help
+
+- 🐛 **Found a bug?** [Open an Issue](https://github.com/github/copilot-cli-for-beginners/issues)
+- 🤝 **Want to contribute?** PRs welcome!
+- 📚 **Official Docs:** [GitHub Copilot CLI Documentation](https://docs.github.com/copilot/concepts/agents/about-copilot-cli)
+
+## License
+
+This project is licensed under the terms of the MIT open source license. Please refer to the [LICENSE](https://github.com/github/copilot-cli-for-beginners/blob/main/LICENSE) file for the full terms.
diff --git a/website/src/content/docs/learning-hub/index.md b/website/src/content/docs/learning-hub/index.md
index b0eff9e92..c7fa0526f 100644
--- a/website/src/content/docs/learning-hub/index.md
+++ b/website/src/content/docs/learning-hub/index.md
@@ -1,6 +1,6 @@
---
title: Learning Hub
-description: 'Curated articles, walkthroughs, and reference material to help you unlock everything you can do with GitHub Copilot'
+description: "Curated articles, walkthroughs, and reference material to help you unlock everything you can do with GitHub Copilot"
tableOfContents: false
---
@@ -21,3 +21,9 @@ for definitions of common terms and concepts.
Interactive samples and recipes to learn by doing. Jump into the
[Cookbook](cookbook/) for code samples, recipes,
and examples you can use right away.
+
+## Copilot CLI for Beginners
+
+Looking for a guided path into GitHub Copilot from the terminal? Start with
+[Copilot CLI for Beginners](cli-for-beginners/) for a course overview,
+then work through chapters 00 through 07 at your own pace.
diff --git a/website/src/styles/global.css b/website/src/styles/global.css
index 84aab1c61..276494d6b 100644
--- a/website/src/styles/global.css
+++ b/website/src/styles/global.css
@@ -9,7 +9,7 @@
/* Nerd Fonts for programming language icons */
@font-face {
font-family: 'Monaspace Argon NF';
- src: url('../../public/fonts/MonaspaceArgonNF-Regular.woff2') format('woff2');
+ src: url('/fonts/MonaspaceArgonNF-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
@@ -619,6 +619,129 @@ body:has(#main-content) {
color: var(--color-text);
}
+
+/* Repo launch CTA */
+.repo-launch-cta {
+ margin: 32px 0;
+}
+
+.repo-launch-cta__inner {
+ background: var(--color-bg-secondary);
+ border: 1px solid var(--color-border);
+ border-radius: var(--border-radius-lg);
+ padding: 28px;
+ position: relative;
+ overflow: hidden;
+}
+
+.repo-launch-cta__inner::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 3px;
+ background: var(--gradient-primary);
+}
+
+.repo-launch-cta__eyebrow {
+ display: inline-block;
+ margin: 0 0 10px;
+ font-size: 12px;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--color-accent-hover);
+}
+
+.repo-launch-cta__title {
+ margin: 0;
+ font-size: 1.35rem;
+ color: var(--color-text-emphasis);
+}
+
+.repo-launch-cta__description {
+ margin: 12px 0 0;
+ color: var(--color-text-muted);
+ line-height: 1.65;
+}
+
+.repo-launch-cta__actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+ margin-top: 20px;
+}
+
+.repo-launch-cta__actions .btn {
+ white-space: nowrap;
+}
+
+.repo-launch-cta__grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
+ gap: 16px;
+ margin-top: 20px;
+}
+
+.repo-launch-cta__card {
+ background: var(--color-card-bg);
+ border: 1px solid var(--color-glass-border);
+ border-radius: var(--border-radius);
+ padding: 18px;
+}
+
+.repo-launch-cta__card h3 {
+ margin: 0;
+ font-size: 1rem;
+ color: var(--color-text-emphasis);
+}
+
+.repo-launch-cta__card p {
+ margin: 10px 0 0;
+ font-size: 0.95rem;
+ color: var(--color-text-muted);
+ line-height: 1.6;
+}
+
+.repo-launch-cta__card-links {
+ margin: 10px 0 0;
+ padding-left: 18px;
+ color: var(--color-text-muted);
+}
+
+.repo-launch-cta__card-links li + li {
+ margin-top: 6px;
+}
+
+.repo-launch-cta__code {
+ display: block;
+ margin-top: 12px;
+ padding: 10px 12px;
+ font-family: var(--font-mono);
+ font-size: 0.88rem;
+ line-height: 1.5;
+ color: var(--color-text);
+ background: var(--color-bg);
+ border: 1px solid var(--color-glass-border);
+ border-radius: var(--border-radius);
+ overflow-x: auto;
+}
+
+@media (max-width: 768px) {
+ .repo-launch-cta__inner {
+ padding: 24px;
+ }
+
+ .repo-launch-cta__actions {
+ flex-direction: column;
+ }
+
+ .repo-launch-cta__actions .btn {
+ justify-content: center;
+ }
+}
+
/* Split Button Dropdown */
.install-dropdown {
position: relative;