diff --git a/CLAUDE.md b/CLAUDE.md index 80740bb5..b4fa6e13 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,3 +68,19 @@ The CLI dogfoods itself — see `.archgate/adrs/` for the full list of ADRs and ## ADR Format YAML frontmatter (`id`, `title`, `domain`, `rules`, optional `files`). Sections: Context, Decision, Do's and Don'ts, Consequences, Compliance, References. Companion `.rules.ts` exports a plain object `satisfies RuleSet`. + +## Adding a New Editor Target + +Editor integrations share the `EditorTarget` union. Adding a new editor requires coordinated edits — missing any one breaks detection, init, or tests: + +1. `src/helpers/init-project.ts` — extend `EditorTarget` union, `EDITOR_LABELS`, the `configureEditorSettings` switch, and (when authenticated install applies) the `tryInstallPlugin` branch +2. `src/helpers/plugin-install.ts` — add `isCliAvailable()` and any install/download helper +3. `src/helpers/editor-detect.ts` — append to the `Promise.all` and the returned array +4. `src/commands/init.ts` — extend `EDITOR_DIRS`, `SIGNUP_EDITORS`, the `--editor` `.choices([...] as const)`, and `printManualInstructions` +5. `src/commands/plugin/install.ts` — extend `.choices([...] as const)` and add a case to `installForEditor` + the manual-instructions `catch` +6. `src/commands/plugin/url.ts` — extend `.choices([...] as const)` and branch before the URL ternary +7. Tests that assert the exact choice list: `tests/commands/plugin/install.test.ts`, `tests/commands/plugin/url.test.ts`, and `tests/helpers/editor-detect.test.ts` (length + id order) + +User-scope editors (e.g., opencode) write to a path resolved in `paths.ts` rather than the project tree — `configureEditorSettings` returns that path for the init summary and the real work happens in `tryInstallPlugin`. + +**Match the target editor's actual path resolution — don't assume Windows conventions.** opencode uses the `xdg-basedir` npm package, which falls back to `~/.config` on **all platforms** (including Windows, where it resolves to `C:\Users\\.config\…`, not `%APPDATA%\…`). `opencodeAgentsDir()` must mirror that exact logic or the CLI writes files the editor can't find. When adding a user-scope editor, verify the editor's path helper in its source before writing the resolver. diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index bcc7e724..12d0f55e 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -218,6 +218,10 @@ export default defineConfig({ { label: "VS Code Plugin", slug: "guides/vscode-plugin" }, { label: "Copilot CLI Plugin", slug: "guides/copilot-cli-plugin" }, { label: "Cursor Integration", slug: "guides/cursor-integration" }, + { + label: "opencode Integration", + slug: "guides/opencode-integration", + }, { label: "Pre-commit Hooks", slug: "guides/pre-commit-hooks" }, { label: "Security", slug: "guides/security" }, ], diff --git a/docs/public/llms-full.txt b/docs/public/llms-full.txt index 5f788544..94334065 100644 --- a/docs/public/llms-full.txt +++ b/docs/public/llms-full.txt @@ -1586,6 +1586,142 @@ The command accepts two optional flags: --- +## Guides: opencode Integration + +Source: https://cli.archgate.dev/guides/opencode-integration/ + +Archgate integrates with [opencode](https://opencode.ai) to give AI agents a structured governance workflow. The agent reads your ADRs before writing code, validates after, and captures new patterns for the team -- the same workflow available in the [Claude Code plugin](/guides/claude-code-plugin/). + +## Setup + +Run `archgate init` with the `--editor opencode` flag to configure opencode integration in your project: + +```bash +archgate init --editor opencode +``` + +The opencode agent bundle is currently in beta. Run `archgate login` to sign up and authenticate. + +Unlike the Claude Code or Cursor integrations, the opencode agents are **not written to your project tree**. They are installed at the user scope instead — so they live on your machine, not in your repository, and are available across every project you open with opencode. + +opencode uses the XDG Base Directory convention on every platform (via the `xdg-basedir` package), so the install location resolves to `$XDG_CONFIG_HOME/opencode/agents/` when that variable is set, and falls back to `$HOME/.config/opencode/agents/` otherwise. That means Windows installs land under `C:\Users\\.config\opencode\agents\`, not under `%APPDATA%`: + +| Platform | Install location | +| ------------- | ---------------------------------------------- | +| Linux / macOS | `~/.config/opencode/agents/` | +| Windows | `C:\Users\\.config\opencode\agents\` | + +### Authenticated install + +The install step only runs when the `opencode` CLI is on your PATH. Archgate needs to confirm opencode is present before writing files into its user-scope config directory — otherwise the agents would sit in a location nothing reads. Install opencode from [opencode.ai](https://opencode.ai/docs/) first, then re-run `archgate init --editor opencode` or `archgate plugin install --editor opencode`. + +If you have logged in via `archgate login` **and** `opencode` is on your PATH, the init command downloads and installs the Archgate agent bundle for opencode. The bundle provides a pre-built primary agent and four subagents that give opencode's AI a full governance workflow. + +To explicitly install the agents: + +```bash +archgate login # one-time setup +archgate init --editor opencode --install-plugin +``` + +To install or reinstall on an already-initialized project: + +```bash +archgate plugin install --editor opencode +``` + +The install step downloads an authenticated tarball from the Archgate plugins service and extracts the five `archgate-*.md` agent files into the opencode user-scope directory. + +### Generated files (user scope) + +| File | Purpose | +| ----------------------------------------------- | ------------------------------------------------------------------------ | +| `/archgate-developer.md` | Primary agent (selectable with Tab) that runs the full ADR workflow | +| `/archgate-architect.md` | Subagent that validates code changes against all project ADRs | +| `/archgate-quality-manager.md` | Subagent that captures learnings and proposes new ADRs | +| `/archgate-adr-author.md` | Subagent that creates and edits ADRs following project conventions | +| `/archgate-cli-reference.md` | Internal reference subagent with the Archgate CLI command guide (hidden) | + +`.archgate/adrs/` and `.archgate/lint/` are still created in your project as usual — only the opencode-specific agent files live outside the project tree. + +## What the bundle provides + +The `archgate-` prefix avoids collision with any user-authored opencode agents in the same directory. Subagents are invoked via opencode's `@-mention` syntax. + +### Primary agent + +| Name | Purpose | +| -------------------- | --------------------------------------------------------------------------- | +| `archgate-developer` | General development agent that reads ADRs before coding and validates after | + +The `archgate-developer` agent orchestrates the subagents below automatically as part of its workflow. + +### Subagents + +| Name | Purpose | +| -------------------------- | ----------------------------------------------------------------------------- | +| `archgate-architect` | Validates code changes against all project ADRs for structural compliance | +| `archgate-quality-manager` | Reviews rule coverage and proposes new ADRs when patterns emerge | +| `archgate-adr-author` | Creates and edits ADRs following project conventions | +| `archgate-cli-reference` | Internal reference for AI agents with the complete Archgate CLI command guide | + +These are the same roles available in the Claude Code plugin, adapted for opencode's native primary/subagent model. + +## How it works in practice + +Select `archgate-developer` as your primary agent (use the Tab key in opencode) when starting a coding task. The agent follows a structured workflow for every change: + +1. **Read applicable ADRs** -- The agent runs `archgate review-context` to see which ADRs apply to the files being changed. It does not write code until it has read the applicable ADRs. + +2. **Write code following ADR constraints** -- The agent implements changes following the Do's and Don'ts from the applicable ADRs. + +3. **Run compliance checks** -- The agent runs `archgate check` to execute automated rules. Any violations are fixed before proceeding. + +4. **Architect review** -- The agent mentions `@archgate-architect` to validate structural ADR compliance beyond what automated rules catch. + +5. **Capture learnings** -- The agent mentions `@archgate-quality-manager` to review the work and identify patterns worth capturing as new ADRs or updates to existing ones. + +## ADR-driven refusal + +When `archgate-developer` encounters a task that would require violating an ADR, it refuses and explains which ADR would be violated. It then suggests how to achieve the same goal while staying compliant. + +For example, if a developer asks the agent to add `chalk` as a dependency in a project governed by a dependency policy ADR, the agent will: + +1. Refuse, citing the ADR and the approved dependency list +2. Suggest using the approved alternative instead +3. Offer to implement the task using the compliant approach + +This behavior is consistent regardless of how the developer phrases the request. ADRs are treated as mandatory constraints, not suggestions. + +## When to use each agent or subagent + +| Scenario | Agent / Subagent | +| -------------------------------------------- | ------------------------------ | +| Day-to-day coding tasks | `archgate-developer` (primary) | +| Reviewing a change for ADR compliance | `@archgate-architect` | +| Noticing a recurring pattern worth codifying | `@archgate-quality-manager` | +| Creating or editing an ADR | `@archgate-adr-author` | + +The `archgate-developer` agent orchestrates the subagents automatically -- it mentions `@archgate-architect` and `@archgate-quality-manager` as part of its workflow. Most of the time, you only need to select `archgate-developer` and let it run. + +## User-scope vs project-scope + +The opencode bundle lives in your user-scope opencode directory rather than in `.opencode/` inside your project. Consequences: + +- **One install per machine.** `archgate plugin install --editor opencode` installs the bundle globally. Every project you open with opencode sees the same `archgate-*` agents. +- **Your repo stays clean.** No `.opencode/` folder is ever created by `archgate init`. Team members who want the agents run their own `archgate plugin install --editor opencode`. +- **Upgrades are global.** Re-running `archgate plugin install --editor opencode` overwrites the existing files with the latest bundle. + +## Tips for effective usage + +- **Select `archgate-developer` at the start of coding sessions.** It orchestrates the full read-validate-capture workflow automatically. +- **Use `@archgate-architect` for reviews.** It validates structural compliance beyond what automated rules catch. +- **Use `@archgate-quality-manager` after resolving tricky issues.** It captures learnings so the same mistakes are not repeated. +- **Keep ADR rules files up to date.** The agent enforces what the rules check for -- if a rule is missing, the violation will not be caught. +- **Re-run `archgate plugin install --editor opencode` to upgrade.** The service returns the latest agent bundle on every authenticated download. + +--- + ## Guides: Pre-commit Hooks Source: https://cli.archgate.dev/guides/pre-commit-hooks/ @@ -3311,10 +3447,10 @@ Creates the `.archgate/` directory with an example ADR, companion rules file, an ## Options -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------------------------- | -| `--editor ` | `claude` | Editor integration to configure (`claude`, `cursor`, `vscode`, `copilot`) | -| `--install-plugin` | auto | Install the Archgate editor plugin (requires prior `archgate login`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------------------------- | +| `--editor ` | `claude` | Editor integration to configure (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | +| `--install-plugin` | auto | Install the Archgate editor plugin (requires prior `archgate login`) | When `--install-plugin` is passed, the CLI installs the Archgate plugin for the selected editor. If the flag is omitted, the CLI auto-detects: it installs the plugin when valid credentials exist (from a previous `archgate login`) and skips otherwise. @@ -3324,6 +3460,8 @@ When `--install-plugin` is passed, the CLI installs the Archgate plugin for the **Cursor:** If the `cursor` CLI is on your PATH, the VS Code extension is installed automatically via `cursor --install-extension`. The team marketplace URL is printed for manual plugin discovery. +**opencode:** Requires the `opencode` CLI to be on your PATH — if it's not, the install is skipped and a message prompts you to install opencode first. When present, the CLI downloads an authenticated tarball of agent files from the Archgate plugins service and extracts it into the user-scope opencode agents directory (`$XDG_CONFIG_HOME/opencode/agents/`, falling back to `$HOME/.config/opencode/agents/` on every platform including Windows — opencode uses XDG paths via `xdg-basedir` and does not read `%APPDATA%`). No files are written to the project tree. See the [opencode integration guide](/guides/opencode-integration/) for details. + ## Output ``` @@ -3496,9 +3634,9 @@ Print the plugin repository URL for manual tool configuration. archgate plugin url [options] ``` -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------- | -| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------- | +| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | The URL can be used to manually configure editor tools. Credentials are provided automatically by your git credential manager (stored during `archgate login`). For example, to add the Archgate marketplace in Claude Code: @@ -3521,9 +3659,9 @@ Install the Archgate plugin for the specified editor on an already-initialized p archgate plugin install [options] ``` -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------- | -| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------- | +| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | Installation behavior varies by editor: @@ -3531,6 +3669,7 @@ Installation behavior varies by editor: - **Copilot CLI:** Auto-installs via `copilot` CLI if available; prints manual commands otherwise. - **Cursor:** Installs the VS Code extension via `cursor` CLI if available and prints the team marketplace URL; prints manual instructions otherwise. - **VS Code:** Adds the marketplace URL to VS Code user settings and installs the VS Code extension (`.vsix`) via `code` CLI if available; prints manual instructions otherwise. +- **opencode:** Requires the `opencode` CLI to be on PATH — skips the install with a clear message otherwise. When present, downloads an authenticated tarball of agent files and extracts it into the user-scope opencode agents directory. `archgate plugin url --editor opencode` prints "N/A" — opencode has no marketplace URL. See the [opencode integration guide](/guides/opencode-integration/) for details. ## Examples @@ -3552,6 +3691,12 @@ Install the plugin for Cursor: archgate plugin install --editor cursor ``` +Install the agent bundle for opencode: + +```bash +archgate plugin install --editor opencode +``` + --- ## Reference: archgate review-context diff --git a/docs/src/content/docs/guides/opencode-integration.mdx b/docs/src/content/docs/guides/opencode-integration.mdx new file mode 100644 index 00000000..2cc5f231 --- /dev/null +++ b/docs/src/content/docs/guides/opencode-integration.mdx @@ -0,0 +1,138 @@ +--- +title: opencode Integration +description: Integrate Archgate with opencode for AI-assisted development with architecture governance. Configure agents and subagents for ADR compliance. +--- + +Archgate integrates with [opencode](https://opencode.ai) to give AI agents a structured governance workflow. The agent reads your ADRs before writing code, validates after, and captures new patterns for the team -- the same workflow available in the [Claude Code plugin](/guides/claude-code-plugin/). + +## Setup + +Run `archgate init` with the `--editor opencode` flag to configure opencode integration in your project: + +```bash +archgate init --editor opencode +``` + +:::note[Beta access required] +The opencode agent bundle is currently in beta. Run `archgate login` to sign up and authenticate. +::: + +Unlike the Claude Code or Cursor integrations, the opencode agents are **not written to your project tree**. They are installed at the user scope instead — so they live on your machine, not in your repository, and are available across every project you open with opencode. + +opencode uses the XDG Base Directory convention on every platform (via the `xdg-basedir` package), so the install location resolves to `$XDG_CONFIG_HOME/opencode/agents/` when that variable is set, and falls back to `$HOME/.config/opencode/agents/` otherwise. That means Windows installs land under `C:\Users\\.config\opencode\agents\`, not under `%APPDATA%`: + +| Platform | Install location | +| ------------- | ---------------------------------------------- | +| Linux / macOS | `~/.config/opencode/agents/` | +| Windows | `C:\Users\\.config\opencode\agents\` | + +### Authenticated install + +:::caution[opencode must be installed first] +The install step only runs when the `opencode` CLI is on your PATH. Archgate needs to confirm opencode is present before writing files into its user-scope config directory — otherwise the agents would sit in a location nothing reads. Install opencode from [opencode.ai](https://opencode.ai/docs/) first, then re-run `archgate init --editor opencode` or `archgate plugin install --editor opencode`. +::: + +If you have logged in via `archgate login` **and** `opencode` is on your PATH, the init command downloads and installs the Archgate agent bundle for opencode. The bundle provides a pre-built primary agent and four subagents that give opencode's AI a full governance workflow. + +To explicitly install the agents: + +```bash +archgate login # one-time setup +archgate init --editor opencode --install-plugin +``` + +To install or reinstall on an already-initialized project: + +```bash +archgate plugin install --editor opencode +``` + +The install step downloads an authenticated tarball from the Archgate plugins service and extracts the five `archgate-*.md` agent files into the opencode user-scope directory. + +### Generated files (user scope) + +| File | Purpose | +| ----------------------------------------------- | ------------------------------------------------------------------------ | +| `/archgate-developer.md` | Primary agent (selectable with Tab) that runs the full ADR workflow | +| `/archgate-architect.md` | Subagent that validates code changes against all project ADRs | +| `/archgate-quality-manager.md` | Subagent that captures learnings and proposes new ADRs | +| `/archgate-adr-author.md` | Subagent that creates and edits ADRs following project conventions | +| `/archgate-cli-reference.md` | Internal reference subagent with the Archgate CLI command guide (hidden) | + +`.archgate/adrs/` and `.archgate/lint/` are still created in your project as usual — only the opencode-specific agent files live outside the project tree. + +## What the bundle provides + +The `archgate-` prefix avoids collision with any user-authored opencode agents in the same directory. Subagents are invoked via opencode's `@-mention` syntax. + +### Primary agent + +| Name | Purpose | +| -------------------- | --------------------------------------------------------------------------- | +| `archgate-developer` | General development agent that reads ADRs before coding and validates after | + +The `archgate-developer` agent orchestrates the subagents below automatically as part of its workflow. + +### Subagents + +| Name | Purpose | +| -------------------------- | ----------------------------------------------------------------------------- | +| `archgate-architect` | Validates code changes against all project ADRs for structural compliance | +| `archgate-quality-manager` | Reviews rule coverage and proposes new ADRs when patterns emerge | +| `archgate-adr-author` | Creates and edits ADRs following project conventions | +| `archgate-cli-reference` | Internal reference for AI agents with the complete Archgate CLI command guide | + +These are the same roles available in the Claude Code plugin, adapted for opencode's native primary/subagent model. + +## How it works in practice + +Select `archgate-developer` as your primary agent (use the Tab key in opencode) when starting a coding task. The agent follows a structured workflow for every change: + +1. **Read applicable ADRs** -- The agent runs `archgate review-context` to see which ADRs apply to the files being changed. It does not write code until it has read the applicable ADRs. + +2. **Write code following ADR constraints** -- The agent implements changes following the Do's and Don'ts from the applicable ADRs. + +3. **Run compliance checks** -- The agent runs `archgate check` to execute automated rules. Any violations are fixed before proceeding. + +4. **Architect review** -- The agent mentions `@archgate-architect` to validate structural ADR compliance beyond what automated rules catch. + +5. **Capture learnings** -- The agent mentions `@archgate-quality-manager` to review the work and identify patterns worth capturing as new ADRs or updates to existing ones. + +## ADR-driven refusal + +When `archgate-developer` encounters a task that would require violating an ADR, it refuses and explains which ADR would be violated. It then suggests how to achieve the same goal while staying compliant. + +For example, if a developer asks the agent to add `chalk` as a dependency in a project governed by a dependency policy ADR, the agent will: + +1. Refuse, citing the ADR and the approved dependency list +2. Suggest using the approved alternative instead +3. Offer to implement the task using the compliant approach + +This behavior is consistent regardless of how the developer phrases the request. ADRs are treated as mandatory constraints, not suggestions. + +## When to use each agent or subagent + +| Scenario | Agent / Subagent | +| -------------------------------------------- | ------------------------------ | +| Day-to-day coding tasks | `archgate-developer` (primary) | +| Reviewing a change for ADR compliance | `@archgate-architect` | +| Noticing a recurring pattern worth codifying | `@archgate-quality-manager` | +| Creating or editing an ADR | `@archgate-adr-author` | + +The `archgate-developer` agent orchestrates the subagents automatically -- it mentions `@archgate-architect` and `@archgate-quality-manager` as part of its workflow. Most of the time, you only need to select `archgate-developer` and let it run. + +## User-scope vs project-scope + +The opencode bundle lives in your user-scope opencode directory rather than in `.opencode/` inside your project. Consequences: + +- **One install per machine.** `archgate plugin install --editor opencode` installs the bundle globally. Every project you open with opencode sees the same `archgate-*` agents. +- **Your repo stays clean.** No `.opencode/` folder is ever created by `archgate init`. Team members who want the agents run their own `archgate plugin install --editor opencode`. +- **Upgrades are global.** Re-running `archgate plugin install --editor opencode` overwrites the existing files with the latest bundle. + +## Tips for effective usage + +- **Select `archgate-developer` at the start of coding sessions.** It orchestrates the full read-validate-capture workflow automatically. +- **Use `@archgate-architect` for reviews.** It validates structural compliance beyond what automated rules catch. +- **Use `@archgate-quality-manager` after resolving tricky issues.** It captures learnings so the same mistakes are not repeated. +- **Keep ADR rules files up to date.** The agent enforces what the rules check for -- if a rule is missing, the violation will not be caught. +- **Re-run `archgate plugin install --editor opencode` to upgrade.** The service returns the latest agent bundle on every authenticated download. diff --git a/docs/src/content/docs/pt-br/guides/opencode-integration.mdx b/docs/src/content/docs/pt-br/guides/opencode-integration.mdx new file mode 100644 index 00000000..7897f9d0 --- /dev/null +++ b/docs/src/content/docs/pt-br/guides/opencode-integration.mdx @@ -0,0 +1,138 @@ +--- +title: Integração com opencode +description: Integre o Archgate com o opencode para desenvolvimento assistido por IA com governança arquitetural. Configure agentes e subagentes para conformidade ADR. +--- + +O Archgate se integra com o [opencode](https://opencode.ai) para oferecer aos agentes de IA um fluxo de governança estruturado. O agente lê seus ADRs antes de escrever código, valida depois e captura novos padrões para a equipe -- o mesmo fluxo disponível no [plugin para Claude Code](/guides/claude-code-plugin/). + +## Configuração + +Execute `archgate init` com a flag `--editor opencode` para configurar a integração com o opencode no seu projeto: + +```bash +archgate init --editor opencode +``` + +:::note[Acesso beta necessário] +O bundle de agentes do opencode está atualmente em beta. Execute `archgate login` para se cadastrar e autenticar. +::: + +Diferente das integrações com Claude Code ou Cursor, os agentes do opencode **não são gravados na árvore do seu projeto**. Em vez disso, são instalados no escopo do usuário -- portanto vivem na sua máquina, não no repositório, e ficam disponíveis em todos os projetos que você abrir com o opencode. + +O opencode usa a convenção XDG Base Directory em todas as plataformas (via o pacote `xdg-basedir`), então o local de instalação é `$XDG_CONFIG_HOME/opencode/agents/` quando essa variável está definida e `$HOME/.config/opencode/agents/` caso contrário. Isso significa que instalações no Windows ficam em `C:\Users\\.config\opencode\agents\`, não em `%APPDATA%`: + +| Plataforma | Local de instalação | +| ------------- | --------------------------------------------- | +| Linux / macOS | `~/.config/opencode/agents/` | +| Windows | `C:\Users\\.config\opencode\agents\` | + +### Instalação autenticada + +:::caution[O opencode precisa estar instalado primeiro] +A instalação só é executada quando a CLI `opencode` está no seu PATH. O Archgate precisa confirmar que o opencode está presente antes de gravar arquivos no diretório de configuração do escopo do usuário -- caso contrário, os agentes ficariam em um local que ninguém lê. Instale o opencode em [opencode.ai](https://opencode.ai/docs/) primeiro, depois re-execute `archgate init --editor opencode` ou `archgate plugin install --editor opencode`. +::: + +Se você fez login via `archgate login` **e** o `opencode` está no seu PATH, o comando init também baixa e instala o bundle de agentes Archgate para o opencode. O bundle fornece um agente primário pré-configurado e quatro subagentes que dão à IA do opencode um fluxo de governança completo. + +Para instalar os agentes explicitamente: + +```bash +archgate login # configuração única +archgate init --editor opencode --install-plugin +``` + +Para instalar ou reinstalar em um projeto já inicializado: + +```bash +archgate plugin install --editor opencode +``` + +O passo de instalação baixa um tarball autenticado do serviço de plugins do Archgate e extrai os cinco arquivos de agente `archgate-*.md` no diretório de escopo do usuário do opencode. + +### Arquivos gerados (escopo do usuário) + +| Arquivo | Propósito | +| ----------------------------------------------- | ---------------------------------------------------------------------------------- | +| `/archgate-developer.md` | Agente primário (selecionável com Tab) que executa o fluxo ADR completo | +| `/archgate-architect.md` | Subagente que valida mudanças de código contra todos os ADRs do projeto | +| `/archgate-quality-manager.md` | Subagente que captura aprendizados e propõe novos ADRs | +| `/archgate-adr-author.md` | Subagente que cria e edita ADRs seguindo as convenções do projeto | +| `/archgate-cli-reference.md` | Subagente de referência interna com o guia de comandos da CLI do Archgate (oculto) | + +`.archgate/adrs/` e `.archgate/lint/` continuam sendo criados no seu projeto normalmente -- apenas os arquivos de agente específicos do opencode ficam fora da árvore do projeto. + +## O que o bundle oferece + +O prefixo `archgate-` evita colisão com agentes opencode criados pelo usuário no mesmo diretório. Os subagentes são invocados através da sintaxe de `@-menção` do opencode. + +### Agente primário + +| Nome | Propósito | +| -------------------- | -------------------------------------------------------------------------- | +| `archgate-developer` | Agente de desenvolvimento geral que lê ADRs antes de codar e valida depois | + +O agente `archgate-developer` orquestra os subagentes abaixo automaticamente como parte do seu fluxo. + +### Subagentes + +| Nome | Propósito | +| -------------------------- | -------------------------------------------------------------------------------------- | +| `archgate-architect` | Valida mudanças de código contra todos os ADRs do projeto para conformidade estrutural | +| `archgate-quality-manager` | Revisa a cobertura de regras e propõe novos ADRs quando padrões emergem | +| `archgate-adr-author` | Cria e edita ADRs seguindo as convenções do projeto | +| `archgate-cli-reference` | Referência interna para agentes de IA com o guia completo de comandos da CLI Archgate | + +São os mesmos papéis disponíveis no plugin para Claude Code, adaptados para o modelo nativo primário/subagente do opencode. + +## Como funciona na prática + +Selecione `archgate-developer` como seu agente primário (use a tecla Tab no opencode) ao iniciar uma tarefa de codificação. O agente segue um fluxo estruturado para cada mudança: + +1. **Ler os ADRs aplicáveis** -- O agente executa `archgate review-context` para ver quais ADRs se aplicam aos arquivos sendo alterados. Ele não escreve código antes de ler os ADRs aplicáveis. + +2. **Escrever código seguindo as restrições dos ADRs** -- O agente implementa as mudanças seguindo os Do's e Don'ts dos ADRs aplicáveis. + +3. **Executar verificações de conformidade** -- O agente executa `archgate check` para executar regras automáticas. Quaisquer violações são corrigidas antes de prosseguir. + +4. **Revisão do architect** -- O agente menciona `@archgate-architect` para validar a conformidade estrutural dos ADRs além do que as regras automáticas detectam. + +5. **Capturar aprendizados** -- O agente menciona `@archgate-quality-manager` para revisar o trabalho e identificar padrões que vale a pena capturar como novos ADRs ou atualizações aos existentes. + +## Recusa orientada por ADR + +Quando `archgate-developer` encontra uma tarefa que exigiria violar um ADR, ele recusa e explica qual ADR seria violado. Em seguida, sugere como alcançar o mesmo objetivo permanecendo em conformidade. + +Por exemplo, se um desenvolvedor pedir ao agente para adicionar `chalk` como dependência em um projeto governado por um ADR de política de dependências, o agente irá: + +1. Recusar, citando o ADR e a lista aprovada de dependências +2. Sugerir usar a alternativa aprovada +3. Oferecer-se para implementar a tarefa usando a abordagem conforme + +Esse comportamento é consistente independentemente de como o desenvolvedor formula o pedido. ADRs são tratados como restrições obrigatórias, não sugestões. + +## Quando usar cada agente ou subagente + +| Cenário | Agente / Subagente | +| --------------------------------------------- | ------------------------------- | +| Tarefas diárias de codificação | `archgate-developer` (primário) | +| Revisar uma mudança para conformidade com ADR | `@archgate-architect` | +| Notar um padrão recorrente que vale codificar | `@archgate-quality-manager` | +| Criar ou editar um ADR | `@archgate-adr-author` | + +O agente `archgate-developer` orquestra os subagentes automaticamente -- ele menciona `@archgate-architect` e `@archgate-quality-manager` como parte do seu fluxo. Na maioria das vezes, você só precisa selecionar `archgate-developer` e deixá-lo executar. + +## Escopo do usuário vs. escopo do projeto + +O bundle do opencode vive no seu diretório opencode de escopo do usuário em vez de em `.opencode/` dentro do projeto. Consequências: + +- **Uma instalação por máquina.** `archgate plugin install --editor opencode` instala o bundle globalmente. Todo projeto que você abrir com o opencode enxerga os mesmos agentes `archgate-*`. +- **Seu repositório permanece limpo.** Nenhuma pasta `.opencode/` é criada por `archgate init`. Membros da equipe que queiram os agentes executam seu próprio `archgate plugin install --editor opencode`. +- **Upgrades são globais.** Re-executar `archgate plugin install --editor opencode` sobrescreve os arquivos existentes com o bundle mais recente. + +## Dicas para uso efetivo + +- **Selecione `archgate-developer` no início das sessões de codificação.** Ele orquestra o fluxo completo de leitura-validação-captura automaticamente. +- **Use `@archgate-architect` para revisões.** Ele valida a conformidade estrutural além do que as regras automáticas detectam. +- **Use `@archgate-quality-manager` depois de resolver problemas complicados.** Ele captura aprendizados para que os mesmos erros não sejam repetidos. +- **Mantenha os arquivos de regras dos ADRs atualizados.** O agente impõe o que as regras verificam -- se uma regra está faltando, a violação não será detectada. +- **Re-execute `archgate plugin install --editor opencode` para atualizar.** O serviço retorna o bundle de agentes mais recente em cada download autenticado. diff --git a/docs/src/content/docs/pt-br/reference/cli/init.mdx b/docs/src/content/docs/pt-br/reference/cli/init.mdx index 6b4bf112..d20b562d 100644 --- a/docs/src/content/docs/pt-br/reference/cli/init.mdx +++ b/docs/src/content/docs/pt-br/reference/cli/init.mdx @@ -13,10 +13,10 @@ Cria o diretório `.archgate/` com um ADR de exemplo, arquivo de regras compleme ## Opções -| Opção | Padrão | Descrição | -| ------------------- | -------- | --------------------------------------------------------------------------- | -| `--editor ` | `claude` | Integração de editor a configurar (`claude`, `cursor`, `vscode`, `copilot`) | -| `--install-plugin` | auto | Instalar o plugin de editor do Archgate (requer `archgate login` prévio) | +| Opção | Padrão | Descrição | +| ------------------- | -------- | --------------------------------------------------------------------------------------- | +| `--editor ` | `claude` | Integração de editor a configurar (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | +| `--install-plugin` | auto | Instalar o plugin de editor do Archgate (requer `archgate login` prévio) | Quando `--install-plugin` é passado, a CLI instala o plugin do Archgate para o editor selecionado. Se a flag for omitida, a CLI faz detecção automática: instala o plugin quando existem credenciais válidas (de um `archgate login` anterior) e pula caso contrário. @@ -26,6 +26,8 @@ Quando `--install-plugin` é passado, a CLI instala o plugin do Archgate para o **Cursor:** Se a CLI `cursor` estiver no seu PATH, a extensão VS Code é instalada automaticamente via `cursor --install-extension`. A URL do team marketplace é impressa para descoberta manual do plugin. +**opencode:** Requer que a CLI `opencode` esteja no seu PATH -- se não estiver, a instalação é pulada e uma mensagem pede que você instale o opencode primeiro. Quando presente, a CLI baixa um tarball autenticado de arquivos de agente do serviço de plugins do Archgate e o extrai no diretório de agentes opencode do escopo do usuário (`$XDG_CONFIG_HOME/opencode/agents/`, com fallback para `$HOME/.config/opencode/agents/` em qualquer plataforma, inclusive Windows -- o opencode usa paths XDG via `xdg-basedir` e não lê `%APPDATA%`). Nenhum arquivo é gravado na árvore do projeto. Veja o [guia de integração com opencode](/guides/opencode-integration/) para detalhes. + ## Saída ``` diff --git a/docs/src/content/docs/pt-br/reference/cli/plugin.mdx b/docs/src/content/docs/pt-br/reference/cli/plugin.mdx index 2cdcda3b..773d054c 100644 --- a/docs/src/content/docs/pt-br/reference/cli/plugin.mdx +++ b/docs/src/content/docs/pt-br/reference/cli/plugin.mdx @@ -21,9 +21,9 @@ Exibe a URL do repositório de plugins para configuração manual de ferramentas archgate plugin url [options] ``` -| Opção | Padrão | Descrição | -| ------------------- | -------- | ----------------------------------------------------- | -| `--editor ` | `claude` | Editor alvo (`claude`, `cursor`, `vscode`, `copilot`) | +| Opção | Padrão | Descrição | +| ------------------- | -------- | ----------------------------------------------------------------- | +| `--editor ` | `claude` | Editor alvo (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | A URL pode ser usada para configurar manualmente as ferramentas do editor. As credenciais são fornecidas automaticamente pelo seu gerenciador de credenciais git (armazenadas durante `archgate login`). Por exemplo, para adicionar o marketplace do Archgate no Claude Code: @@ -46,9 +46,9 @@ Instala o plugin do Archgate para o editor especificado em um projeto já inicia archgate plugin install [options] ``` -| Opção | Padrão | Descrição | -| ------------------- | -------- | ----------------------------------------------------- | -| `--editor ` | `claude` | Editor alvo (`claude`, `cursor`, `vscode`, `copilot`) | +| Opção | Padrão | Descrição | +| ------------------- | -------- | ----------------------------------------------------------------- | +| `--editor ` | `claude` | Editor alvo (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | O comportamento de instalação varia por editor: @@ -56,6 +56,7 @@ O comportamento de instalação varia por editor: - **Copilot CLI:** Instala automaticamente via CLI `copilot` se disponível; exibe comandos manuais caso contrário. - **Cursor:** Instala a extensão VS Code via CLI `cursor` se disponível e exibe a URL do team marketplace; exibe instruções manuais caso contrário. - **VS Code:** Adiciona a URL do marketplace nas configurações de usuário do VS Code e instala a extensão VS Code (`.vsix`) via CLI `code` se disponível; exibe instruções manuais caso contrário. +- **opencode:** Requer que a CLI `opencode` esteja no PATH -- pula a instalação com uma mensagem clara caso contrário. Quando presente, baixa um tarball autenticado de arquivos de agente e o extrai no diretório de agentes opencode do escopo do usuário. `archgate plugin url --editor opencode` exibe "N/A" -- opencode não tem URL de marketplace. Veja o [guia de integração com opencode](/guides/opencode-integration/) para detalhes. ## Exemplos @@ -76,3 +77,9 @@ Instalar o plugin para o Cursor: ```bash archgate plugin install --editor cursor ``` + +Instalar o bundle de agentes para o opencode: + +```bash +archgate plugin install --editor opencode +``` diff --git a/docs/src/content/docs/reference/cli/init.mdx b/docs/src/content/docs/reference/cli/init.mdx index f8f7b0bd..46a4de4c 100644 --- a/docs/src/content/docs/reference/cli/init.mdx +++ b/docs/src/content/docs/reference/cli/init.mdx @@ -13,10 +13,10 @@ Creates the `.archgate/` directory with an example ADR, companion rules file, an ## Options -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------------------------- | -| `--editor ` | `claude` | Editor integration to configure (`claude`, `cursor`, `vscode`, `copilot`) | -| `--install-plugin` | auto | Install the Archgate editor plugin (requires prior `archgate login`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------------------------- | +| `--editor ` | `claude` | Editor integration to configure (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | +| `--install-plugin` | auto | Install the Archgate editor plugin (requires prior `archgate login`) | When `--install-plugin` is passed, the CLI installs the Archgate plugin for the selected editor. If the flag is omitted, the CLI auto-detects: it installs the plugin when valid credentials exist (from a previous `archgate login`) and skips otherwise. @@ -26,6 +26,8 @@ When `--install-plugin` is passed, the CLI installs the Archgate plugin for the **Cursor:** If the `cursor` CLI is on your PATH, the VS Code extension is installed automatically via `cursor --install-extension`. The team marketplace URL is printed for manual plugin discovery. +**opencode:** Requires the `opencode` CLI to be on your PATH — if it's not, the install is skipped and a message prompts you to install opencode first. When present, the CLI downloads an authenticated tarball of agent files from the Archgate plugins service and extracts it into the user-scope opencode agents directory (`$XDG_CONFIG_HOME/opencode/agents/`, falling back to `$HOME/.config/opencode/agents/` on every platform including Windows — opencode uses XDG paths via `xdg-basedir` and does not read `%APPDATA%`). No files are written to the project tree. See the [opencode integration guide](/guides/opencode-integration/) for details. + ## Output ``` diff --git a/docs/src/content/docs/reference/cli/plugin.mdx b/docs/src/content/docs/reference/cli/plugin.mdx index ad8f5297..916548e8 100644 --- a/docs/src/content/docs/reference/cli/plugin.mdx +++ b/docs/src/content/docs/reference/cli/plugin.mdx @@ -21,9 +21,9 @@ Print the plugin repository URL for manual tool configuration. archgate plugin url [options] ``` -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------- | -| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------- | +| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | The URL can be used to manually configure editor tools. Credentials are provided automatically by your git credential manager (stored during `archgate login`). For example, to add the Archgate marketplace in Claude Code: @@ -46,9 +46,9 @@ Install the Archgate plugin for the specified editor on an already-initialized p archgate plugin install [options] ``` -| Option | Default | Description | -| ------------------- | -------- | ------------------------------------------------------- | -| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`) | +| Option | Default | Description | +| ------------------- | -------- | ------------------------------------------------------------------- | +| `--editor ` | `claude` | Target editor (`claude`, `cursor`, `vscode`, `copilot`, `opencode`) | Installation behavior varies by editor: @@ -56,6 +56,7 @@ Installation behavior varies by editor: - **Copilot CLI:** Auto-installs via `copilot` CLI if available; prints manual commands otherwise. - **Cursor:** Installs the VS Code extension via `cursor` CLI if available and prints the team marketplace URL; prints manual instructions otherwise. - **VS Code:** Adds the marketplace URL to VS Code user settings and installs the VS Code extension (`.vsix`) via `code` CLI if available; prints manual instructions otherwise. +- **opencode:** Requires the `opencode` CLI to be on PATH — skips the install with a clear message otherwise. When present, downloads an authenticated tarball of agent files and extracts it into the user-scope opencode agents directory. `archgate plugin url --editor opencode` prints "N/A" — opencode has no marketplace URL. See the [opencode integration guide](/guides/opencode-integration/) for details. ## Examples @@ -76,3 +77,9 @@ Install the plugin for Cursor: ```bash archgate plugin install --editor cursor ``` + +Install the agent bundle for opencode: + +```bash +archgate plugin install --editor opencode +``` diff --git a/src/commands/init.ts b/src/commands/init.ts index d518c90d..07a435f6 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -26,6 +26,10 @@ const EDITOR_DIRS: Record = { cursor: ".cursor/", vscode: ".vscode/", copilot: ".github/copilot/", + // Opencode agents install to a user-scope directory, not the project tree. + // Shown as a shorthand in the init summary; the resolved absolute path is + // printed via `result.plugin.detail` when the install succeeds. + opencode: "(user-scope)", }; /** Map init editor flags to signup editor identifiers. */ @@ -34,12 +38,13 @@ const SIGNUP_EDITORS: Record = { cursor: "cursor", vscode: "vscode", copilot: "copilot-cli", + opencode: "opencode", }; const editorOption = new Option( "--editor ", "editor integration (omit to auto-detect and select)" -).choices(["claude", "cursor", "vscode", "copilot"] as const); +).choices(["claude", "cursor", "vscode", "copilot", "opencode"] as const); export function registerInitCommand(program: Command) { program @@ -197,6 +202,31 @@ function printManualInstructions(editor: EditorTarget, detail?: string): void { logWarn("Copilot CLI not found. To install the plugin manually, run:"); console.log(` ${styleText("bold", "copilot plugin install")} ${detail}`); break; + case "opencode": + // `cli-not-found` is the sentinel set by `tryInstallPlugin` in + // init-project.ts when the `opencode` binary is not on PATH. All other + // values are error messages from a failed download/extract. + if (detail === "cli-not-found") { + logWarn( + "opencode CLI not found on PATH — skipping agent install.", + "Install opencode from https://opencode.ai/docs/, then run:" + ); + console.log( + ` ${styleText("bold", "archgate plugin install --editor opencode")}` + ); + } else { + logWarn( + "Failed to install opencode agents.", + detail ?? "Check your credentials and retry." + ); + console.log( + ` Retry with: ${styleText("bold", "archgate plugin install --editor opencode")}` + ); + console.log( + ` If the token has expired: ${styleText("bold", "archgate login refresh")}` + ); + } + break; default: // cursor/vscode auto-install — should not reach here break; diff --git a/src/commands/plugin/install.ts b/src/commands/plugin/install.ts index 43dc3bdc..068be4fb 100644 --- a/src/commands/plugin/install.ts +++ b/src/commands/plugin/install.ts @@ -12,7 +12,7 @@ import { exitWith } from "../../helpers/exit"; import { EDITOR_LABELS } from "../../helpers/init-project"; import type { EditorTarget } from "../../helpers/init-project"; import { logError, logInfo, logWarn } from "../../helpers/log"; -import { findProjectRoot } from "../../helpers/paths"; +import { findProjectRoot, opencodeAgentsDir } from "../../helpers/paths"; import { buildCursorMarketplaceUrl, buildMarketplaceUrl, @@ -20,10 +20,12 @@ import { installClaudePlugin, installCopilotPlugin, installCursorPlugin, + installOpencodePlugin, installVscodeExtension, isClaudeCliAvailable, isCopilotCliAvailable, isCursorCliAvailable, + isOpencodeCliAvailable, isVscodeCliAvailable, } from "../../helpers/plugin-install"; import { configureVscodeSettings } from "../../helpers/vscode-settings"; @@ -31,7 +33,7 @@ import { configureVscodeSettings } from "../../helpers/vscode-settings"; const editorOption = new Option( "--editor ", "target editor (omit to auto-detect and select)" -).choices(["claude", "cursor", "vscode", "copilot"] as const); +).choices(["claude", "cursor", "vscode", "copilot", "opencode"] as const); async function installForEditor( editor: EditorTarget, @@ -84,6 +86,27 @@ async function installForEditor( } break; } + case "opencode": { + // Writing agent files to `~/.config/opencode/agents/` is only useful + // if opencode is actually installed. Skip the install and surface a + // clear message otherwise, matching every other editor's guard. + if (!(await isOpencodeCliAvailable())) { + logWarn( + "opencode CLI not found on PATH — skipping agent install.", + "Install opencode from https://opencode.ai/docs/, then re-run:" + ); + console.log( + ` ${styleText("bold", "archgate plugin install --editor opencode")}` + ); + break; + } + await installOpencodePlugin(token); + logInfo( + `Archgate agents installed for ${label}.`, + `Target directory: ${opencodeAgentsDir()}` + ); + break; + } case "vscode": { const url = buildVscodeMarketplaceUrl(); await configureVscodeSettings(findProjectRoot() ?? process.cwd(), url); @@ -191,6 +214,16 @@ export function registerPluginInstallCommand(plugin: Command) { console.log(` rm archgate.vsix`); break; } + case "opencode": { + logInfo( + "Retry the install, or refresh your credentials if they have expired:" + ); + console.log(` ${styleText("bold", "archgate login refresh")}`); + console.log( + ` ${styleText("bold", "archgate plugin install --editor opencode")}` + ); + break; + } } // oxlint-disable-next-line no-await-in-loop -- exit immediately on first editor failure diff --git a/src/commands/plugin/url.ts b/src/commands/plugin/url.ts index 00328eec..8af85e92 100644 --- a/src/commands/plugin/url.ts +++ b/src/commands/plugin/url.ts @@ -17,7 +17,7 @@ import { const editorOption = new Option( "--editor ", "target editor (omit to auto-detect and select)" -).choices(["claude", "cursor", "vscode", "copilot"] as const); +).choices(["claude", "cursor", "vscode", "copilot", "opencode"] as const); export function registerPluginUrlCommand(plugin: Command) { plugin @@ -36,6 +36,16 @@ export function registerPluginUrlCommand(plugin: Command) { editor = "claude"; } + if (editor === "opencode") { + // Opencode has no marketplace URL — agents are installed via the + // authenticated plugins service. Point the user at the command + // that performs the install instead of printing an empty line. + console.log( + "N/A — run `archgate plugin install --editor opencode` (authenticated install)." + ); + return; + } + const url = editor === "cursor" ? buildCursorMarketplaceUrl() diff --git a/src/helpers/editor-detect.ts b/src/helpers/editor-detect.ts index 3b92023a..7b58a695 100644 --- a/src/helpers/editor-detect.ts +++ b/src/helpers/editor-detect.ts @@ -14,6 +14,7 @@ import { resolveCommand } from "./platform"; import { isClaudeCliAvailable, isCopilotCliAvailable, + isOpencodeCliAvailable, isVscodeCliAvailable, } from "./plugin-install"; @@ -30,14 +31,15 @@ export interface DetectedEditor { */ export async function detectEditors(): Promise { logDebug("Detecting available editor CLIs"); - const [claude, cursor, vscode, copilot] = await Promise.all([ + const [claude, cursor, vscode, copilot, opencode] = await Promise.all([ isClaudeCliAvailable(), resolveCommand("cursor").then((r) => r !== null), isVscodeCliAvailable(), isCopilotCliAvailable(), + isOpencodeCliAvailable(), ]); - logDebug("Editor detection:", { claude, cursor, vscode, copilot }); + logDebug("Editor detection:", { claude, cursor, vscode, copilot, opencode }); return [ { id: "claude" as const, label: EDITOR_LABELS.claude, available: claude }, { id: "cursor" as const, label: EDITOR_LABELS.cursor, available: cursor }, @@ -47,6 +49,11 @@ export async function detectEditors(): Promise { label: EDITOR_LABELS.copilot, available: copilot, }, + { + id: "opencode" as const, + label: EDITOR_LABELS.opencode, + available: opencode, + }, ]; } diff --git a/src/helpers/init-project.ts b/src/helpers/init-project.ts index ed967b50..17036f8e 100644 --- a/src/helpers/init-project.ts +++ b/src/helpers/init-project.ts @@ -6,17 +6,27 @@ import { configureClaudeSettings } from "./claude-settings"; import { configureCopilotSettings } from "./copilot-settings"; import { configureCursorSettings } from "./cursor-settings"; import { logDebug } from "./log"; -import { createPathIfNotExists, projectPaths } from "./paths"; +import { + createPathIfNotExists, + opencodeAgentsDir, + projectPaths, +} from "./paths"; import { writeRulesShim } from "./rules-shim"; import { configureVscodeSettings } from "./vscode-settings"; -export type EditorTarget = "claude" | "cursor" | "vscode" | "copilot"; +export type EditorTarget = + | "claude" + | "cursor" + | "vscode" + | "copilot" + | "opencode"; export const EDITOR_LABELS: Record = { claude: "Claude Code", cursor: "Cursor", vscode: "VS Code", copilot: "Copilot CLI", + opencode: "opencode", }; export interface InitOptions { @@ -146,6 +156,12 @@ async function configureEditorSettings( } case "copilot": return configureCopilotSettings(projectRoot); + case "opencode": + // Opencode agent files are user-scope and written by `tryInstallPlugin` + // after authenticating against the plugins service. Nothing lands in + // the project tree — return the resolved user-scope path so the init + // summary has something meaningful to print. + return opencodeAgentsDir(); default: return configureClaudeSettings(projectRoot); } @@ -269,6 +285,42 @@ async function tryInstallPlugin(editor: EditorTarget): Promise { }; } + if (editor === "opencode") { + const { isOpencodeCliAvailable, installOpencodePlugin } = + await import("./plugin-install"); + + // Writing agent markdown to `~/.config/opencode/agents/` is only useful + // if opencode itself is on PATH — otherwise we leave stale files in a + // directory nothing reads. Mirror the detect-before-install guard that + // every other editor's install path already uses. + if (!(await isOpencodeCliAvailable())) { + return { + installed: true, + // `cli-not-found` is a marker recognized by `printManualInstructions` + // in `commands/init.ts`; the user-facing message lives there. + detail: "cli-not-found", + }; + } + + try { + await installOpencodePlugin(credentials.token); + return { + installed: true, + autoInstalled: true, + detail: opencodeAgentsDir(), + }; + } catch (error) { + // Surface as a non-auto install so init routes through + // `printManualInstructions("opencode", detail)`, which prints a + // retry hint to the user. + logDebug("Failed to install opencode agent bundle:", error); + return { + installed: true, + detail: error instanceof Error ? error.message : String(error), + }; + } + } + if (editor === "copilot") { const { isCopilotCliAvailable, diff --git a/src/helpers/paths.ts b/src/helpers/paths.ts index b4c795bc..7fc8eddf 100644 --- a/src/helpers/paths.ts +++ b/src/helpers/paths.ts @@ -26,6 +26,37 @@ export function internalPath(...path: string[]) { return join(internalFolder, ...path); } +/** + * Accept an env-var value only when it is a non-empty string that isn't the + * literal "undefined". Mirrors the defensive handling in `archgateHomeDir()` + * — shells and tooling sometimes surface an unset variable as the string + * "undefined", which would otherwise leak into the resolved path. + */ +function usableEnv(value: string | undefined): string | null { + if (typeof value !== "string") return null; + if (value.length === 0 || value === "undefined") return null; + return value; +} + +/** + * Resolve the opencode user-scope agents directory. + * + * Opencode uses the `xdg-basedir` package to locate its config root. That + * package reads `$XDG_CONFIG_HOME` when set and otherwise falls back to + * `~/.config` on **all platforms** — including Windows, where the resolved + * path is `C:\Users\\.config\opencode\agents` rather than anything + * under `%APPDATA%`. We mirror the same resolution here so the CLI writes + * to the exact directory opencode reads from. + * + * The path is resolved at call time, not cached — tests override `HOME` / + * `XDG_CONFIG_HOME` per-test and expect the helper to pick up the override. + */ +export function opencodeAgentsDir(): string { + const xdg = usableEnv(Bun.env.XDG_CONFIG_HOME); + const base = xdg ?? join(archgateHomeDir(), ".config"); + return join(base, "opencode", "agents"); +} + export const paths = { cacheFolder: internalPath("cache") } as const; export function projectPath(projectRoot: string, ...path: string[]) { diff --git a/src/helpers/plugin-install.ts b/src/helpers/plugin-install.ts index 9cd9a16b..2c47aa79 100644 --- a/src/helpers/plugin-install.ts +++ b/src/helpers/plugin-install.ts @@ -1,9 +1,9 @@ /** Download and install the archgate plugin for supported editors. */ -import { unlinkSync } from "node:fs"; +import { mkdirSync, unlinkSync } from "node:fs"; import { logDebug } from "./log"; -import { internalPath } from "./paths"; +import { internalPath, opencodeAgentsDir } from "./paths"; import { resolveCommand } from "./platform"; const PLUGINS_API = "https://plugins.archgate.dev"; @@ -175,6 +175,64 @@ export async function installCursorPlugin(token: string): Promise { } } +// --------------------------------------------------------------------------- +// opencode — download agent bundle into user-scope agents dir +// --------------------------------------------------------------------------- + +/** + * Check whether the `opencode` CLI is available on the system PATH. + * On WSL, also checks for `opencode.exe` (Windows-side installation). + */ +export async function isOpencodeCliAvailable(): Promise { + const resolved = await resolveCommand("opencode"); + return resolved !== null; +} + +/** + * Install the archgate opencode agents into the user-scope agents directory. + * + * Opencode has no plugin marketplace — agents are plain markdown files. + * Archgate ships them as an authenticated tarball at `/api/opencode`. The + * tarball contains `archgate-*.md` files at its root which extract directly + * into the resolved `opencodeAgentsDir()`. + * + * The extraction uses `tar` via `Bun.spawn` (ARCH-007) — `tar` is available + * on macOS, Linux, and modern Windows (bsdtar ships with Windows 10+). + * + * Throws on download or extraction failure so callers can surface a manual + * retry hint. + */ +export async function installOpencodePlugin(token: string): Promise { + const tarballPath = internalPath("archgate-opencode.tar.gz"); + const agentsDir = opencodeAgentsDir(); + + const buffer = await downloadPluginAsset("/api/opencode", token); + logDebug( + `Downloaded opencode agent bundle (${Math.round(buffer.byteLength / 1024)} KB)` + ); + await Bun.write(tarballPath, buffer); + + try { + // Ensure target dir exists — tar will write files, but it won't create + // the enclosing `/opencode/agents/` path. + mkdirSync(agentsDir, { recursive: true }); + + logDebug(`Extracting opencode agents into ${agentsDir}`); + const result = await run(["tar", "-xzf", tarballPath, "-C", agentsDir]); + if (result.exitCode !== 0) { + throw new Error( + `tar -xzf failed (exit ${result.exitCode}) while extracting opencode agents` + ); + } + } finally { + try { + unlinkSync(tarballPath); + } catch { + // Ignore cleanup errors + } + } +} + // --------------------------------------------------------------------------- // Copilot CLI — CLI auto-install + manual fallback // --------------------------------------------------------------------------- diff --git a/tests/commands/plugin/install.test.ts b/tests/commands/plugin/install.test.ts index 28d3679b..6916b7bd 100644 --- a/tests/commands/plugin/install.test.ts +++ b/tests/commands/plugin/install.test.ts @@ -38,6 +38,7 @@ describe("registerPluginInstallCommand", () => { "cursor", "vscode", "copilot", + "opencode", ]); }); }); diff --git a/tests/commands/plugin/url.test.ts b/tests/commands/plugin/url.test.ts index f2af355d..47847b9a 100644 --- a/tests/commands/plugin/url.test.ts +++ b/tests/commands/plugin/url.test.ts @@ -38,6 +38,7 @@ describe("registerPluginUrlCommand", () => { "cursor", "vscode", "copilot", + "opencode", ]); }); }); diff --git a/tests/helpers/editor-detect.test.ts b/tests/helpers/editor-detect.test.ts index ca6440d4..17fef71b 100644 --- a/tests/helpers/editor-detect.test.ts +++ b/tests/helpers/editor-detect.test.ts @@ -4,15 +4,16 @@ import { detectEditors } from "../../src/helpers/editor-detect"; describe("editor-detect", () => { describe("detectEditors", () => { - test("returns all four editors with availability status", async () => { + test("returns all five editors with availability status", async () => { const editors = await detectEditors(); - expect(editors).toHaveLength(4); + expect(editors).toHaveLength(5); expect(editors.map((e) => e.id)).toEqual([ "claude", "cursor", "vscode", "copilot", + "opencode", ]); for (const editor of editors) { diff --git a/tests/helpers/plugin-install.test.ts b/tests/helpers/plugin-install.test.ts index a521fb1d..709a02d6 100644 --- a/tests/helpers/plugin-install.test.ts +++ b/tests/helpers/plugin-install.test.ts @@ -5,6 +5,7 @@ import { buildVscodeMarketplaceUrl, isClaudeCliAvailable, isCopilotCliAvailable, + isOpencodeCliAvailable, isVscodeCliAvailable, } from "../../src/helpers/plugin-install"; @@ -67,4 +68,11 @@ describe("plugin-install", () => { expect(typeof result).toBe("boolean"); }); }); + + describe("isOpencodeCliAvailable", () => { + test("returns a boolean", async () => { + const result = await isOpencodeCliAvailable(); + expect(typeof result).toBe("boolean"); + }); + }); });