Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion framework/agents/_shared/cli-tools-protocol.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Avant d'utiliser un outil, vérifier sa disponibilité :
- **Google Workspace** : `gws` (`recommended` depuis 2026-04-29) — remplace les MCPs Calendar + Gmail + Drive (~10-12K tokens cumulés économisés). Install : `npm i -g @googleworkspace/cli`
- **Base de données** : `neonctl` si Neon, sinon `psql`/`mysql` direct
- **Containers** : `docker`, `kubectl` direct
- **Capture web** : `shot-scraper` (`required` depuis 2026-05-06) — **toute capture web sans exception** : screenshots, JS execution, arbre d'accessibilité. Remplace `mcp__chrome-devtools__*` globalement. Protocole : `_shared/shot-scraper-protocol.md`. Install : `pip install shot-scraper && shot-scraper install`.

## Linear — CLI-first (depuis 2026-04-29)

Expand Down Expand Up @@ -71,7 +72,7 @@ Ces 5 MCPs n'ont pas de CLI viable couvrant 80%+ du besoin — les conserver :
| **Figma** | Lecture des nodes/tokens/variables Figma impossible sans API | `mcp__plugin_figma_figma__*` |
| **Linear** | MCP fallback quand `LINEAR_API_KEY` absent ou pour opérations complexes | `mcp__claude_ai_Linear__*` |
| **Pencil/Penpot** | Design interactif .pen files — aucun équivalent CLI | `mcp__pencil__*` |
| **Chrome DevTools** | Automation browser — seul MCP autorisé (jamais `claude-in-chrome` ni Playwright) | `mcp__plugin_chrome-devtools-mcp_chrome-devtools__*` |
| **Chrome DevTools** | ⚠️ Remplacé par `shot-scraper` CLI depuis 2026-05-06 — n'utiliser que si `shot-scraper` non disponible et pour les cas réseau (network monitoring) non couverts | `mcp__plugin_chrome-devtools-mcp_chrome-devtools__*` |
| **shadcn registry** | Accès au registre de composants shadcn/ui — pas de CLI équivalent | `mcp__clerk__*` |

## Drifts à surveiller
Expand Down
9 changes: 5 additions & 4 deletions framework/cli/internal/installer/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,11 @@ var All = []Installable{

// --- External tools ---
&ExternalModule{
base: base{key: "shot-scraper", flag: "--with-shot-scraper", label: "shot-scraper", description: "captures web headless (screenshots, JS, accessibilité) — remplace mcp__chrome-devtools__* (required)", category: "tools"},
dep: "pip3",
runCmd: []string{"sh", "-c", "pip3 install shot-scraper && shot-scraper install"},
message: "pip3 requis : brew install python3 (macOS) · apt install python3-pip (Linux)",
base: base{key: "shot-scraper", flag: "--with-shot-scraper", label: "shot-scraper", description: "captures web headless (screenshots, JS, accessibilité) — remplace mcp__chrome-devtools__* (required)", enabledByDefault: true, category: "tools"},
dep: "pip3",
runCmd: []string{"sh", "-c", "pip3 install shot-scraper && shot-scraper install"},
message: "pip3 requis : brew install python3 (macOS) · apt install python3-pip (Linux)",
skipIfInstalled: "shot-scraper",
},
&NoopModule{
base: base{key: "faru", flag: "--with-faru", label: "faru", description: "kanban git-natif agent-first — crée docs/backlog/ (installe faru manuellement : npm install -g faru)", category: "tools"},
Expand Down
17 changes: 13 additions & 4 deletions framework/cli/internal/installer/external.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import (
// ExternalModule installs a tool via an external CLI (npm, npx, pip…).
// If msgOnly is true, it only prints installation instructions without running anything.
// If dep is set and the required CLI is missing, it prints a hint and skips.
// If skipIfInstalled is set and that command is found in PATH, the install is skipped (idempotent).
type ExternalModule struct {
base
dep string // required CLI dependency (checked via exec.LookPath)
runCmd []string // command to execute when dep is found
msgOnly bool // skip execution, print message instead
message string // informational message (used when msgOnly or on dep-miss)
dep string // required CLI dependency (checked via exec.LookPath)
runCmd []string // command to execute when dep is found
msgOnly bool // skip execution, print message instead
message string // informational message (used when msgOnly or on dep-miss)
skipIfInstalled string // if non-empty, skip install when this command is already in PATH
}

func (m *ExternalModule) Install(ctx *Context) error {
Expand All @@ -23,6 +25,13 @@ func (m *ExternalModule) Install(ctx *Context) error {
return nil
}

if m.skipIfInstalled != "" {
if _, err := exec.LookPath(m.skipIfInstalled); err == nil {
ctx.progress(m.label, "déjà installé")
return nil
}
}

if m.dep != "" {
if _, err := exec.LookPath(m.dep); err != nil {
hint := m.message
Expand Down
4 changes: 2 additions & 2 deletions framework/cli/internal/installer/modules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ func TestDefaultModules(t *testing.T) {
t.Errorf("DefaultModules len: got %d, want %d", len(defaults), len(All))
}
// modules enabled by default
for _, key := range []string{"figma-skills", "swift-skills", "flutter-skills", "context-audit", "obsidian-skills", "symbols", "architecture-diagram", "rtk-hook"} {
for _, key := range []string{"figma-skills", "swift-skills", "flutter-skills", "context-audit", "obsidian-skills", "symbols", "architecture-diagram", "rtk-hook", "shot-scraper"} {
if !defaults[key] {
t.Errorf("%s should be enabled by default", key)
}
}
// modules disabled by default
for _, key := range []string{"vps", "agent-teams", "memory-loop", "xavier-hook", "hue", "caveman", "caveman-output", "logo-generator", "accountability", "context-mode", "refusal-scope", "sentinel", "statusline", "figma-mcp", "shot-scraper", "faru", "kami", "code-graph", "cloud-clis", "database-clis", "security-clis", "notif-clis", "container-clis", "monitoring-clis", "ai-clis", "doc-clis", "data-clis", "design-clis", "devops-clis", "mobile-clis"} {
for _, key := range []string{"vps", "agent-teams", "memory-loop", "xavier-hook", "hue", "caveman", "caveman-output", "logo-generator", "accountability", "context-mode", "refusal-scope", "sentinel", "statusline", "figma-mcp", "faru", "kami", "code-graph", "cloud-clis", "database-clis", "security-clis", "notif-clis", "container-clis", "monitoring-clis", "ai-clis", "doc-clis", "data-clis", "design-clis", "devops-clis", "mobile-clis"} {
if defaults[key] {
t.Errorf("%s should be disabled by default", key)
}
Expand Down
Loading