# Extensions, skills, and slash commands

> Scan project/user commands, skills, and agents; install skills from marketplace; plugin marketplaces; GStack workflow modes; and command autocomplete in chat.

- Repository: Parcha-ai/build
- GitHub: https://github.com/Parcha-ai/build
- Human docs: https://grok-wiki.com/public/docs/parcha-ai-build-bea5702b371b
- Complete Markdown: https://grok-wiki.com/public/docs/parcha-ai-build-bea5702b371b/llms-full.txt

## Source Files

- `src/main/services/extension.service.ts`
- `src/main/ipc/extension.ipc.ts`
- `src/main/services/plugin.service.ts`
- `src/main/services/gstack.service.ts`
- `src/renderer/components/extensions/UnifiedMarketplace.tsx`
- `src/renderer/components/chat/CommandAutocomplete.tsx`

---

---
title: "Extensions, skills, and slash commands"
description: "Scan project/user commands, skills, and agents; install skills from marketplace; plugin marketplaces; GStack workflow modes; and command autocomplete in chat."
---

Build discovers Claude Code–compatible extensions on disk (commands, skills, agents), exposes them through main-process scanners and IPC, and surfaces them in the Extensions side panel and chat autocomplete. Plugin and MCP marketplaces install additional capabilities via the Claude CLI and `npx`; GStack adds a separate workflow skill pack under `~/.claude/skills/gstack` with per-session mode state and optional system-prompt routing.

## Architecture

```mermaid
flowchart TB
  subgraph disk [On-disk layout]
    UC["~/.claude/commands|skills|agents"]
    PC["{project}/.claude/..."]
    PM["~/.claude/plugins/marketplaces"]
    GS["~/.claude/skills/gstack"]
  end

  subgraph main [Main process]
    ES[extension.service.ts]
    PS[plugin.service.ts]
    GSvc[gstack.service.ts]
    EIPC[extension.ipc.ts]
    PIPC[plugin.ipc.ts]
    SSH[ssh.service.ts]
  end

  subgraph renderer [Renderer]
    EE[ExtensionsExplorer]
    UM[UnifiedMarketplace]
    IA[InputArea / CompactInputArea]
    CA[CommandAutocomplete]
  end

  UC --> ES
  PC --> ES
  PM --> PS
  GS --> GSvc
  ES --> EIPC
  PS --> PIPC
  GSvc --> index[index.ts GSTACK handlers]
  EIPC -->|contextBridge| EE
  EIPC --> IA
  PIPC --> UM
  SSH --> EIPC
  IA --> CA
```

| Layer | Module | Responsibility |
|-------|--------|----------------|
| Scan | `ExtensionService` | Walk `~/.claude` and project `.claude` trees for commands, skills, agents |
| Plugins | `PluginService` | Read `known_marketplaces.json`, parse manifests, shell out to `claude plugin` |
| GStack | `gstack.service.ts` | Discover gstack skill dirs, install/upgrade from GitHub, build routing prompt |
| IPC | `extension.ipc.ts`, `plugin.ipc.ts`, `index.ts` | Typed invoke handlers; SSH branches for remote sessions |
| UI | `ExtensionsExplorer`, `UnifiedMarketplace`, `CommandAutocomplete` | Browse, install, autocomplete in chat |

## On-disk extension layout

Build follows Claude Code conventions. User scope lives under the home directory; project scope under one or more `.claude` directories in the workspace.

| Kind | User path | Project path | File pattern |
|------|-----------|--------------|--------------|
| Commands | `~/.claude/commands/` | `{project}/.claude/commands/` (and nested `.claude` dirs, depth ≤ 3) | `*.md`; nested dirs become `namespace:command` names |
| Skills | `~/.claude/skills/{name}/` | Same under each discovered `.claude/skills/` | `SKILL.md` per skill directory |
| Agents | `~/.claude/agents/` | `{claudeDir}/agents/` | `*.md` with `#` description and `## System Prompt` / `## Prompt` sections |

**Command metadata:** The first line may be an HTML comment `<!-- description -->` parsed as `description`.

**Skill metadata:** The first heading line (`# Title`) becomes `description` when present.

**Agent parsing:** Agents without both a description paragraph and a system prompt section are skipped.

`ExtensionService.scanRootSkills()` scans only `~/.claude/skills` and `{projectPath}/.claude/skills` (no nested `.claude` walk). That method is not exposed over IPC; the UI and IPC use `scanSkills()`, which recursively discovers all skill directories under each `.claude/skills` tree.

## Scanning behavior

`ExtensionService` (`src/main/services/extension.service.ts`):

- **Commands:** `scanCommands(projectPath?)` merges user commands, then every `.claude/commands` found by `findClaudeDirs()` (skips `node_modules`, `.git`, `dist`, `build`, `.next`, `target`).
- **Skills:** `scanSkillsRec()` accepts directories and symlinks to directories; reads `SKILL.md` or recurses if missing.
- **Agents:** Recursive `.md` scan with `parseAgent()`.
- **Lookup:** `getCommandContent(cmdName, projPath?)` re-scans and matches by full namespaced name.

Returned shapes match shared types `Command`, `Skill`, and `AgentDefinition` (`scope`: `'user' | 'project'`).

## IPC and preload API

Handlers are registered in `registerExtensionHandlers()` and exposed as `window.electronAPI.extensions` in `preload.ts`.

| Channel constant | Invoke signature | Behavior |
|------------------|------------------|----------|
| `extension:scan-commands` | `{ sessionId?, projectPath? }` or legacy `projectPath` string | Local scan or `sshService.scanRemoteCommands` when session has `sshConfig` |
| `extension:scan-skills` | Same | Local or `scanRemoteSkills` |
| `extension:scan-agents` | Same | Local or `scanRemoteAgents` |
| `extension:get-command` | `commandName`, `projectPath?` | Returns markdown body or `null` |
| `extension:install-skill` | `source`, `{ global?, skills?, projectPath?, sessionId? }` | Runs `npx skills add <source> -y [-g] [--skill …] -a claude-code` locally, or remote install via SSH |
| `extension:list-available-skills` | `source` | Runs `npx skills list <source>` and parses stdout |

<Note>
SSH sessions route extension scans and skill installs through `ssh.service.ts` using remote `find`/`cat` over the SSH bridge, using `remoteWorkdir` from session config.
</Note>

## Extensions Explorer (installed tab)

`ExtensionsExplorer` loads in the session side panel (`MainContent.tsx`) with `sessionId` and `projectPath` (worktree path).

On mount it parallel-fetches:

- `extensions.scanCommands|scanSkills|scanAgents`
- `mcp.getServers`
- `plugins.getInstalled`

Sections: **Commands**, **Skills**, **Agents**, **MCP servers**, **Plugins**, plus a **Marketplace** tab hosting `UnifiedMarketplace`.

**Skill install (marketplace/catalog):**

- GitHub/catalog: `extensions.installSkill(source, { global, projectPath, sessionId })` → `npx skills add`.
- Local file upload: writes `{base}/.claude/skills/{name}/SKILL.md` via `fs.writeFile` (supports SSH `sessionId`).

**Create skill:** In-app dialog writes a new `SKILL.md` from a template.

Empty states point users at `.claude/commands/*.md` and skill directory layout.

## Plugin marketplaces

`PluginService` manages Claude Code plugins under `~/.claude/plugins/`:

- **Registry file:** `known_marketplaces.json` lists configured marketplaces and `installLocation`.
- **Discovery:** `getAvailablePlugins()` reads each marketplace’s `.claude-plugin/marketplace.json` and flags content types (`commands`, `skills`, `agents`, `hooks`, `mcp`).
- **CLI:** Requires `claude` on PATH (`resolveClaudeCli()`); uses `claude plugin list|install|uninstall|enable|disable` and `claude plugin marketplace add|remove|update`.

`POPULAR_MARKETPLACES` seeds the UI with curated GitHub repos (official Anthropic marketplaces and community catalogs).

| Preload API | IPC channel |
|-------------|-------------|
| `plugins.getPopularMarketplaces()` | `plugin:get-popular-marketplaces` |
| `plugins.getMarketplaces()` | `plugin:get-marketplaces` |
| `plugins.getInstalled()` | `plugin:get-installed` |
| `plugins.getAvailable()` | `plugin:get-available` |
| `plugins.install(id, marketplace, { scope? })` | `plugin:install` |
| `plugins.enable` / `disable` / `uninstall` | matching channels |
| `plugins.addMarketplace(source)` | `plugin:add-marketplace` |
| `plugins.updateMarketplaces(name?)` | `plugin:update-marketplace` |

Installed plugins show `id` as `{name}@{marketplace}`, version, scope, and enabled flag parsed from `claude plugin list` output.

## Unified Marketplace

`UnifiedMarketplace` combines two tabs:

1. **MCP Servers** — `mcp.getMarketplace()` registry browse; install via `MCPInstallDialog` or custom npm/remote dialog (`mcp.installRaw`).
2. **Plugins** — `plugins.getAvailable()`; install/enable/disable per card; **GitHub** button opens `GitHubPluginInstallDialog` → `plugins.addMarketplace(repo)`.

Refresh runs `plugins.updateMarketplaces()` then reloads both catalogs. Plugin cards show badges for commands, skills, agents, and MCP when manifest scanning detects those folders.

<Info>
MCP marketplace behavior is documented on the MCP servers page. This page only covers the shared marketplace shell and plugin tab.
</Info>

## GStack workflow modes

GStack is the upstream [garrytan/gstack](https://github.com/garrytan/gstack) skill pack, not a copy baked into app logic. Build discovers it from:

1. `~/.claude/skills/gstack` (with `setup/` present)
2. `{cwd}/.claude/skills/gstack`
3. Packaged `process.resourcesPath/gstack` when present

`discoverGStackSkills()` reads each subdirectory’s `SKILL.md` YAML frontmatter (`name`, `description`), applies `SKILL_CATEGORIES` for UI color/shortName, and hides internal utilities (`open-gstack-browser`, `gstack-upgrade`, etc.).

| IPC | Handler |
|-----|---------|
| `gstack:get-modes` | `getGStackModes()` |
| `gstack:is-installed` | `isGStackInstalled()` |
| `gstack:install` | `git clone` + `./setup` into `~/.claude/skills/gstack` |
| `gstack:upgrade` | `git pull` + `./setup` |

**Per-session mode:** `session.gstackMode` (string skill id) is stored in Zustand and persisted via `sessions.update`. `sendMessage` passes `gstackMode` to `CLAUDE_SEND_MESSAGE` for harness routing (e.g. Auto Build tier hints in `auto-router.service.ts`).

**Activation paths:**

- **GStack launcher** (`InputArea`): sends `/{skillId}` as a chat message (Claude Code invokes the skill).
- **Slash autocomplete:** GStack modes appear as pseudo-commands with `itemType: 'gstack'`; selecting sets `gstackMode` without leaving `/shortname` in the buffer when using inline `/` mode.
- **`/gstack-off`:** Clears active mode.

**System prompt routing:** When `AppSettings.gstackEnabled` is `true` (default `false` in `settings.service.ts`), `ClaudeService.buildSystemPromptAppend()` injects `getGStackRoutingPrompt()` — a dynamic list of `/{id}` routes and key mappings (office-hours, investigate, ship, qa, review, etc.).

<ParamField body="gstackEnabled" type="boolean">
Enables GStack routing text in Claude system prompt append. Does not install gstack; use `gstack:install` or the launcher UI.
</ParamField>

<ParamField body="gstackMode" type="string (per session)">
Active GStack skill id for UI accent (session card, thinking block) and Auto Build routing hints.
</ParamField>

## Slash commands and chat autocomplete

`CommandAutocomplete` is a presentational dropdown; parent components own keyboard handling via `CommandAutocompleteHandle` (`selectCurrent`, `moveSelection`, `dismiss`) — no global key listeners inside the dropdown.

**Trigger rules** (`InputArea`, `CompactInputArea`):

- `/` at start of input or after whitespace; query = text after `/` with no spaces.
- `@agent-` after `@` for subagent definitions.

**Filter behavior:**

| `type` prop | Matches |
|-------------|---------|
| `command` | Commands **and** skills (up to 10 combined) |
| `skill` | Skills only |
| `agent` | Agents only |

Display: `/{name}` for commands/skills, `@agent-{name}` for agents; scope shown in parentheses.

**Selection outcomes:**

| `itemType` | Effect |
|------------|--------|
| `command` | `extensions.getCommand` → replace `/name` with file body (HTML comment lines stripped) |
| `skill` / `claude-code` | Insert `/{name}` |
| `agent` | Insert `@agent-{name}` |
| `gstack` | `setGStackMode(sessionId, gstackId \| null)` |
| `codex` (builtin) | Switch model to a `codex:*` id |
| Builtins | `monitor`, `loop` (Claude Code); `codex` second opinion |

`InputArea` also loads GStack modes into the command list (shortName lowercase aliases) and supports a **popover** slash menu (button) vs **inline** `/` typing; popover mode inserts at cursor without requiring a leading `/` in the buffer.

## Provider-neutral skill sources

Skill packs are files, git repos, or catalog URLs — not tied to a single model vendor:

- **Project/user folders:** `.claude/skills` and `.claude/commands`
- **Catalog CLI:** `npx skills add` / `npx skills list` (BYOC: uses local Node/npm)
- **Plugin marketplaces:** any git/GitHub source accepted by `claude plugin marketplace add`
- **GStack:** optional third-party git checkout under `~/.claude/skills/gstack`

Build does not require hosted skill APIs; installation flows shell out to local tooling or SSH remotes.

## Verification

| Check | Expected signal |
|-------|-----------------|
| Local commands visible | Extensions → Commands lists `*.md` under `~/.claude/commands` or project `.claude/commands` |
| Skill install | `npx skills add` succeeds; skills list refreshes in Extensions Explorer |
| Plugin marketplace | `plugins.addMarketplace('owner/repo')` then Plugins tab shows new entries after refresh |
| GStack | `gstack:is-installed` true; launcher lists categorized skills; `/{id}` message invokes skill in harness |
| Autocomplete | Typing `/rev` filters commands/skills; Enter selects via parent `selectCurrent` |
| SSH session | Scans return remote `~/.claude` and `{remoteWorkdir}/.claude` content |

<Warning>
Plugin operations fail if the Claude Code CLI is missing or quarantined on macOS (`resolveClaudeCli()` error). Skill catalog install requires `npx` on PATH in the main process environment.
</Warning>

## Related pages

<CardGroup>
  <Card title="MCP servers" href="/mcp-servers">
    Registry marketplace, stdio/http install, and harness sync — complements the Unified Marketplace MCP tab.
  </Card>
  <Card title="IPC and preload bridge" href="/ipc-bridge">
    How `window.electronAPI` maps to `ipcMain` handlers for extensions, plugins, and GStack.
  </Card>
  <Card title="SSH remote sessions" href="/ssh-remote-sessions">
    Remote extension scans and skill installs over SSH.
  </Card>
  <Card title="Settings reference" href="/settings-reference">
    `gstackEnabled` and other `claudette-settings` keys.
  </Card>
  <Card title="Manage coding sessions" href="/manage-sessions">
    Session fields including `gstackMode` persistence and side panel layout.
  </Card>
</CardGroup>
