AI Engineering Fluency canvas β Copilot plugin
This folder is the root of the ai-fluency-canvas Copilot plugin: a
GitHub Copilot app canvas that shows your AI Engineering
Fluency stats (token usage, cost, sessions, charts, fluency score) from local session logs.
π Install and usage docs for users: docs/copilot-app/README.md
Layout
copilot-app/ <- plugin root (marketplace "source": "./copilot-app")
βββ plugin.json <- Agent Plugins 1.0 manifest (closed schema)
βββ skills/ai-fluency/SKILL.md <- tells the agent when/how to open the canvas
βββ com.github.copilot/extensions/ai-fluency/ <- the canvas extension (canvasId "ai-fluency")
β βββ extension.mjs <- entry point: hands the Copilot SDK to canvas.mjs
β βββ canvas.mjs <- registers the canvas and its agent actions
β βββ cli.mjs refresher.mjs store.mjs server.mjs panels.mjs
β βββ assets/ <- UI served on 127.0.0.1 (index.html, app.js, style.css)
β βββ copilot-extension.json <- only for the app's manual "Install extension" flow
β βββ test/ <- canvas unit tests (synthetic fixtures)
β βββ README.md <- how the canvas works
βββ test/manifest.test.mjs <- plugin.json / marketplace.json / no-personal-data checks
The marketplace catalog lives at .github/plugin/marketplace.json
(marketplace name ai-engineering-fluency).
The extension folder keeps the name ai-fluency so the canvasId and the snapshot location
($COPILOT_HOME/extensions/ai-fluency/artifacts/) stay the same whether the canvas is installed
as a plugin or copied by hand. Snapshots are never written inside this folder; .gitignore
and test/manifest.test.mjs both guard against committing an artifacts/ directory,
snapshot.json or refresh.lock* files.
Tests
No dependencies β plain node --test (Node.js 22+). From the repository root:
node --test "copilot-app/**/*.test.mjs"
CI runs the same command in .github/workflows/copilot-app.yml.
Versioning and releasing
- Bump
versionin bothcopilot-app/plugin.jsonand theai-fluency-canvasentry in.github/plugin/marketplace.json(semver).test/manifest.test.mjsfails if they differ. - Merge to
main. The marketplace is read straight from the repository, so there is no separate publish step. - Users pick up the new version with
copilot plugin marketplace updatefollowed bycopilot plugin update ai-fluency-canvas(or the Update action in the app).
Trying a branch before it is merged
Use a fresh, isolated config directory so nothing is installed into your real ~/.copilot. The
finally block restores your previous COPILOT_HOME and deletes only the folder this run created:
$testHome = Join-Path ([IO.Path]::GetTempPath()) "copilot-plugin-test-$([guid]::NewGuid())"
$previousHome = $env:COPILOT_HOME
try {
$env:COPILOT_HOME = $testHome
copilot plugin marketplace add rajbos/ai-engineering-fluency#<branch>
copilot plugin install ai-fluency-canvas@ai-engineering-fluency
copilot plugin list
} finally {
$env:COPILOT_HOME = $previousHome
Remove-Item -LiteralPath $testHome -Recurse -Force -ErrorAction SilentlyContinue
}
To try it in the Copilot app itself, install into your real config instead (after removing any manually installed copy β see "Migrating" in the user docs).