Skip to content

feat: APM integration — squad skill publish/install + apm.yml in init#876

Merged
tamirdresher merged 8 commits intobradygaster:insiderfrom
tamirdresher:feature/apm-integration
Apr 8, 2026
Merged

feat: APM integration — squad skill publish/install + apm.yml in init#876
tamirdresher merged 8 commits intobradygaster:insiderfrom
tamirdresher:feature/apm-integration

Conversation

@tamirdresher
Copy link
Copy Markdown
Collaborator

@tamirdresher tamirdresher commented Apr 6, 2026

Summary

Implements #824 — APM (Agent Package Manager) integration into Squad CLI.

What is APM?

APM is \package.json\ for AI agent context. You declare skills, instructions, and prompts in \apm.yml\ and \apm install\ deploys them to .github/, .claude/, .cursor/\ etc.
See: https://github.com/microsoft/apm

Changes

New command: \squad skill\

\
squad skill publish [] Export skill(s) to APM format (updates apm.yml)
squad skill install Install from APM registry
squad skill list List installed skills
\\

Install sources:

  • \owner/repo\ — all skills from a GitHub repo (reads their \apm.yml\ or .squad/skills/)
  • \owner/repo/skill-name\ — a specific named skill
  • \https://...\ — direct URL to a \skill.md\ file

Implementation details:

  • \skill publish\ reads front-matter from \skill.md\ files to populate \apm.yml\
  • \skill install\ uses GitHub CLI (\gh api) to fetch content — no extra dependencies
  • Installed skills get a .apm-source.json\ metadata file for provenance tracking

Updated: \squad init\

Now generates \apm.yml\ at the project root alongside .squad/.
Follows \skipExisting\ semantics — re-running \squad init\ won't overwrite.

Updated: \squad help\

Added \skill\ command to help output.

Design notes

  • .squad/\ remains the source of truth — APM is an additional export layer
  • Skills become portable and community-shareable via APM registry
  • No new npm dependencies added

Closes #824

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

🛫 PR Readiness Check

ℹ️ This comment updates on each push. Last checked: commit e033083

PR Scope: 📦🔧 Mixed (product + infrastructure)

⚠️ 4 item(s) to address before review

Status Check Details
Single commit 8 commits — consider squashing before review
Not in draft Ready for review
Branch up to date insider is 69 commit(s) ahead — rebase recommended
Copilot review No Copilot review yet — it may still be processing
Changeset present Changeset file found
Scope clean ⚠️ PR includes 2 .squad/ file(s) — ensure these are intentional
No merge conflicts Merge conflicts detected — resolve before review
Copilot threads resolved No Copilot review threads
CI passing All checks passing
Issue linked Issue reference found
Protected files No protected bootstrap files changed

Files Changed (12 files, +1328 −1)

File +/−
.changeset/apm-integration.md +7 −0
.squad-templates/squad.agent.md +2 −1
.squad-templates/workflow-wiring-appendix-a-code-reviewer.md +131 −0
.squad-templates/workflow-wiring-appendix-b-documenter.md +140 −0
.squad-templates/workflow-wiring-guide.md +276 −0
.squad/skills/fact-checking/SKILL.md +61 −0
.squad/templates/agents/challenger.md +72 −0
CHANGELOG.md +4 −0
packages/squad-cli/src/cli-entry.ts +10 −0
packages/squad-cli/src/cli/commands/skill.ts +568 −0
packages/squad-cli/src/cli/core/init.ts +55 −0
packages/squad-cli/src/cli/index.ts +2 −0

Total: +1328 −1


This check runs automatically on every push. Fix any ❌ items and push again.
See CONTRIBUTING.md and PR Requirements for details.

@tamirdresher tamirdresher force-pushed the feature/apm-integration branch from a1f9a83 to e781d20 Compare April 6, 2026 07:21
skills.push({
name: fm['name'] ?? entry,
description: fm['description'],
path: `.squad/skills/${entry}/skill.md`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are skills still being saved here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. collectSkills itself is read-only — it scans .squad/skills/*/skill.md, parses front-matter, and returns an in-memory array. No writes happen here.

Skills are persisted in two other places in this file:

  1. publish() — calls collectSkills, then serializes the result into apm.yml via writeFile(apmPath, ...) (around line 155). For single-skill publish, it also writes a per-skill apm.yml inside the skill directory (line 127).

  2. install() — writes the fetched skill.md to .squad/skills/<name>/skill.md and adds an .apm-source.json metadata file for provenance tracking (e.g. lines 259–265 in installFromGitHub).

So the flow is: install saves skills to disk → collectSkills reads them back → publish exports them to apm.yml. The .squad/ directory remains the source of truth as noted in the PR description.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant skills are now regular skills. #430

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — #430 moved skills to .copilot/skills/ as the standard path. This APM code still hardcodes .squad/skills/. I'll update skill.ts to use .copilot/skills/ as primary (with .squad/skills/ fallback for backward compat, same pattern as LocalSkillSource).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*You're absolutely right 😉

Copy link
Copy Markdown

@Omzig Omzig Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

they closed my enhancement request to get those paths normalized and added to default settings :(

@Omzig
Copy link
Copy Markdown

Omzig commented Apr 6, 2026

FYI; i put in a manual fix to the front matter and the cli does not see the nap command but the copilot chat does:

image

@Omzig
Copy link
Copy Markdown

Omzig commented Apr 6, 2026

after more research, it looks like .copilot/* is not a supported folder in the repo for the github Copilot CLI:
https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/create-skills

@Omzig
Copy link
Copy Markdown

Omzig commented Apr 6, 2026

I added an enhancement request for copilot:

They closed my enhancement request.

@tamirdresher tamirdresher changed the base branch from main to insider April 8, 2026 05:33
joniba and others added 6 commits April 8, 2026 08:34
…bradygaster#592)

Fixes bradygaster#591

- Added step 7 (Wire enforcement) to Adding Team Members in squad.agent.md
- Added workflow-wiring-guide.md with configuration surface area, wiring instructions, common mistakes, and verification checklist
- Added appendix walkthroughs for code reviewer (gate pattern) and documenter (follow-up trigger pattern)

Co-authored-by: Jonathan Ben Ami <jbenami@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-checking skill (bradygaster#603)

* feat(skills): add fact-checking skill\n\nAdds challenger/fact-checking review pattern.\nVerified against 200+ issues in production squads.\nCloses bradygaster#598

* feat(agents): add challenger agent charter template\n\nGeneric Devil's Advocate / Challenger template.\nProvides auto-spawn integration pattern for coordinators.\nCloses bradygaster#598
Closes bradygaster#824

## Changes

### New command: squad skill
- squad skill publish [<name>] — exports skill(s) to APM format, generating/updating apm.yml
- squad skill install <source> — installs a skill from APM registry
  - Supports owner/repo, owner/repo/skill-name, and direct URLs
  - Uses GitHub CLI to fetch from repos that have apm.yml or .squad/skills/
  - Writes .apm-source.json metadata to track skill origin
- squad skill list — lists installed skills with source provenance

### Updated: squad init
- Now generates �pm.yml at project root alongside .squad/
- Follows skipExisting semantics (safe to re-run)
- apm.yml includes skills, instructions, and prompts sections

### Updated: squad help
- Added skill command to help text with usage examples

## APM format
apm.yml is the Agent Package Manager manifest — package.json for AI agent context.
See: https://github.com/microsoft/apm

The manifest declares skills, instructions, and prompts in a portable format
that �pm install can deploy to .github/, .claude/, .cursor/ etc.
The skills unification in bradygaster#430 migrated skills from .squad/skills/
to .copilot/skills/. This updates the APM skill command to:

- Check .copilot/skills/ first, fall back to .squad/skills/ (backward compat)
- Use resolveSkillsDir() helper matching LocalSkillSource pattern
- Update all user-facing messages and apm.yml template paths
- Fix installSkillsFromSquadDir candidate order

Addresses review feedback from @Meir017.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tamirdresher tamirdresher force-pushed the feature/apm-integration branch from e033083 to f2f4201 Compare April 8, 2026 05:35
@tamirdresher tamirdresher added the skip-version-check Skip prerelease version guard for this PR label Apr 8, 2026
Copilot and others added 2 commits April 8, 2026 11:56
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tamirdresher tamirdresher merged commit 6e72c8a into bradygaster:insider Apr 8, 2026
12 checks passed
@diberry
Copy link
Copy Markdown
Collaborator

diberry commented Apr 8, 2026

⚛️ Post-Merge Review — River (TypeScript Architect)

Verdict: 🟡 Conditional Approval — Architecture is sound, type safety needs follow-ups.

What's Good

  • .squad/ is source of truth, APM is export layer — Clean separation. No coupling inversion.
  • ApmSkill and ApmManifest interfaces — Good starting contracts, exported from barrel.
  • Command routing follows existing patterns. generateApmYml is idempotent.
  • Zero new npm dependencies — disciplined.

Type Safety Findings

# Severity Finding Location
1 🔴 catch (err: any) ×2 — Should be unknown with narrowing skill.ts:1057, 1171
2 🟡 as { name: string; path: string } ×3 — Replace with type guard skill.ts:1117, 1125, 1131
3 🟡 Non-null assertions (!) ×6 — Regex groups and array indices aren't narrowed by TS scattered
4 🟡 parseFrontMatter returns Record<string, string> — stringly typed, no compile-time contract skill.ts:819
5 🟡 ApmManifest declared but never validated at runtime — type exists as documentation only skill.ts:807-814
6 🟠 generateApmYml uses sync fs (writeFileSync) while skill.ts is fully async init.ts:1397
7 🔴 No YAML value escaping — skill names/descriptions containing :, #, quotes, or newlines produce invalid YAML publish(), generateApmYml()

Architecture Risks

  • 🔴 Hand-rolled YAML parser in installFromGitHub — line-splitting and regex will silently break on multi-line strings, inline comments, quoted values with colons, flow sequences. Single biggest correctness risk.
  • 🟡 Silent error swallowingcollectSkills, readProjectName, listSkills all have catch { /* ignore */ }. Corrupted skill files are silently skipped.
  • 🟡 568 lines in one fileskill.ts handles YAML parsing, GitHub API calls, URL fetching, file I/O, manifest generation, and CLI routing. Should be split.
  • Zero test files for 568 lines of new code. The hand-rolled YAML parser is too risky to ship untested.

Recommended Follow-Ups (Priority Order)

  1. Add YAML value escaping for all publish/init output paths (data corruption bug)
  2. Add unit tests for YAML parsing — at least 5 cases
  3. Replace catch (err: any) with catch (err: unknown) — 2 instances
  4. Add parseApmManifest() runtime validator
  5. Consider yaml npm package (0 deps, 50KB) vs maintaining regex parser

Review by Squad AI team (River — TypeScript Architect) · requested by Dina Berry

@tamirdresher
Copy link
Copy Markdown
Collaborator Author

Thanks @diberry — River's review is solid. Filed #924 to track all findings. The YAML escaping and hand-rolled parser are the highest priority. Also noting @Omzig's finding that .copilot/skills/\ isn't supported by Copilot CLI — that affects our resolveSkillsDir() approach.

tamirdresher pushed a commit to tamirdresher/squad that referenced this pull request Apr 8, 2026
…#900, bradygaster#875)

- Add YAML value escaping helper for skill metadata
- Replace catch(err: any) with catch(err: unknown) + narrowing
- Add type guards to replace unsafe type assertions
- Standardize deprecation messages on `gh copilot`
- Fix unsafe exports type cast in cross-package test

Closes bradygaster#924, bradygaster#925, bradygaster#926

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster pushed a commit that referenced this pull request Apr 12, 2026
- Add YAML value escaping helper for skill metadata
- Replace catch(err: any) with catch(err: unknown) + narrowing
- Add type guards to replace unsafe type assertions
- Standardize deprecation messages on `gh copilot`
- Fix unsafe exports type cast in cross-package test

Closes #924, #925, #926

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster added a commit that referenced this pull request Apr 12, 2026
* fix: address post-merge review findings (#876, #900, #875)

- Add YAML value escaping helper for skill metadata
- Replace catch(err: any) with catch(err: unknown) + narrowing
- Add type guards to replace unsafe type assertions
- Standardize deprecation messages on `gh copilot`
- Fix unsafe exports type cast in cross-package test

Closes #924, #925, #926

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add changeset for review findings fix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: trigger CI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(.squad): EECOM history — PR #942 rebase learnings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: update changeset to accurately reflect PR changes (drop YAML escaping reference)

Agent-Logs-Url: https://github.com/bradygaster/squad/sessions/54f41407-61bf-4977-85b7-572341c47b62

Co-authored-by: bradygaster <41929050+bradygaster@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
tamirdresher added a commit that referenced this pull request Apr 21, 2026
…#876)

* Add enforcement wiring step to hiring process + workflow wiring guide (#592)

Fixes #591

- Added step 7 (Wire enforcement) to Adding Team Members in squad.agent.md
- Added workflow-wiring-guide.md with configuration surface area, wiring instructions, common mistakes, and verification checklist
- Added appendix walkthroughs for code reviewer (gate pattern) and documenter (follow-up trigger pattern)

Co-authored-by: Jonathan Ben Ami <jbenami@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(agents): add Challenger / Devil's Advocate agent template + fact-checking skill (#603)

* feat(skills): add fact-checking skill\n\nAdds challenger/fact-checking review pattern.\nVerified against 200+ issues in production squads.\nCloses #598

* feat(agents): add challenger agent charter template\n\nGeneric Devil's Advocate / Challenger template.\nProvides auto-spawn integration pattern for coordinators.\nCloses #598

* feat: add APM integration for skill publishing and installation

Closes #824

## Changes

### New command: squad skill
- squad skill publish [<name>] — exports skill(s) to APM format, generating/updating apm.yml
- squad skill install <source> — installs a skill from APM registry
  - Supports owner/repo, owner/repo/skill-name, and direct URLs
  - Uses GitHub CLI to fetch from repos that have apm.yml or .squad/skills/
  - Writes .apm-source.json metadata to track skill origin
- squad skill list — lists installed skills with source provenance

### Updated: squad init
- Now generates �pm.yml at project root alongside .squad/
- Follows skipExisting semantics (safe to re-run)
- apm.yml includes skills, instructions, and prompts sections

### Updated: squad help
- Added skill command to help text with usage examples

## APM format
apm.yml is the Agent Package Manager manifest — package.json for AI agent context.
See: https://github.com/microsoft/apm

The manifest declares skills, instructions, and prompts in a portable format
that �pm install can deploy to .github/, .claude/, .cursor/ etc.

* chore: add changeset for APM integration

* docs: update CHANGELOG.md with APM integration entry

* fix(skill): use .copilot/skills/ as primary path per #430

The skills unification in #430 migrated skills from .squad/skills/
to .copilot/skills/. This updates the APM skill command to:

- Check .copilot/skills/ first, fall back to .squad/skills/ (backward compat)
- Use resolveSkillsDir() helper matching LocalSkillSource pattern
- Update all user-facing messages and apm.yml template paths
- Fix installSkillsFromSquadDir candidate order

Addresses review feedback from @Meir017.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align CHANGELOG.md with dev branch

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: add missing fs import in init.ts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: joniba <joniba@users.noreply.github.com>
Co-authored-by: Jonathan Ben Ami <jbenami@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <Copilot@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
tamirdresher pushed a commit that referenced this pull request Apr 21, 2026
* fix: address post-merge review findings (#876, #900, #875)

- Add YAML value escaping helper for skill metadata
- Replace catch(err: any) with catch(err: unknown) + narrowing
- Add type guards to replace unsafe type assertions
- Standardize deprecation messages on `gh copilot`
- Fix unsafe exports type cast in cross-package test

Closes #924, #925, #926

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add changeset for review findings fix

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: trigger CI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(.squad): EECOM history — PR #942 rebase learnings

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: update changeset to accurately reflect PR changes (drop YAML escaping reference)

Agent-Logs-Url: https://github.com/bradygaster/squad/sessions/54f41407-61bf-4977-85b7-572341c47b62

Co-authored-by: bradygaster <41929050+bradygaster@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
tamirdresher pushed a commit that referenced this pull request Apr 21, 2026
The skill.ts command file existed but was never imported in
cli-entry.ts, causing the cli-command-wiring test to fail.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-version-check Skip prerelease version guard for this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants