feat(settings): retire the third-party plugin integrations

Settings → Integrations offered install cards for the Claude Code and
Cursor provider plugins. They are gone: the section, its plugin catalog,
its own i18n module and tests, the settings search entries, the page
keywords, and the two sprite icons only it used. The page now holds the
built-in GitHub and Linear cards, so it is hidden in VS Code where neither
applies; its title and description live in the settings dictionaries.

Docs follow: the Integrations page in every locale now documents GitHub
(pointing at its own page) and Linear in full, the GitHub page names
Settings → Integrations as the place to connect and covers linking an
issue or PR to a message, and the Providers pages no longer promise Claude
or Cursor subscriptions.

Claude-Session: https://claude.ai/code/session_01HB9wdLQoZX2vfyDjwv6Rso
This commit is contained in:
Bohdan Triapitsyn
2026-09-04 23:34:15 +03:00
parent 34bf631157
commit d6f0f2f23c
58 changed files with 435 additions and 1764 deletions
+7 -3
View File
@@ -9,11 +9,11 @@ Verbinde dein GitHub-Konto und OpenChamber kann Issues und Pull Requests einlese
## GitHub verbinden
1. Öffne **Einstellungen → Git**.
2. Wähle unter GitHub **Connect**. OpenChamber zeigt einen Link und einen kurzen Code an.
1. Öffne **Einstellungen → Integrationen** und klappe die Karte **GitHub** auf.
2. Wähle **Connect GitHub**. OpenChamber zeigt einen Link und einen kurzen Code an.
3. Öffne den Link, gib den Code ein und bestätige.
Wenn die Verbindung steht, erscheint dein Konto im GitHub-Bereich. Du kannst mehr als ein Konto verbinden und zwischen ihnen wechseln oder dich jederzeit trennen.
Wenn die Verbindung steht, erscheint dein Konto auf der Karte. Du kannst mehr als ein Konto verbinden und zwischen ihnen wechseln oder dich jederzeit trennen. Ist die `gh`-CLI auf demselben Rechner angemeldet, kann OpenChamber sie als Fallback nutzen.
## Arbeit aus einem Issue oder PR starten
@@ -28,6 +28,10 @@ So landest du direkt in einer Sitzung, in der der Kontext bereits geladen ist.
Im **PR**-Tab der [Git-Ansicht](/git/) kannst du einen Pull Request erstellen, aktualisieren, einen Entwurf als bereit markieren oder mergen. OpenChamber kann den PR-Titel und die Beschreibung aus deinen Änderungen generieren.
## Issue oder PR an eine Nachricht hängen
Wähle im Chat-Composer **Link GitHub Issue** oder **Link GitHub PR**. Das Issue bzw. der PR mit seinem Diff geht als Kontext mit deiner nächsten Nachricht mit, und das Arbeitsstatus-Panel der Session behält einen Link darauf. Über denselben Picker kannst du auch eine neue Session mit dem Issue als erstem Prompt starten.
## Verwandt
- [Git- & GitHub-Workflows](/git/) — committen und Branches verwalten
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Integrationen
description: Nutze dein Claude- oder Cursor-Abo als Provider.
description: Verbinde GitHub und Linear mit OpenChamber.
---
# Integrationen
Eine Integration ist ein kleines Plugin, das OpenChamber einen Provider hinzufügt — auf Basis eines Abos, das du bereits hast. Verwalten kannst du sie unter **Settings → Integrations**.
Unter **Einstellungen → Integrationen** meldest du dich bei den Diensten an, mit denen OpenChamber arbeitet. Die Anmeldung wird auf dem OpenChamber-Server gespeichert, sodass Web, Desktop und ein gekoppeltes Telefon sie teilen.
> **Experimentelle Funktion.** Wir bemühen uns, die Richtlinien der Anbieter zu respektieren, aber Kontobeschränkungen und Sperrungen liegen bei jedem Anbieter. Nutze Integrationen auf eigenes Risiko.
## GitHub
Verfügbare Integrationen:
Klappe die Karte **GitHub** auf und wähle **Connect GitHub**, um dich mit einem kurzen Gerätecode anzumelden. Danach kann OpenChamber Sessions aus Issues und Pull Requests starten, sie an Nachrichten hängen und PRs öffnen oder aktualisieren. Alles, was GitHub kann, steht unter [GitHub Issues & PRs](/de/github/).
- **Claude Code** — dein Claude Pro- oder Max-Plan, ohne API-Keys
- **Cursor** — die Modell-Limits deines Cursor-Plans
## Linear
## Integration installieren
### Workspace verbinden
1. Öffne **Settings → Integrations**.
2. Suche die Integration und wähle **Install**.
3. Starte OpenCode neu, wenn darum gebeten wird — der Provider erscheint nach dem Neustart.
4. Wähle **Set up** und melde dich an. Die Modelle erscheinen danach in der Modellauswahl im Chat.
1. Klappe die Karte **Linear** auf und wähle **Connect**.
2. Bestätige den Zugriff im Browser-Tab, der sich öffnet. Bis dahin zeigt die Karte **Waiting for Linear**.
Integrationen werden für deinen Benutzer installiert und funktionieren damit in jedem Projekt. Aktualisieren oder entfernen kannst du sie jederzeit über dieselbe Karte.
Eine weitere Linear-Organisation verbindest du mit **Add workspace**. Es ist immer genau ein Workspace aktuell: Wechsle mit **Switch to**, und **Disconnect** entfernt nur den aktuellen. Deine Projektzuordnung bleibt erhalten.
## Claude Code
### Issues durchsuchen
Claude Code nutzt deinen Claude Pro- oder Max-Plan — ohne API-Keys und ohne separate Claude-App.
Sobald ein Workspace verbunden ist, erscheint das Panel **Linear** in der rechten Kontextleiste. Es listet die Issues des aktuellen Workspace und erlaubt dir:
1. Installiere die Integration (siehe oben).
2. Wähle **Set up** und melde dich an. Wenn du die Claude Code CLI noch nicht hast, bietet die Einrichtung an, sie zuerst zu installieren, und meldet dich danach an.
- nach Status (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), Zuständigem (**Anyone** oder **Assigned to me**), Team und Priorität zu filtern
- nach Titel, Kennung oder Linear-URL zu suchen
- ein Issue zu öffnen und Beschreibung, Kommentare, Labels und Priorität zu lesen
- seinen **Status** zu ändern oder **Close issue** zu wählen
- den aktuellen **Workspace** zu wechseln
Claude Code ist die einzige Integration hier, die ihre Provider-CLI installiert und angemeldet benötigt. Cursor braucht seine CLI nicht.
### Session aus einem Issue starten
**Wie dein Claude-Konto geschützt bleibt:** Diese Integration nutzt das offizielle Claude Agent SDK von Anthropic und deine installierte Claude Code CLI. Sie kapert kein OAuth, extrahiert oder wiederholt keine Browser-Tokens, gibt sich nicht als nicht unterstützter Client aus und umgeht nicht Anthropics Authentifizierung. Sie bleibt auf dem von Anthropic unterstützten Zugriffsweg und trägt daher nicht das mit Token-Hijacking oder unautorisierten Authentifizierungsumgehungen verbundene Sperrrisiko.
- Öffne im Linear-Panel ein Issue und wähle **Start session**. Der Button bleibt in der Fußzeile, während das Issue scrollt.
- Wähle im Chat **New Session From Linear Issue**, um eines aus der Liste zu wählen, mit **Create in worktree**, wenn du einen frischen Branch möchtest.
- Wähle im Dialog **New Worktree** die Option **Start from Linear Issue**.
## Cursor
Die Session öffnet sich im Projekt, das dem Team des Issues zugeordnet ist, mit dem Issue als erstem Prompt. Teams ordnest du in der Linear-Karte zu: **Default project** gilt für alle Teams, **Team projects** überschreibt es pro Team. Bei einem nicht zugeordneten Team wirst du zuerst um die Zuordnung gebeten. Die erste Nachricht entsteht aus dem Magic Prompt **Issue Review**, den du unter **Einstellungen → Magic Prompts → Linear** bearbeiten kannst.
Cursor macht die Modelle deines Cursor-Plans in OpenChamber nutzbar.
### Issue an eine Nachricht hängen
1. Installiere die Integration (siehe oben).
2. Wähle **Set up**, öffne den Link und genehmige den Zugriff im Browser. Kein API-Key nötig. Die Modellliste lädt nach der Anmeldung automatisch.
Wähle im Chat-Composer **Link Linear Issue**. Das Issue geht als Kontext mit deiner nächsten Nachricht mit, und das Arbeitsstatus-Panel der Session behält einen Link darauf.
## Aktualisieren oder entfernen
### Session-Kommentare
- **Update** installiert die neueste veröffentlichte Version des Plugins.
- **Remove** löscht das Plugin aus deiner OpenCode-Konfiguration. Der Provider wird beim nächsten Neuladen von OpenCode nicht mehr geladen.
Wenn eine Karte meldet, dass Einträge manuell verwaltet werden müssen, wähle **Manage plugins** und bereinige die Duplikate dort.
Schalte **Session comments** in der Linear-Karte ein, und eine aus einem Issue gestartete Session schreibt beim Start, beim Abschluss oder bei einem Fehler einen Kommentar auf das Issue, jeweils mit einem Link, der die Session öffnet. Kommentare werden nur gepostet, wenn dieser OpenChamber-Server eine öffentliche Adresse hat, damit der Link für alle am Issue funktioniert; bei einer lokalen oder privaten Adresse wird nichts gepostet.
## Verwandtes
- [Anbieter, Modelle und Agenten](/de/providers/) — weitere Provider verbinden und Modelle wählen
- [Nutzung und Kontingente](/de/usage/) — verfolge, wie viel du genutzt hast
- [GitHub Issues & PRs](/de/github/) — alles, was GitHub in OpenChamber kann
- [Worktree-Sessions](/de/worktrees/) — wo Issue-Sessions starten können
- [Magic Prompts](/de/magic-prompts/) — den Prompt bearbeiten, mit dem eine Linear-Session beginnt
+1 -1
View File
@@ -45,6 +45,6 @@ Provider-Anmeldungen werden von OpenCode gespeichert, nicht von OpenChamber, dah
## Weiterführend
- [Integrationen](/integrations/) — nutze ein Claude-, Command-Code- oder Cursor-Abo als Provider
- [Integrationen](/de/integrations/) — GitHub und Linear verbinden
- [MCP-Server](/mcp/) — füge Agents zusätzliche Werkzeuge hinzu
- [Nutzung & Kontingente](/usage/) — verfolge, wie viel du verbraucht hast
+7 -3
View File
@@ -9,11 +9,11 @@ Conecta tu cuenta de GitHub y OpenChamber podrá traer issues y pull requests, i
## Conecta GitHub
1. Abre **Settings → Git**.
2. En GitHub, elige **Connect**. OpenChamber muestra un enlace y un código corto.
1. Abre **Settings → Integrations** y despliega la tarjeta **GitHub**.
2. Elige **Connect GitHub**. OpenChamber muestra un enlace y un código corto.
3. Abre el enlace, introduce el código y aprueba.
Cuando esté conectado, tu cuenta aparece en la sección de GitHub. Puedes conectar más de una cuenta y cambiar entre ellas, o desconectar en cualquier momento.
Cuando esté conectado, tu cuenta aparece en la tarjeta. Puedes conectar más de una cuenta y cambiar entre ellas, o desconectar en cualquier momento. Si la CLI `gh` tiene sesión iniciada en la misma máquina, OpenChamber puede usarla como respaldo.
## Empieza a trabajar desde una issue o PR
@@ -28,6 +28,10 @@ Esto te deja directamente en una sesión con el contexto ya cargado.
Desde la pestaña **PR** en la [vista de git](/es/git/), puedes crear un pull request, actualizarlo, marcar un borrador como listo o fusionarlo. OpenChamber puede generar el título y la descripción del PR a partir de tus cambios.
## Vincula una issue o PR a un mensaje
En el compositor del chat, elige **Link GitHub Issue** o **Link GitHub PR**. La issue, o el PR con su diff, acompaña tu siguiente mensaje como contexto, y el panel de estado de trabajo de la sesión conserva un enlace. El mismo selector puede iniciar una nueva sesión con la issue como primer prompt.
## Relacionado
- [Flujos de trabajo de Git y GitHub](/es/git/) — haz commit y gestiona ramas
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Integraciones
description: Usa tu suscripción de Claude o Cursor como proveedor.
description: Conecta GitHub y Linear con OpenChamber.
---
# Integraciones
Una integración es un pequeño plugin que añade un proveedor a OpenChamber usando una suscripción que ya tienes. Las gestionas en **Settings → Integrations**.
En **Ajustes → Integraciones** inicias sesión en los servicios con los que trabaja OpenChamber. El inicio de sesión se guarda en el servidor de OpenChamber, así que la web, el escritorio y un teléfono emparejado lo comparten.
> **Función experimental.** Buscamos respetar las políticas de los proveedores, pero las restricciones y suspensiones de cuentas son decisión de cada proveedor. Usa las integraciones bajo tu propia responsabilidad.
## GitHub
Integraciones disponibles:
Despliega la tarjeta **GitHub** y elige **Connect GitHub** para iniciar sesión con un código de dispositivo corto. Una vez conectado, OpenChamber puede iniciar sesiones desde issues y pull requests, adjuntarlos a mensajes y abrir o actualizar PRs. Todo lo que GitHub puede hacer está en [Issues y PRs de GitHub](/es/github/).
- **Claude Code** — tu plan Claude Pro o Max, sin claves de API
- **Cursor** — los límites de modelos de tu plan de Cursor
## Linear
## Instalar una integración
### Conecta un espacio de trabajo
1. Abre **Settings → Integrations**.
2. Busca la integración y elige **Install**.
3. Reinicia OpenCode cuando se te pida — el proveedor aparece tras el reinicio.
4. Elige **Set up** e inicia sesión. Los modelos aparecerán luego en el selector de modelos del chat.
1. Despliega la tarjeta **Linear** y elige **Connect**.
2. Aprueba el acceso en la pestaña del navegador que se abre. Mientras tanto la tarjeta muestra **Waiting for Linear**.
Las integraciones se instalan para tu usuario, así que funcionan en todos los proyectos. Puedes actualizarlas o eliminarlas desde la misma tarjeta en cualquier momento.
Conecta otra organización de Linear con **Add workspace**. Solo un espacio de trabajo es el actual: cambia con **Switch to**, y **Disconnect** quita solo el actual. La asignación de proyectos se conserva.
## Claude Code
### Explora issues
Claude Code usa tu plan Claude Pro o Max — sin claves de API y sin una app de Claude aparte.
Con un espacio de trabajo conectado, el panel **Linear** aparece en la barra de contexto derecha. Lista las issues del espacio actual y te permite:
1. Instala la integración (arriba).
2. Elige **Set up** e inicia sesión. Si aún no tienes la CLI de Claude Code, la configuración ofrece instalarla primero y luego iniciar sesión.
- filtrar por estado (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), asignado (**Anyone** o **Assigned to me**), equipo y prioridad
- buscar por título, identificador o URL de Linear
- abrir una issue para leer su descripción, comentarios, etiquetas y prioridad
- cambiar su **Status** o elegir **Close issue**
- cambiar el **Workspace** actual
Claude Code es la única integración de esta página que requiere tener la CLI de su proveedor instalada y con sesión iniciada. Cursor no requiere su CLI.
### Inicia una sesión desde una issue
**Cómo se protege tu cuenta de Claude:** esta integración usa el Claude Agent SDK oficial de Anthropic y tu CLI de Claude Code instalada. No secuestra OAuth, no extrae ni reutiliza tokens del navegador, no se hace pasar por un cliente no admitido ni omite la autenticación de Anthropic. Se mantiene en la vía de acceso admitida por Anthropic, por lo que no conlleva el riesgo de baneo asociado al secuestro de tokens o a rodeos de autenticación no autorizados.
- En el panel de Linear, abre una issue y elige **Start session**. El botón se queda en el pie mientras la issue se desplaza.
- En el chat, elige **New Session From Linear Issue** para escoger una de la lista, con **Create in worktree** si quieres una rama nueva.
- En el diálogo **New Worktree**, elige **Start from Linear Issue**.
## Cursor
La sesión se abre en el proyecto asignado al equipo de la issue, con la issue como primer prompt. Asigna equipos en la tarjeta de Linear: **Default project** cubre todos los equipos y **Team projects** lo sobrescribe por equipo. Un equipo sin asignar te pide asignarlo primero. El primer mensaje se construye con el magic prompt **Issue Review**, que puedes editar en **Ajustes → Magic Prompts → Linear**.
Cursor hace disponibles en OpenChamber los modelos incluidos en tu plan de Cursor.
### Vincula una issue a un mensaje
1. Instala la integración (arriba).
2. Elige **Set up**, abre el enlace y autoriza el acceso en tu navegador. No necesitas clave de API. La lista de modelos se carga automáticamente tras iniciar sesión.
En el compositor del chat, elige **Link Linear Issue**. La issue acompaña tu siguiente mensaje como contexto y el panel de estado de trabajo de la sesión conserva un enlace a ella.
## Actualizar o eliminar
### Comentarios de sesión
- **Update** instala la última versión publicada del plugin.
- **Remove** elimina el plugin de tu configuración de OpenCode. El proveedor deja de cargarse cuando OpenCode se recarga.
Si una tarjeta indica que las entradas requieren gestión manual, elige **Manage plugins** y limpia ahí los duplicados.
Activa **Session comments** en la tarjeta de Linear y una sesión iniciada desde una issue publica un comentario en esa issue al empezar, terminar o fallar, cada uno con un enlace que abre la sesión. Los comentarios solo se publican cuando este servidor de OpenChamber tiene una dirección pública, para que el enlace funcione para todos en la issue; en una dirección local o privada no se publica nada.
## Relacionado
- [Proveedores, modelos y agentes](/es/providers/) — conecta otros proveedores y elige modelos
- [Uso y cuotas](/es/usage/) — sigue cuánto has usado
- [Issues y PRs de GitHub](/es/github/) — todo lo que GitHub puede hacer en OpenChamber
- [Sesiones en worktree](/es/worktrees/) — donde pueden empezar las sesiones desde issues
- [Magic Prompts](/es/magic-prompts/) — edita el prompt con el que empieza una sesión de Linear
+1 -1
View File
@@ -45,6 +45,6 @@ Los inicios de sesión de los proveedores los guarda OpenCode, no OpenChamber, a
## Relacionado
- [Integraciones](/es/integrations/) — usa una suscripción de Claude o Cursor como proveedor
- [Integraciones](/es/integrations/) — conecta GitHub y Linear
- [Servidores MCP](/es/mcp/) — añade herramientas extra para los agentes
- [Uso y cuotas](/es/usage/) — controla cuánto has consumido
+7 -3
View File
@@ -9,11 +9,11 @@ Connectez votre compte GitHub et OpenChamber peut récupérer les issues et pull
## Connecter GitHub
1. Ouvrez **Paramètres → Git**.
2. Sous GitHub, choisissez **Connect**. OpenChamber affiche un lien et un code court.
1. Ouvrez **Paramètres → Intégrations** et dépliez la carte **GitHub**.
2. Choisissez **Connect GitHub**. OpenChamber affiche un lien et un code court.
3. Ouvrez le lien, saisissez le code et approuvez.
Une fois connecté, votre compte apparaît dans la section GitHub. Vous pouvez connecter plusieurs comptes et passer de lun à lautre, ou vous déconnecter à tout moment.
Une fois connecté, votre compte apparaît sur la carte. Vous pouvez connecter plusieurs comptes et passer de lun à lautre, ou vous déconnecter à tout moment. Si la CLI `gh` est connectée sur la même machine, OpenChamber peut lutiliser en secours.
## Démarrer le travail depuis une issue ou une PR
@@ -28,6 +28,10 @@ Vous arrivez directement dans une session avec le contexte déjà chargé.
Depuis longlet **PR** de la [vue git](/git/), vous pouvez créer une pull request, la mettre à jour, marquer un brouillon comme prêt ou la merger. OpenChamber peut générer le titre et la description de la PR à partir de vos changements.
## Lier une issue ou une PR à un message
Dans le composer du chat, choisissez **Link GitHub Issue** ou **Link GitHub PR**. Lissue, ou la PR avec son diff, accompagne votre prochain message comme contexte, et le panneau d’état de la session en garde un lien. Le même sélecteur peut démarrer une nouvelle session avec lissue comme premier prompt.
## Pages liées
- [Workflows Git et GitHub](/git/) — commiter et gérer les branches
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Intégrations
description: Utilise ton abonnement Claude ou Cursor comme fournisseur.
description: Connecte GitHub et Linear à OpenChamber.
---
# Intégrations
Une intégration est un petit plugin qui ajoute un fournisseur à OpenChamber à partir d'un abonnement que tu possèdes déjà. Tu les gères dans **Settings → Integrations**.
**Paramètres → Intégrations** est l'endroit où tu te connectes aux services avec lesquels OpenChamber travaille. La connexion est enregistrée sur le serveur OpenChamber, donc le web, le bureau et un téléphone appairé la partagent.
> **Fonctionnalité expérimentale.** Nous cherchons à respecter les règles des fournisseurs, mais les restrictions et suspensions de compte relèvent de leur décision. Utilise les intégrations à tes risques.
## GitHub
Intégrations disponibles :
Déplie la carte **GitHub** et choisis **Connect GitHub** pour te connecter avec un code d'appareil court. Une fois connecté, OpenChamber peut démarrer des sessions depuis des issues et des pull requests, les attacher à des messages, et ouvrir ou mettre à jour des PR. Tout ce que GitHub sait faire est sur [Issues et PR GitHub](/fr/github/).
- **Claude Code** — ton plan Claude Pro ou Max, sans clés API
- **Cursor** — les limites de modèles de ton plan Cursor
## Linear
## Installer une intégration
### Connecter un espace de travail
1. Ouvre **Settings → Integrations**.
2. Trouve l'intégration et choisis **Install**.
3. Redémarre OpenCode quand c'est demandé — le fournisseur apparaît après le redémarrage.
4. Choisis **Set up** et connecte-toi. Les modèles apparaissent ensuite dans le sélecteur de modèles du chat.
1. Déplie la carte **Linear** et choisis **Connect**.
2. Approuve l'accès dans l'onglet de navigateur qui s'ouvre. La carte affiche **Waiting for Linear** en attendant.
Les intégrations s'installent pour ton utilisateur et fonctionnent donc dans tous les projets. Tu peux les mettre à jour ou les retirer à tout moment depuis la même carte.
Connecte une autre organisation Linear avec **Add workspace**. Un seul espace de travail est courant à la fois : change avec **Switch to**, et **Disconnect** ne retire que le courant. Ton association de projets est conservée.
## Claude Code
### Parcourir les issues
Claude Code utilise ton plan Claude Pro ou Max — sans clés API et sans application Claude séparée.
Dès qu'un espace de travail est connecté, le panneau **Linear** apparaît dans la barre de contexte de droite. Il liste les issues de l'espace courant et te permet de :
1. Installe l'intégration (ci-dessus).
2. Choisis **Set up** et connecte-toi. Si tu n'as pas encore la CLI Claude Code, la configuration propose de l'installer d'abord, puis de te connecter.
- filtrer par statut (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), assigné (**Anyone** ou **Assigned to me**), équipe et priorité
- chercher par titre, identifiant ou URL Linear
- ouvrir une issue pour lire sa description, ses commentaires, ses labels et sa priorité
- changer son **Status** ou choisir **Close issue**
- changer le **Workspace** courant
Claude Code est la seule intégration ici qui exige que la CLI de son fournisseur soit installée et connectée. Cursor n'exige pas sa CLI.
### Démarrer une session depuis une issue
**Comment ton compte Claude reste protégé :** cette intégration utilise le Claude Agent SDK officiel d'Anthropic et ta CLI Claude Code installée. Elle ne détourne pas l'OAuth, n'extrait ni rejoue de tokens de navigateur, ne se fait pas passer pour un client non pris en charge et ne contourne pas l'authentification d'Anthropic. Elle reste sur la voie d'accès prise en charge par Anthropic et ne porte donc pas le risque de bannissement associé au détournement de tokens ou aux contournements d'authentification non autorisés.
- Dans le panneau Linear, ouvre une issue et choisis **Start session**. Le bouton reste dans le pied pendant que l'issue défile.
- Dans le chat, choisis **New Session From Linear Issue** pour en choisir une dans la liste, avec **Create in worktree** si tu veux une branche neuve.
- Dans la boîte de dialogue **New Worktree**, choisis **Start from Linear Issue**.
## Cursor
La session s'ouvre dans le projet associé à l'équipe de l'issue, avec l'issue comme premier prompt. Associe les équipes dans la carte Linear : **Default project** couvre toutes les équipes, et **Team projects** le remplace équipe par équipe. Une équipe non associée te demande d'abord de le faire. Le premier message est construit à partir du magic prompt **Issue Review**, modifiable dans **Paramètres → Magic Prompts → Linear**.
Cursor rend disponibles dans OpenChamber les modèles inclus dans ton plan Cursor.
### Lier une issue à un message
1. Installe l'intégration (ci-dessus).
2. Choisis **Set up**, ouvre le lien et autorise l'accès dans ton navigateur. Aucune clé API n'est nécessaire. La liste des modèles se charge automatiquement après la connexion.
Dans le composer du chat, choisis **Link Linear Issue**. L'issue accompagne ton prochain message comme contexte, et le panneau d'état de la session garde un lien vers elle.
## Mettre à jour ou retirer
### Commentaires de session
- **Update** installe la dernière version publiée du plugin.
- **Remove** supprime le plugin de ta configuration OpenCode. Le fournisseur cesse d'être chargé au prochain rechargement d'OpenCode.
Si une carte indique que les entrées nécessitent une gestion manuelle, choisis **Manage plugins** et nettoie les doublons à cet endroit.
Active **Session comments** dans la carte Linear : une session démarrée depuis une issue publie un commentaire sur cette issue au démarrage, à la fin ou en cas d'échec, chacun avec un lien qui ouvre la session. Les commentaires ne sont publiés que si ce serveur OpenChamber a une adresse publique, pour que le lien fonctionne pour tout le monde sur l'issue ; sur une adresse locale ou privée, rien n'est publié.
## À voir aussi
- [Fournisseurs, modèles et agents](/fr/providers/) — connecter d'autres fournisseurs et choisir des modèles
- [Utilisation et quotas](/fr/usage/) — suis ta consommation
- [Issues et PR GitHub](/fr/github/) — tout ce que GitHub peut faire dans OpenChamber
- [Sessions worktree](/fr/worktrees/) — où les sessions d'issue peuvent démarrer
- [Magic Prompts](/fr/magic-prompts/) — modifier le prompt de départ d'une session Linear
+1 -1
View File
@@ -45,6 +45,6 @@ Les connexions aux fournisseurs sont stockées par OpenCode, pas OpenChamber ; e
## Pages liées
- [Intégrations](/integrations/) — utiliser un abonnement Claude ou Cursor comme fournisseur
- [Intégrations](/fr/integrations/) — connecter GitHub et Linear
- [Serveurs MCP](/mcp/) — ajouter des outils supplémentaires aux agents
- [Utilisation et quotas](/usage/) — suivre votre consommation
+7 -3
View File
@@ -9,11 +9,11 @@ Connect your GitHub account and OpenChamber can pull in issues and pull requests
## Connect GitHub
1. Open **Settings → Git**.
2. Under GitHub, choose **Connect**. OpenChamber shows a link and a short code.
1. Open **Settings → Integrations** and expand the **GitHub** card.
2. Choose **Connect GitHub**. OpenChamber shows a link and a short code.
3. Open the link, enter the code, and approve.
When it's connected, your account shows under the GitHub section. You can connect more than one account and switch between them, or disconnect at any time.
When it's connected, your account shows on the card. You can connect more than one account and switch between them, or disconnect at any time. If the `gh` CLI is signed in on the same machine, OpenChamber can use it as a fallback.
## Start work from an issue or PR
@@ -28,6 +28,10 @@ This drops you straight into a session with the context already loaded.
From the **PR** tab in the [git view](/git/), you can create a pull request, update it, mark a draft as ready, or merge it. OpenChamber can generate the PR title and description from your changes.
## Link an issue or PR to a message
In the chat composer, choose **Link GitHub Issue** or **Link GitHub PR**. The issue, or the PR with its diff, rides along with your next message as context, and the session's work status panel keeps a link to it. The same picker can start a new session with the issue as the first prompt.
## Related
- [Git & GitHub Workflows](/git/) — commit and manage branches
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Integrations
description: Use your Claude or Cursor subscription as a provider.
description: Connect GitHub and Linear to OpenChamber.
---
# Integrations
An integration is a small plugin that adds a provider to OpenChamber using a subscription you already have. You manage them at **Settings → Integrations**.
**Settings → Integrations** is where you sign in to the services OpenChamber works with. The sign-in is stored on the OpenChamber server, so web, desktop, and a paired phone share it.
> **Experimental feature.** We aim to respect provider policies, but account restrictions and suspensions remain each provider's decision. Use integrations at your own risk.
## GitHub
Available integrations:
Expand the **GitHub** card and choose **Connect GitHub** to sign in with a short device code. Once connected, OpenChamber can start sessions from issues and pull requests, attach them to messages, and open or update PRs. Everything GitHub can do is on [GitHub Issues & PRs](/github/).
- **Claude Code** — your Claude Pro or Max plan, no API keys
- **Cursor** — the model limits of your Cursor plan
## Linear
## Install an integration
### Connect a workspace
1. Open **Settings → Integrations**.
2. Find the integration and choose **Install**.
3. Restart OpenCode when asked — the provider appears after the restart.
4. Choose **Set up** and sign in. The models then appear in the chat model picker.
1. Expand the **Linear** card and choose **Connect**.
2. Approve access in the browser tab that opens. The card shows **Waiting for Linear** until you do.
Integrations install for your user, so they work in every project. You can update or remove them from the same card at any time.
Connect another Linear organization with **Add workspace**. One workspace is current at a time: switch with **Switch to**, and **Disconnect** removes only the current one. Your project mapping stays.
## Claude Code
### Browse issues
Claude Code uses your Claude Pro or Max plan — no API keys and no separate Claude app.
Once a workspace is connected, the **Linear** panel appears in the right-hand context rail. It lists the current workspace's issues and lets you:
1. Install the integration (above).
2. Choose **Set up** and sign in. If you don't have the Claude Code CLI yet, setup offers to install it first and then sign you in.
- filter by status (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), assignee (**Anyone** or **Assigned to me**), team, and priority
- search by title, identifier, or a Linear URL
- open an issue to read its description, comments, labels, and priority
- change its **Status** or **Close issue**
- switch the current **Workspace**
Claude Code is the only integration here that requires its provider CLI to be installed and signed in. Cursor does not require its CLI.
### Start a session from an issue
**How your Claude account stays safe:** this integration uses Anthropic's official Claude Agent SDK and your installed Claude Code CLI. It does not hijack OAuth, extract or replay browser tokens, impersonate an unsupported client, or bypass Anthropic's authentication flow. It stays on Anthropic's supported access path, so it does not carry the account-ban risk of token hijacking or unauthorized authentication workarounds.
- In the Linear panel, open an issue and choose **Start session**. The button stays in the footer while the issue scrolls.
- In the chat, choose **New Session From Linear Issue** to pick one from the list, with **Create in worktree** if you want a fresh branch.
- In the **New Worktree** dialog, choose **Start from Linear Issue**.
## Cursor
The session opens in the project mapped to the issue's team, with the issue as the first prompt. Map teams in the Linear card: **Default project** covers every team, and **Team projects** override it per team. An unmapped team asks you to map it first. The first message is built from the **Issue Review** magic prompt, which you can edit at **Settings → Magic Prompts → Linear**.
Cursor makes the models included in your Cursor plan available in OpenChamber.
### Link an issue to a message
1. Install the integration (above).
2. Choose **Set up**, open the link, and approve access in your browser. No API key is required. The model list loads automatically after you sign in.
In the chat composer, choose **Link Linear Issue**. The issue rides along with your next message as context, and the session's work status panel keeps a link back to it.
## Update or remove
### Session comments
- **Update** installs the latest published version of the plugin.
- **Remove** deletes the plugin from your OpenCode config. The provider stops loading after OpenCode refreshes.
If a card says the entries need manual management, choose **Manage plugins** and clean up the duplicates there.
Turn on **Session comments** in the Linear card and a session started from an issue posts a comment on that issue when it starts, finishes, or fails, each with a link that opens the session. Comments are only posted when this OpenChamber server has a public address, so the link works for everyone on the issue; on a local or private address nothing is posted.
## Related
- [Providers, Models & Agents](/providers/) — connect other providers and pick models
- [Usage & Quotas](/usage/) — track how much you've used
- [GitHub Issues & PRs](/github/) — everything GitHub can do in OpenChamber
- [Worktree Sessions](/worktrees/) — where issue sessions can start
- [Magic Prompts](/magic-prompts/) — edit the prompt a Linear session starts with
+7 -3
View File
@@ -9,11 +9,11 @@ GitHub アカウントを接続すると、OpenChamber は Issue とプルリク
## GitHub を接続する
1. **Settings → Git** を開きます。
2. GitHub セクションで **Connect** を選びます。OpenChamber がリンクと短いコードを表示します。
1. **Settings → Integrations** を開き、**GitHub** カードを展開します。
2. **Connect GitHub** を選びます。OpenChamber がリンクと短いコードを表示します。
3. リンクを開き、コードを入力して承認します。
接続されると、GitHub セクションにアカウントが表示されます。複数のアカウントを接続して切り替えたり、いつでも切断したりできます。
接続されると、カードにアカウントが表示されます。複数のアカウントを接続して切り替えたり、いつでも切断したりできます。同じマシンで `gh` CLI にサインイン済みなら、OpenChamber はそれをフォールバックとして使えます。
## Issue または PR から作業を始める
@@ -28,6 +28,10 @@ GitHub 接続済みで [worktree セッション](/worktrees/) を作成する
[Git ビュー](/git/) の **PR** タブから、プルリクエストの作成、更新、draft から ready への変更、マージができます。OpenChamber は変更内容から PR のタイトルと説明を生成できます。
## Issue や PR をメッセージに添付する
チャットのコンポーザーで **Link GitHub Issue** または **Link GitHub PR** を選びます。Issue、または diff 付きの PR が次のメッセージにコンテキストとして添付され、セッションの作業ステータスパネルにリンクが残ります。同じピッカーから、Issue を最初のプロンプトにした新しいセッションを開始することもできます。
## 関連
- [Git と GitHub ワークフロー](/git/) — コミットとブランチ管理
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: 統合機能
description: Claude または Cursor のサブスクリプションをプロバイダーとして使う
description: GitHub と Linear を OpenChamber に接続する
---
# 統合機能
統合機能(インテグレーション)は、すでに持っているサブスクリプションを使って OpenChamber にプロバイダーを追加する小さなプラグインです。**Settings → Integrations** で管理します。
**設定 → 統合機能** では、OpenChamber が連携するサービスにサインインします。サインイン情報は OpenChamber サーバーに保存されるため、Web、デスクトップ、ペアリングした端末で共有されます。
> **実験的な機能。** プロバイダーの方針を尊重するよう努めていますが、アカウントの制限や停止は各プロバイダーの判断に委ねられます。自己責任で連携を使用してください。
## GitHub
利用できる統合機能:
**GitHub** カードを展開し、**Connect GitHub** を選んで短いデバイスコードでサインインします。接続後は、Issue やプルリクエストからセッションを開始し、メッセージに添付し、PR を作成・更新できます。GitHub でできることは [GitHub Issues と PR](/ja/github/) にまとめています。
- **Claude Code** — Claude Pro または Max プラン、API キー不要
- **Cursor** — Cursor プランのモデル利用枠
## Linear
## 統合機能をインストールする
### ワークスペースを接続する
1. **Settings → Integrations** を開きます。
2. 統合機能を見つけて **Install** を選びます。
3. 求められたら OpenCode を再起動します — 再起動後にプロバイダーが現れます。
4. **Set up** を選んでサインインします。するとチャットのモデル選択にモデルが表示されます。
1. **Linear** カードを展開し、**Connect** を選びます。
2. 開いたブラウザータブでアクセスを承認します。承認するまでカードには **Waiting for Linear** と表示されます。
統合機能はユーザー単位でインストールされるため、すべてのプロジェクトで使えます。同じカードからいつでも更新や削除ができます。
別の Linear 組織は **Add workspace** で接続します。現在のワークスペースは常に 1 つで、**Switch to** で切り替え、**Disconnect** は現在のものだけを外します。プロジェクトの対応付けは残ります。
## Claude Code
### Issue を閲覧する
Claude Code は Claude Pro または Max プランを使います — API キーも Claude アプリも不要です。
ワークスペースを接続すると、右側のコンテキストレールに **Linear** パネルが現れます。現在のワークスペースの Issue を一覧し、次の操作ができます。
1. 統合機能をインストールします(上記)。
2. **Set up** を選んでサインインします。Claude Code CLI がまだない場合は、セットアップがまずインストールを提案し、その後サインインします。
- ステータス(**Backlog**、**To Do**、**In Progress**、**In Review**、**Done**、**Canceled**、**Duplicate**)、担当者(**Anyone** または **Assigned to me**)、チーム、優先度で絞り込む
- タイトル、識別子、Linear の URL で検索する
- Issue を開いて説明、コメント、ラベル、優先度を読む
- **Status** を変更する、または **Close issue** を選ぶ
- 現在の **Workspace** を切り替える
Claude Code は、ここで唯一プロバイダーの CLI のインストールとサインインを必要とする統合機能です。Cursor は CLI を必要としません。
### Issue からセッションを開始する
**Claude アカウントが守られる仕組み:** この統合機能は Anthropic の公式 Claude Agent SDK と、インストール済みの Claude Code CLI を使用します。OAuth の乗っ取り、ブラウザートークンの抽出や再生、未対応クライアントへの偽装、Anthropic の認証フローの回避は一切行いません。Anthropic がサポートする正規のアクセス経路を使うため、トークン乗っ取りや不正な認証の回避につきもののアカウント停止リスクはありません
- Linear パネルで Issue を開き、**Start session** を選びます。ボタンは Issue をスクロールしてもフッターに残ります
- チャットで **New Session From Linear Issue** を選ぶと一覧から選べます。新しいブランチが欲しければ **Create in worktree** を使います。
- **New Worktree** ダイアログで **Start from Linear Issue** を選びます。
## Cursor
セッションは Issue のチームに対応付けられたプロジェクトで開き、Issue が最初のプロンプトになります。チームの対応付けは Linear カードで行います。**Default project** が全チームに適用され、**Team projects** でチームごとに上書きできます。対応付けのないチームでは、先に対応付けを求められます。最初のメッセージは Magic Prompt の **Issue Review** から作られ、**設定 → Magic Prompts → Linear** で編集できます。
Cursor は Cursor プランに含まれるモデルを OpenChamber で使えるようにします。
### Issue をメッセージに添付する
1. 統合機能をインストールします(上記)
2. **Set up** を選び、リンクを開いてブラウザーでアクセスを許可します。API キーは不要です。サインイン後、モデル一覧は自動的に読み込まれます。
チャットのコンポーザーで **Link Linear Issue** を選びます。Issue は次のメッセージにコンテキストとして添付され、セッションの作業ステータスパネルにリンクが残ります
## 更新と削除
### セッションコメント
- **Update** はプラグインの最新の公開バージョンをインストールします
- **Remove** は OpenCode の設定からプラグインを削除します。OpenCode が再読み込みされるとプロバイダーは読み込まれなくなります。
カードに手動での管理が必要だと表示された場合は、**Manage plugins** を選んで重複を整理してください。
Linear カードで **Session comments** をオンにすると、Issue から開始したセッションが開始時、完了時、失敗時にその Issue へコメントを投稿します。各コメントにはセッションを開くリンクが付きます。コメントは、この OpenChamber サーバーが公開アドレスを持つ場合にのみ投稿されます(Issue の関係者全員がリンクを開けるようにするため)。ローカルやプライベートなアドレスでは何も投稿されません
## 関連情報
- [プロバイダー、モデル、エージェント](/ja/providers/) — 他のプロバイダーの接続とモデルの選択
- [使用量とクォータ](/ja/usage/) — 利用量を追跡
- [GitHub Issues と PR](/ja/github/) — OpenChamber で GitHub にできること
- [ワークツリーセッション](/ja/worktrees/) — Issue からのセッションを開始できる場所
- [Magic Prompts](/ja/magic-prompts/) — Linear セッションの最初のプロンプトを編集する
+1 -1
View File
@@ -45,6 +45,6 @@ OpenChamber が何かを行うには、少なくとも 1 つの AI プロバイ
## 関連
- [統合機能](/integrations/) — Claude または Cursor のサブスクリプションをプロバイダーとして使う
- [統合機能](/ja/integrations/) — GitHub と Linear を接続する
- [MCP サーバー](/mcp/) — エージェントに追加ツールを加える
- [使用量とクォータ](/usage/) — 使った量を追跡する
+7 -3
View File
@@ -9,11 +9,11 @@ GitHub 계정을 연결하면 OpenChamber가 이슈와 풀 리퀘스트를 가
## GitHub 연결하기
1. **Settings → Git**를 엽니다.
2. GitHub 아래에서 **Connect**를 선택합니다. OpenChamber가 링크와 짧은 코드를 표시합니다.
1. **Settings → Integrations**를 열고 **GitHub** 카드를 펼칩니다.
2. **Connect GitHub**를 선택합니다. OpenChamber가 링크와 짧은 코드를 표시합니다.
3. 링크를 열고 코드를 입력한 뒤 승인합니다.
연결되면 GitHub 섹션 아래에 계정이 표시됩니다. 계정을 여러 개 연결해 전환할 수 있으며, 언제든 연결을 해제할 수 있습니다.
연결되면 카드에 계정이 표시됩니다. 계정을 여러 개 연결해 전환할 수 있으며, 언제든 연결을 해제할 수 있습니다. 같은 컴퓨터에서 `gh` CLI에 로그인되어 있으면 OpenChamber가 이를 대체 수단으로 사용할 수 있습니다.
## 이슈나 PR에서 작업 시작하기
@@ -28,6 +28,10 @@ GitHub가 연결된 상태에서 [worktree 세션](/ko/worktrees/)을 만들면
[git 보기](/ko/git/)의 **PR** 탭에서 풀 리퀘스트를 만들고, 업데이트하고, 초안을 준비 완료로 표시하거나 병합할 수 있습니다. OpenChamber는 변경 사항에서 PR 제목과 설명을 생성할 수 있습니다.
## 이슈나 PR을 메시지에 연결하기
채팅 작성창에서 **Link GitHub Issue** 또는 **Link GitHub PR**을 선택합니다. 이슈, 또는 diff가 포함된 PR이 다음 메시지에 컨텍스트로 함께 전송되고, 세션의 작업 상태 패널에 링크가 남습니다. 같은 선택기에서 이슈를 첫 프롬프트로 하는 새 세션을 시작할 수도 있습니다.
## 관련 항목
- [Git & GitHub Workflows](/ko/git/) — 커밋하고 브랜치를 관리하세요
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: 통합 기능
description: Claude 또는 Cursor 구독을 공급자로 사용하세요.
description: GitHub와 Linear를 OpenChamber에 연결합니다.
---
# 통합 기능
통합 기능(인테그레이션)은 이미 가지고 있는 구독을 사용해 OpenChamber에 공급자를 추가하는 작은 플러그인니다. **Settings → Integrations**에서 관리합니다.
**설정 → 통합 기능**에서 OpenChamber가 함께 사용하는 서비스에 로그인니다. 로그인 정보는 OpenChamber 서버에 저장되므로 웹, 데스크톱, 페어링된 휴대전화가 이를 공유합니다.
> **실험 단계 기능.** 프로바이더 정책을 존중하려 노력하지만, 계정 제한과 정지는 각 프로바이더의 결정입니다. 본인의 책임 아래 통합 기능을 사용하세요.
## GitHub
사용 가능한 통합 기능:
**GitHub** 카드를 펼치고 **Connect GitHub**를 선택해 짧은 기기 코드로 로그인합니다. 연결되면 OpenChamber가 이슈와 풀 리퀘스트에서 세션을 시작하고, 메시지에 첨부하고, PR을 열거나 업데이트할 수 있습니다. GitHub로 할 수 있는 모든 것은 [GitHub 이슈 및 PR](/ko/github/)에 있습니다.
- **Claude Code** — Claude Pro 또는 Max 플랜, API 키 불필요
- **Cursor** — Cursor 플랜의 모델 한도
## Linear
## 통합 기능 설치
### 워크스페이스 연결하기
1. **Settings → Integrations**를 니다.
2. 통합 기능을 찾아 **Install**을 선택합니다.
3. 요청되면 OpenCode를 다시 시작합니다 — 재시작 후 공급자가 나타납니다.
4. **Set up**를 선택하고 로그인합니다. 그러면 채팅의 모델 선택기에 모델이 나타납니다.
1. **Linear** 카드를 펼치고 **Connect**를 선택합니다.
2. 열리는 브라우저 탭에서 접근을 승인합니다. 승인 전까지 카드에는 **Waiting for Linear**가 표시됩니다.
통합 기능은 사용자 단위로 설치되므로 모든 프로젝트에서 작동합니다. 같은 카드에서 언제든 업데이트하거나 제거할 수 있습니다.
다른 Linear 조직은 **Add workspace**로 연결합니다. 현재 워크스페이스는 한 번에 하나이며, **Switch to**로 전환하고 **Disconnect**는 현재 워크스페이스만 제거합니다. 프로젝트 매핑은 유지됩니다.
## Claude Code
### 이슈 찾아보기
Claude Code는 Claude Pro 또는 Max 플랜을 사용합니다 — API 키도 별도의 Claude 앱도 필요 없습니다.
워크스페이스가 연결되면 오른쪽 컨텍스트 레일에 **Linear** 패널이 나타납니다. 현재 워크스페이스의 이슈를 나열하며 다음을 할 수 있습니다.
1. 통합 기능을 설치합니다(위 참고).
2. **Set up**를 선택하고 로그인합니다. Claude Code CLI가 아직 없으면 설정에서 먼저 설치를 제안한 뒤 로그인을 진행합니다.
- 상태(**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), 담당자(**Anyone** 또는 **Assigned to me**), 팀, 우선순위로 필터링
- 제목, 식별자 또는 Linear URL로 검색
- 이슈를 열어 설명, 댓글, 라벨, 우선순위 확인
- **Status** 변경 또는 **Close issue** 선택
- 현재 **Workspace** 전환
Claude Code는 여기에서 유일하게 공급자 CLI 설치와 로그인을 필요로 하는 통합 기능입니다. Cursor는 CLI가 필요 없습니다.
### 이슈에서 세션 시작하기
**Claude 계정이 안전하게 유지되는 방식:** 이 통합 기능은 Anthropic의 공식 Claude Agent SDK와 설치된 Claude Code CLI를 사용합니다. OAuth 탈취, 브라우저 토큰 추출·재사용, 지원되지 않는 클라이언트로의 위장, Anthropic 인증 우회를 하지 않습니다. Anthropic이 지원하는 정상 경로를 사용하므로 토큰 탈취나 비인가 인증 우회에 따른 계정 정지 위험이 없습니다.
- Linear 패널에서 이슈를 열고 **Start session**을 선택합니다. 이슈를 스크롤해도 버튼은 하단에 남아 있습니다.
- 채팅에서 **New Session From Linear Issue**를 선택해 목록에서 고릅니다. 새 브랜치가 필요하면 **Create in worktree**를 사용합니다.
- **New Worktree** 대화상자에서 **Start from Linear Issue**를 선택합니다.
## Cursor
세션은 이슈의 팀에 매핑된 프로젝트에서 열리고, 이슈가 첫 프롬프트가 됩니다. 팀 매핑은 Linear 카드에서 합니다. **Default project**는 모든 팀에 적용되고 **Team projects**는 팀별로 이를 덮어씁니다. 매핑되지 않은 팀은 먼저 매핑하라고 요청합니다. 첫 메시지는 **Issue Review** 매직 프롬프트로 만들어지며 **설정 → Magic Prompts → Linear**에서 편집할 수 있습니다.
Cursor는 Cursor 플랜에 포함된 모델을 OpenChamber에서 사용할 수 있게 합니다.
### 이슈를 메시지에 연결하기
1. 통합 기능을 설치합니다(위 참고).
2. **Set up**를 선택하고 링크를 열어 브라우저에서 접근을 승인합니다. API 키는 필요 없습니다. 로그인 후 모델 목록이 자동으로 로드됩니다.
채팅 작성창에서 **Link Linear Issue**를 선택합니다. 이슈가 다음 메시지에 컨텍스트로 함께 전송되고, 세션의 작업 상태 패널에 링크가 남습니다.
## 업데이트 및 제거
### 세션 댓글
- **Update**는 플러그인의 최신 공개 버전을 설치합니다.
- **Remove**는 OpenCode 설정에서 플러그인을 삭제합니다. OpenCode가 다시 로드되면 공급자는 더 이상 로드되지 않습니다.
카드에 항목을 수동으로 관리해야 한다고 표시되면 **Manage plugins**를 선택해 중복 항목을 정리하세요.
Linear 카드에서 **Session comments**를 켜면 이슈에서 시작한 세션이 시작, 완료, 실패 시 해당 이슈에 댓글을 남기며, 각 댓글에는 세션을 여는 링크가 포함됩니다. 댓글은 이 OpenChamber 서버에 공개 주소가 있을 때만 게시되어 이슈의 모든 사람이 링크를 열 수 있습니다. 로컬이나 사설 주소에서는 아무것도 게시되지 않습니다.
## 관련 문서
- [공급자, 모델, 에이전트](/ko/providers/) — 다른 공급자 연결과 모델 선택
- [사용량 및 할당량](/ko/usage/) — 사용량 추적
- [GitHub 이슈 및 PR](/ko/github/) — OpenChamber에서 GitHub로 할 수 있는 모든 것
- [워크트리 세션](/ko/worktrees/) — 이슈 세션을 시작할 수 있는 곳
- [Magic Prompts](/ko/magic-prompts/) — Linear 세션이 시작하는 프롬프트 편집
+1 -1
View File
@@ -45,6 +45,6 @@ OpenChamber가 무언가를 하려면 먼저 최소한 하나의 AI 공급자가
## 관련 항목
- [통합 기능](/ko/integrations/) — Claude 또는 Cursor 구독을 공급자로 사용
- [통합 기능](/ko/integrations/) — GitHub와 Linear 연결
- [MCP Servers](/ko/mcp/) — 에이전트에 추가 도구를 제공합니다
- [Usage & Quotas](/ko/usage/) — 사용량을 추적합니다
+7 -3
View File
@@ -9,11 +9,11 @@ Połącz swoje konto GitHub, a OpenChamber może pobierać issues i pull request
## Połącz GitHub
1. Otwórz **Settings → Git**.
2. W sekcji GitHub wybierz **Connect**. OpenChamber pokazuje link i krótki kod.
1. Otwórz **Settings → Integrations** i rozwiń kartę **GitHub**.
2. Wybierz **Connect GitHub**. OpenChamber pokazuje link i krótki kod.
3. Otwórz link, wpisz kod i zatwierdź.
Po połączeniu Twoje konto pojawia się w sekcji GitHub. Możesz połączyć więcej niż jedno konto i przełączać się między nimi albo rozłączyć w dowolnym momencie.
Po połączeniu Twoje konto pojawia się na karcie. Możesz połączyć więcej niż jedno konto i przełączać się między nimi albo rozłączyć w dowolnym momencie. Jeśli CLI `gh` jest zalogowane na tej samej maszynie, OpenChamber może użyć go jako zapasowego źródła.
## Rozpocznij pracę od issue lub PR
@@ -28,6 +28,10 @@ To wprowadza Cię prosto do sesji z już wczytanym kontekstem.
Z zakładki **PR** w [widoku git](/pl/git/) możesz utworzyć pull request, zaktualizować go, oznaczyć szkic jako gotowy lub scalić go. OpenChamber może wygenerować tytuł i opis PR na podstawie Twoich zmian.
## Dołącz issue lub PR do wiadomości
W polu czatu wybierz **Link GitHub Issue** lub **Link GitHub PR**. Issue, albo PR razem z jego diffem, trafia jako kontekst do Twojej następnej wiadomości, a panel statusu pracy sesji zachowuje do niego link. Ten sam selektor może rozpocząć nową sesję z issue jako pierwszym promptem.
## Powiązane
- [Przepływy Git i GitHub](/pl/git/) — commituj i zarządzaj gałęziami
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Integracje
description: Używaj subskrypcji Claude lub Cursor jako dostawcy.
description: Połącz GitHub i Linear z OpenChamber.
---
# Integracje
Integracja to mała wtyczka, która dodaje dostawcę do OpenChamber na podstawie subskrypcji, którą już masz. Zarządzasz nimi w **Settings → Integrations**.
W **Ustawienia → Integracje** logujesz się do usług, z którymi pracuje OpenChamber. Logowanie jest zapisywane na serwerze OpenChamber, więc web, desktop i sparowany telefon korzystają z niego wspólnie.
> **Funkcja eksperymentalna.** Staramy się przestrzegać zasad dostawców, ale ograniczenia i zawieszenia kont pozostają decyzją każdego dostawcy. Używaj integracji na własne ryzyko.
## GitHub
Dostępne integracje:
Rozwiń kartę **GitHub** i wybierz **Connect GitHub**, aby zalogować się krótkim kodem urządzenia. Po połączeniu OpenChamber może rozpoczynać sesje z issues i pull requestów, dołączać je do wiadomości oraz otwierać i aktualizować PR-y. Wszystko, co potrafi GitHub, opisuje strona [Issues i PR na GitHub](/pl/github/).
- **Claude Code** — Twój plan Claude Pro lub Max, bez kluczy API
- **Cursor** — limity modeli z Twojego planu Cursor
## Linear
## Instalacja integracji
### Połącz przestrzeń roboczą
1. Otwórz **Settings → Integrations**.
2. Znajdź integrację i wybierz **Install**.
3. Uruchom OpenCode ponownie, gdy o to poproszą — dostawca pojawi się po restarcie.
4. Wybierz **Set up** i zaloguj się. Modele pojawią się potem w selektorze modeli na czacie.
1. Rozwiń kartę **Linear** i wybierz **Connect**.
2. Zatwierdź dostęp w karcie przeglądarki, która się otworzy. Do tego czasu karta pokazuje **Waiting for Linear**.
Integracje instalują się dla Twojego użytkownika, więc działają w każdym projekcie. W każdej chwili możesz je zaktualizować lub usunąć z tej samej karty.
Kolejną organizację Linear połączysz przez **Add workspace**. Bieżąca jest zawsze jedna przestrzeń: przełączaj przez **Switch to**, a **Disconnect** usuwa tylko bieżącą. Mapowanie projektów zostaje.
## Claude Code
### Przeglądaj issues
Claude Code korzysta z Twojego planu Claude Pro lub Max — bez kluczy API i bez osobnej aplikacji Claude.
Gdy przestrzeń robocza jest połączona, w prawym pasku kontekstu pojawia się panel **Linear**. Wyświetla issues bieżącej przestrzeni i pozwala:
1. Zainstaluj integrację (patrz wyżej).
2. Wybierz **Set up** i zaloguj się. Jeśli nie masz jeszcze Claude Code CLI, konfiguracja zaoferuje najpierw jego instalację, a potem logowanie.
- filtrować po statusie (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), osobie przypisanej (**Anyone** lub **Assigned to me**), zespole i priorytecie
- szukać po tytule, identyfikatorze lub adresie URL Linear
- otworzyć issue, aby przeczytać opis, komentarze, etykiety i priorytet
- zmienić jego **Status** lub wybrać **Close issue**
- przełączyć bieżący **Workspace**
Claude Code jest jedyną integracją tutaj, która wymaga zainstalowanego i zalogowanego CLI swojego dostawcy. Cursor nie wymaga swojego CLI.
### Rozpocznij sesję z issue
**Jak chronione jest Twoje konto Claude:** ta integracja używa oficjalnego Claude Agent SDK od Anthropic i Twojego zainstalowanego Claude Code CLI. Nie przechwytuje OAuth, nie wyodrębnia ani nie odtwarza tokenów przeglądarki, nie podszywa się pod nieobsługiwany klient i nie omija uwierzytelniania Anthropic. Działa na obsługiwanej przez Anthropic ścieżce dostępu, więc nie niesie ryzyka zablokowania konta związanego z przechwytywaniem tokenów lub nieautoryzowanymi obejściami uwierzytelniania.
- W panelu Linear otwórz issue i wybierz **Start session**. Przycisk zostaje w stopce, gdy przewijasz issue.
- W czacie wybierz **New Session From Linear Issue**, aby wybrać z listy, z opcją **Create in worktree**, jeśli chcesz świeżej gałęzi.
- W oknie **New Worktree** wybierz **Start from Linear Issue**.
## Cursor
Sesja otwiera się w projekcie zmapowanym do zespołu issue, a issue staje się pierwszym promptem. Zespoły mapujesz na karcie Linear: **Default project** obejmuje wszystkie zespoły, a **Team projects** nadpisuje go dla poszczególnych. Niezmapowany zespół najpierw poprosi o mapowanie. Pierwsza wiadomość powstaje z magic promptu **Issue Review**, który edytujesz w **Ustawienia → Magic Prompts → Linear**.
Cursor udostępnia w OpenChamber modele zawarte w Twoim planie Cursor.
### Dołącz issue do wiadomości
1. Zainstaluj integrację (patrz wyżej).
2. Wybierz **Set up**, otwórz link i zatwierdź dostęp w przeglądarce. Klucz API nie jest potrzebny. Lista modeli wczyta się automatycznie po zalogowaniu.
W polu czatu wybierz **Link Linear Issue**. Issue trafia jako kontekst do Twojej następnej wiadomości, a panel statusu pracy sesji zachowuje do niego link.
## Aktualizacja i usuwanie
### Komentarze sesji
- **Update** instaluje najnowszą opublikowaną wersję wtyczki.
- **Remove** usuwa wtyczkę z konfiguracji OpenCode. Dostawca przestanie się ładować po odświeżeniu OpenCode.
Jeśli karta wskazuje, że wpisy wymagają ręcznego zarządzania, wybierz **Manage plugins** i wyczyść tam duplikaty.
Włącz **Session comments** na karcie Linear, a sesja rozpoczęta z issue doda na nim komentarz przy starcie, zakończeniu lub błędzie, każdy z linkiem otwierającym sesję. Komentarze są publikowane tylko wtedy, gdy ten serwer OpenChamber ma publiczny adres, aby link działał dla wszystkich w issue; przy adresie lokalnym lub prywatnym nic nie jest publikowane.
## Powiązane
- [Dostawcy, modele i agenci](/pl/providers/) — podłączanie innych dostawców i wybór modeli
- [Zużycie i limity](/pl/usage/) — śledź, ile wykorzystałeś
- [Issues i PR na GitHub](/pl/github/) — wszystko, co GitHub potrafi w OpenChamber
- [Sesje worktree](/pl/worktrees/) — gdzie mogą zaczynać się sesje z issue
- [Magic Prompts](/pl/magic-prompts/) — edytuj prompt, od którego zaczyna się sesja Linear
+1 -1
View File
@@ -45,6 +45,6 @@ Logowania dostawców są przechowywane przez OpenCode, a nie OpenChamber, więc
## Powiązane
- [Integracje](/pl/integrations/) — używaj subskrypcji Claude lub Cursor jako dostawcy
- [Integracje](/pl/integrations/) — połącz GitHub i Linear
- [Serwery MCP](/pl/mcp/) — dodaj agentom dodatkowe narzędzia
- [Zużycie i limity](/pl/usage/) — śledź, ile już wykorzystałeś
+1 -1
View File
@@ -57,6 +57,6 @@ Provider sign-ins are stored by OpenCode, not OpenChamber, so they're shared wit
## Related
- [Integrations](/integrations/) — use a Claude or Cursor subscription as a provider
- [Integrations](/integrations/) — connect GitHub and Linear
- [MCP Servers](/mcp/) — add extra tools for agents
- [Usage & Quotas](/usage/) — track how much you've used
+7 -3
View File
@@ -9,11 +9,11 @@ Conecte sua conta do GitHub e o OpenChamber pode trazer issues e pull requests,
## Conectar o GitHub
1. Abra **Settings → Git**.
2. Em GitHub, escolha **Connect**. O OpenChamber mostra um link e um código curto.
1. Abra **Settings → Integrations** e expanda o cartão **GitHub**.
2. Escolha **Connect GitHub**. O OpenChamber mostra um link e um código curto.
3. Abra o link, insira o código e aprove.
Quando estiver conectado, sua conta aparece na seção do GitHub. Você pode conectar mais de uma conta e alternar entre elas, ou desconectar a qualquer momento.
Quando estiver conectado, sua conta aparece no cartão. Você pode conectar mais de uma conta e alternar entre elas, ou desconectar a qualquer momento. Se a CLI `gh` estiver logada na mesma máquina, o OpenChamber pode usá-la como alternativa.
## Começar o trabalho a partir de uma issue ou PR
@@ -28,6 +28,10 @@ Isso o coloca direto em uma sessão com o contexto já carregado.
Pela aba **PR** na [visão de git](/pt-br/git/), você pode criar um pull request, atualizá-lo, marcar um rascunho como pronto ou fazer merge. O OpenChamber pode gerar o título e a descrição do PR a partir das suas mudanças.
## Vincule uma issue ou PR a uma mensagem
No compositor do chat, escolha **Link GitHub Issue** ou **Link GitHub PR**. A issue, ou o PR com seu diff, acompanha sua próxima mensagem como contexto, e o painel de status de trabalho da sessão mantém um link para ela. O mesmo seletor pode iniciar uma nova sessão com a issue como primeiro prompt.
## Relacionado
- [Fluxos de Git e GitHub](/pt-br/git/) — faça commit e gerencie branches
@@ -1,54 +1,53 @@
---
title: Integrações
description: Use sua assinatura Claude ou Cursor como provedor.
description: Conecte o GitHub e o Linear ao OpenChamber.
---
# Integrações
Uma integração é um pequeno plugin que adiciona um provedor ao OpenChamber usando uma assinatura que você já tem. Você as gerencia em **Settings → Integrations**.
Em **Configurações → Integrações** você entra nos serviços com os quais o OpenChamber trabalha. O login fica salvo no servidor do OpenChamber, então web, desktop e um telefone pareado o compartilham.
> **Recurso experimental.** Buscamos respeitar as políticas dos provedores, mas restrições e suspensões de conta continuam sendo decisão de cada provedor. Use as integrações por sua conta e risco.
## GitHub
Integrações disponíveis:
Expanda o cartão **GitHub** e escolha **Connect GitHub** para entrar com um código curto de dispositivo. Conectado, o OpenChamber pode iniciar sessões a partir de issues e pull requests, anexá-los a mensagens e abrir ou atualizar PRs. Tudo o que o GitHub pode fazer está em [Issues e PRs do GitHub](/pt-br/github/).
- **Claude Code** — seu plano Claude Pro ou Max, sem chaves de API
- **Cursor** — os limites de modelos do seu plano Cursor
## Linear
## Instalar uma integração
### Conecte um workspace
1. Abra **Settings → Integrations**.
2. Encontre a integração e escolha **Install**.
3. Reinicie o OpenCode quando solicitado — o provedor aparece após a reinicialização.
4. Escolha **Set up** e faça login. Os modelos aparecem então no seletor de modelos do chat.
1. Expanda o cartão **Linear** e escolha **Connect**.
2. Aprove o acesso na aba do navegador que se abre. Até lá, o cartão mostra **Waiting for Linear**.
As integrações são instaladas para o seu usuário, então funcionam em todos os projetos. Você pode atualizá-las ou removê-las do mesmo cartão a qualquer momento.
Conecte outra organização do Linear com **Add workspace**. Só um workspace é o atual por vez: troque com **Switch to**, e **Disconnect** remove apenas o atual. O mapeamento de projetos é mantido.
## Claude Code
### Navegue pelas issues
O Claude Code usa seu plano Claude Pro ou Max — sem chaves de API e sem um app Claude separado.
Com um workspace conectado, o painel **Linear** aparece na barra de contexto à direita. Ele lista as issues do workspace atual e permite:
1. Instale a integração (acima).
2. Escolha **Set up** e faça login. Se você ainda não tem a CLI do Claude Code, a configuração oferece instalá-la primeiro e depois fazer login.
- filtrar por status (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), responsável (**Anyone** ou **Assigned to me**), time e prioridade
- buscar por título, identificador ou URL do Linear
- abrir uma issue para ler descrição, comentários, labels e prioridade
- mudar o **Status** ou escolher **Close issue**
- trocar o **Workspace** atual
O Claude Code é a única integração aqui que exige que a CLI do provedor esteja instalada e autenticada. Cursor não exige sua CLI.
### Inicie uma sessão a partir de uma issue
**Como sua conta Claude fica protegida:** esta integração usa o Claude Agent SDK oficial da Anthropic e a CLI do Claude Code instalada em sua máquina. Ela não sequestra OAuth, não extrai nem reproduz tokens do navegador, não se passa por um cliente não suportado e não contorna a autenticação da Anthropic. Ela permanece no caminho de acesso suportado pela Anthropic, portanto não traz o risco de banimento de conta associado a sequestro de tokens ou a contornos de autenticação não autorizados.
- No painel do Linear, abra uma issue e escolha **Start session**. O botão fica no rodapé enquanto a issue rola.
- No chat, escolha **New Session From Linear Issue** para escolher uma da lista, com **Create in worktree** se quiser um branch novo.
- Na caixa de diálogo **New Worktree**, escolha **Start from Linear Issue**.
## Cursor
A sessão abre no projeto mapeado para o time da issue, com a issue como primeiro prompt. Mapeie os times no cartão do Linear: **Default project** cobre todos os times e **Team projects** o sobrescreve por time. Um time sem mapeamento pede que você o mapeie primeiro. A primeira mensagem é montada a partir do magic prompt **Issue Review**, editável em **Configurações → Magic Prompts → Linear**.
O Cursor torna disponíveis no OpenChamber os modelos incluídos no seu plano Cursor.
### Vincule uma issue a uma mensagem
1. Instale a integração (acima).
2. Escolha **Set up**, abra o link e autorize o acesso no navegador. Nenhuma chave de API é necessária. A lista de modelos carrega automaticamente após o login.
No compositor do chat, escolha **Link Linear Issue**. A issue acompanha sua próxima mensagem como contexto, e o painel de status de trabalho da sessão mantém um link para ela.
## Atualizar ou remover
### Comentários de sessão
- **Update** instala a versão publicada mais recente do plugin.
- **Remove** exclui o plugin da sua configuração do OpenCode. O provedor deixa de ser carregado quando o OpenCode é recarregado.
Se um cartão indicar que as entradas precisam de gerenciamento manual, escolha **Manage plugins** e limpe as duplicatas lá.
Ative **Session comments** no cartão do Linear e uma sessão iniciada a partir de uma issue publica um comentário nela ao começar, terminar ou falhar, cada um com um link que abre a sessão. Os comentários só são publicados quando este servidor do OpenChamber tem um endereço público, para que o link funcione para todos na issue; em um endereço local ou privado nada é publicado.
## Relacionado
- [Provedores, modelos e agentes](/pt-br/providers/) — conecte outros provedores e escolha modelos
- [Uso e cotas](/pt-br/usage/) — acompanhe quanto você usou
- [Issues e PRs do GitHub](/pt-br/github/) — tudo o que o GitHub pode fazer no OpenChamber
- [Sessões em worktree](/pt-br/worktrees/) — onde as sessões a partir de issues podem começar
- [Magic Prompts](/pt-br/magic-prompts/) — edite o prompt com que uma sessão do Linear começa
@@ -45,6 +45,6 @@ Os logins de provedores são armazenados pelo OpenCode, não pelo OpenChamber, e
## Relacionado
- [Integrações](/pt-br/integrations/) — use uma assinatura Claude ou Cursor como provedor
- [Integrações](/pt-br/integrations/) — conecte o GitHub e o Linear
- [Servidores MCP](/pt-br/mcp/) — adicione ferramentas extras para os agentes
- [Uso e Cotas](/pt-br/usage/) — acompanhe quanto você já usou
+7 -3
View File
@@ -9,11 +9,11 @@ GitHub hesabınızı bağlayın. OpenChamber issue'ları ve pull request'leri i
## GitHub'ı bağlayın
1. **Settings → Git** bölümünü açın.
2. GitHub altında **Connect** seçin. OpenChamber bir bağlantı ve kısa bir kod gösterir.
1. **Settings → Integrations** bölümünü açın ve **GitHub** kartını genişletin.
2. **Connect GitHub** seçin. OpenChamber bir bağlantı ve kısa bir kod gösterir.
3. Bağlantıyı açın, kodu girin ve onaylayın.
Bağlantı kurulunca hesabınız GitHub bölümünde görünür. Birden fazla hesap bağlayabilir, aralarında geçiş yapabilir ya da istediğiniz zaman bağlantıyı kesebilirsiniz.
Bağlantı kurulunca hesabınız kartta görünür. Birden fazla hesap bağlayabilir, aralarında geçiş yapabilir ya da istediğiniz zaman bağlantıyı kesebilirsiniz. Aynı makinede `gh` CLI ile giriş yapılmışsa OpenChamber onu yedek olarak kullanabilir.
## Bir issue veya PR'den işe başlayın
@@ -28,6 +28,10 @@ Bu sizi, bağlam zaten yüklenmiş halde doğrudan bir oturuma sokar.
[git view](/git/) içindeki **PR** sekmesinden pull request oluşturabilir, güncelleyebilir, taslağı hazır diye işaretleyebilir ya da merge edebilirsiniz. OpenChamber PR başlığını ve açıklamasını değişikliklerinizden oluşturabilir.
## Bir issue ya da PR'ı mesaja bağlayın
Sohbet yazma alanında **Link GitHub Issue** ya da **Link GitHub PR** seçin. Issue ya da diff'iyle birlikte PR, bir sonraki mesajınıza bağlam olarak eklenir ve oturumun çalışma durumu paneli ona bir bağlantı tutar. Aynı seçiciden, issue'yu ilk istem olarak kullanan yeni bir oturum da başlatabilirsiniz.
## İlgili
- [Git & GitHub Workflows](/git/) — branch'leri commit edin ve yönetin
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Entegrasyonlar
description: Claude ya da Cursor aboneliğinizi bir provider olarak kullanın.
description: GitHub ve Linear’ı OpenChambera bağlayın.
---
# Entegrasyonlar
Integration, sahip olduğunuz bir aboneliği kullanarak OpenChamber'a bir provider ekleyen küçük bir eklentidir. Bunları **Settings → Integrations** altında yönetirsiniz.
**Settings → Integrations**, OpenChamber’ın birlikte çalıştığı servislere giriş yaptığınız yerdir. Giriş OpenChamber sunucusunda saklanır; böylece web, masaüstü ve eşleştirilmiş telefon aynı girişi paylaşır.
> **Experimental feature.** Provider politikalarına uymaya çalışıyoruz, ama hesap kısıtlamaları ve askıya alma kararları yine her provider'ın kendi kararıdır. Integrations'ı kendi sorumluluğunuzda kullanın.
## GitHub
Kullanılabilir integrations:
**GitHub** kartını genişletin ve kısa bir cihaz koduyla giriş yapmak için **Connect GitHub** seçin. Bağlandıktan sonra OpenChamber issuelardan ve pull requestlerden oturum başlatabilir, onları mesajlara ekleyebilir ve PR açıp güncelleyebilir. GitHub’ın yapabildiği her şey [GitHub Issues & PRs](/tr/github/) sayfasında.
- **Claude Code** — Claude Pro ya da Max planınız, API anahtarı gerekmez
- **Cursor** — Cursor planınızın model limitleri
## Linear
## Bir entegrasyon kurun
### Çalışma alanı bağlayın
1. **Settings → Integrations** bölümünü açın.
2. Integration'ı bulun ve **Install** seçin.
3. İstenince OpenCode'u yeniden başlatın. Provider yeniden başlatmadan sonra görünür.
4. **Set up** seçin ve giriş yapın. Modeller sonra sohbet model seçicisinde görünür.
1. **Linear** kartını genişletin ve **Connect** seçin.
2. Açılan tarayıcı sekmesinde erişimi onaylayın. O zamana kadar kart **Waiting for Linear** gösterir.
Integration'lar kullanıcı düzeyinde kurulur, bu yüzden her projede çalışır. Aynı karttan istediğiniz zaman güncelleyebilir ya da kaldırabilirsiniz.
Başka bir Linear organizasyonunu **Add workspace** ile bağlayın. Aynı anda tek bir çalışma alanı geçerlidir: **Switch to** ile geçiş yapın; **Disconnect** yalnızca geçerli olanı kaldırır. Proje eşlemeniz korunur.
## Claude Code
### Issuelara göz atın
Claude Code, Claude Pro ya da Max planınızı kullanır. API anahtarı yoktur ve ayrı bir Claude uygulaması gerekmez.
Bir çalışma alanı bağlandığında sağdaki bağlam çubuğunda **Linear** paneli belirir. Geçerli çalışma alanının issuelarını listeler ve şunları yapmanızı sağlar:
1. Integration'ı kurun. Yukarıya bakın.
2. **Set up** seçin ve giriş yapın. Henüz Claude Code CLI'nız yoksa kurulum önce onu yüklemeyi önerir, sonra giriş yaptırır.
- duruma (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), atanan kişiye (**Anyone** ya da **Assigned to me**), takıma ve önceliğe göre filtreleme
- başlık, tanımlayıcı ya da Linear URLsiyle arama
- bir issueyu açıp açıklamasını, yorumlarını, etiketlerini ve önceliğini okuma
- **Status** değiştirme ya da **Close issue** seçme
- geçerli **Workspace**i değiştirme
Claude Code, burada provider CLI'sının kurulu ve giriş yapılmış olmasını gerektiren tek integration'dır. Cursor CLI gerektirmez.
### Bir issuedan oturum başlatın
**Claude hesabınız nasıl güvende kalır:** Bu integration, Anthropic'in resmi Claude Agent SDK'sını ve kurulu Claude Code CLI'nızı kullanır. OAuth'u kaçırmaz, tarayıcı token'larını çıkarmaz ya da yeniden oynatmaz, desteklenmeyen bir istemciyi taklit etmez ve Anthropic'in kimlik doğrulama akışını atlamaz. Anthropic'in desteklediği erişim yolunda kalır. Bu yüzden token kaçırma ya da yetkisiz kimlik doğrulama kestirmelerinin hesap banı riskini taşımaz.
- Linear panelinde bir issue açın ve **Start session** seçin. Issue kaydırılırken düğme alt kısımda kalır.
- Sohbette listeden seçmek için **New Session From Linear Issue** seçin; yeni bir dal istiyorsanız **Create in worktree** kullanın.
- **New Worktree** iletişim kutusunda **Start from Linear Issue** seçin.
## Cursor
Oturum, issuenun takımına eşlenen projede açılır ve issue ilk istem olur. Takımları Linear kartında eşleyin: **Default project** tüm takımları kapsar, **Team projects** takım bazında bunu geçersiz kılar. Eşlenmemiş bir takım için önce eşleme yapmanız istenir. İlk mesaj **Issue Review** magic promptundan oluşturulur; bunu **Settings → Magic Prompts → Linear** altında düzenleyebilirsiniz.
Cursor, Cursor planınıza dahil modelleri OpenChamber'da kullanılabilir hale getirir.
### Bir issueyu mesaja bağlayın
1. Integration'ı kurun. Yukarıya bakın.
2. **Set up** seçin, bağlantıyı açın ve tarayıcınızda erişimi onaylayın. API anahtarı gerekmez. Giriş yaptıktan sonra model listesi otomatik yüklenir.
Sohbet yazma alanında **Link Linear Issue** seçin. Issue, bir sonraki mesajınıza bağlam olarak eklenir ve oturumun çalışma durumu paneli ona bir bağlantı tutar.
## Güncelleme ya da kaldırma
### Oturum yorumları
- **Update** eklentinin en son yayımlanmış sürümünü kurar.
- **Remove** eklentiyi OpenCode config'inizden siler. OpenCode yenilendikten sonra provider yüklenmeyi bırakır.
Bir kartta girdilerin elle yönetilmesi gerektiği yazıyorsa, **Manage plugins** seçin ve kopyaları orada temizleyin.
Linear kartında **Session comments** açın; bir issuedan başlatılan oturum başladığında, bittiğinde ya da başarısız olduğunda o issueya oturumu açan bir bağlantıyla yorum bırakır. Yorumlar yalnızca bu OpenChamber sunucusunun herkese açık bir adresi olduğunda gönderilir; böylece bağlantı issuedaki herkes için çalışır. Yerel ya da özel bir adreste hiçbir şey gönderilmez.
## İlgili
- [Providers, Models & Agents](/providers/) — diğer provider'ları bağlayın ve model seçin
- [Usage & Quotas](/usage/) — ne kadar kullandığınızı izleyin
- [GitHub Issues & PRs](/tr/github/) — GitHub’ın OpenChamberda yapabildiği her şey
- [Worktree oturumları](/tr/worktrees/) — issue oturumlarının başlayabileceği yer
- [Magic Prompts](/tr/magic-prompts/) — bir Linear oturumunun başladığı istemi düzenleyin
+1 -1
View File
@@ -57,6 +57,6 @@ Sağlayıcı oturum açmaları OpenChamber'da değil OpenCode'da saklanır. Bu y
## İlgili
- [Integrations](/integrations/) — Claude veya Cursor aboneliğini sağlayıcı olarak kullanın
- [Integrations](/integrations/) — GitHub ve Linear’ı bağlayın
- [MCP Servers](/mcp/) — aracılar için ek araçlar ekleyin
- [Usage & Quotas](/usage/) — ne kadar kullandığınızı izleyin
+7 -3
View File
@@ -9,11 +9,11 @@ description: Підключіть GitHub і починайте сесії з iss
## Підключення GitHub
1. Відкрийте **Settings → Git**.
2. Під GitHub виберіть **Connect**. OpenChamber покаже посилання й короткий код.
1. Відкрийте **Settings → Integrations** і розгорніть картку **GitHub**.
2. Виберіть **Connect GitHub**. OpenChamber покаже посилання й короткий код.
3. Відкрийте посилання, уведіть код і підтвердьте.
Коли підключення виконано, ваш акаунт показується в розділі GitHub. Ви можете підключити більше одного акаунта й перемикатися між ними або відключитися будь-коли.
Коли підключення виконано, ваш акаунт показується на картці. Ви можете підключити більше одного акаунта й перемикатися між ними або відключитися будь-коли. Якщо на цій самій машині виконано вхід у `gh` CLI, OpenChamber може використати його як запасний варіант.
## Початок роботи з issue чи PR
@@ -28,6 +28,10 @@ description: Підключіть GitHub і починайте сесії з iss
З вкладки **PR** у [вигляді git](/uk/git/) ви можете створити pull request, оновити його, позначити чернетку готовою чи злити її. OpenChamber може згенерувати заголовок та опис PR з ваших змін.
## Прикріплення issue чи PR до повідомлення
У полі вводу чату виберіть **Link GitHub Issue** або **Link GitHub PR**. Issue, або PR разом із його diff, піде як контекст із вашим наступним повідомленням, а панель статусу роботи сесії збереже посилання на нього. Через той самий вибір можна почати нову сесію з issue як першим промптом.
## Пов'язане
- [Робочі процеси Git і GitHub](/uk/git/) — комітьте та керуйте гілками
+28 -29
View File
@@ -1,54 +1,53 @@
---
title: Інтеграції
description: Використовуйте підписки Claude або Cursor як провайдерів.
description: Підключіть GitHub і Linear до OpenChamber.
---
# Інтеграції
Інтеграція — це невеликий плагін, що додає провайдера до OpenChamber на основі підписки, яка в вас уже є. Керувати ними можна в **Settings → Integrations**.
У **Settings → Integrations** ви входите в сервіси, з якими працює OpenChamber. Вхід зберігається на сервері OpenChamber, тож веб, десктоп і спарений телефон користуються ним спільно.
> **Експериментальна функція.** Ми прагнемо дотримуватися політик провайдерів, але обмеження та блокування облікових записів залишаються рішенням кожного провайдера. Використовуйте інтеграції на власний ризик.
## GitHub
Доступні інтеграції:
Розгорніть картку **GitHub** і виберіть **Connect GitHub**, щоб увійти за коротким кодом пристрою. Після підключення OpenChamber може починати сесії з issue та pull request-ів, прикріплювати їх до повідомлень і відкривати чи оновлювати PR. Усе, що вміє GitHub, описано на сторінці [GitHub Issues та PR](/uk/github/).
- **Claude Code** — ваша підписка Claude Pro або Max, без API-ключів
- **Cursor** — ліміти моделей вашої підписки Cursor
## Linear
## Встановлення інтеграції
### Підключення робочого простору
1. Відкрийте **Settings → Integrations**.
2. Знайдіть інтеграцію та натисніть **Install**.
3. Перезапустіть OpenCode, коли про це попросять, — провайдер з'явиться після перезапуску.
4. Натисніть **Set up** і увійдіть. Після цього моделі з'являться в перемикачі моделей у чаті.
1. Розгорніть картку **Linear** і виберіть **Connect**.
2. Підтвердьте доступ у вкладці браузера, що відкриється. Доти картка показує **Waiting for Linear**.
Інтеграції встановлюються для вашого користувача, тож працюють у всіх проєктах. Оновити або видалити їх можна в будь-який момент з тієї ж карточки.
Іншу організацію Linear підключайте через **Add workspace**. Поточним є один робочий простір: перемикайтеся через **Switch to**, а **Disconnect** відключає лише поточний. Зіставлення проєктів зберігається.
## Claude Code
### Перегляд issues
Claude Code використовує вашу підписку Claude Pro або Max — без API-ключів і без окремого застосунку Claude.
Щойно робочий простір підключено, у правій панелі контексту з'являється розділ **Linear**. Він показує issues поточного простору й дозволяє:
1. Встановіть інтеграцію (вище).
2. Натисніть **Set up** і увійдіть. Якщо у вас ще немає Claude Code CLI, програма встановлення спершу запропонує його встановити, а потім виконає вхід.
- фільтрувати за статусом (**Backlog**, **To Do**, **In Progress**, **In Review**, **Done**, **Canceled**, **Duplicate**), виконавцем (**Anyone** або **Assigned to me**), командою та пріоритетом
- шукати за назвою, ідентифікатором або посиланням Linear
- відкрити issue, щоб прочитати опис, коментарі, мітки та пріоритет
- змінити її **Status** або натиснути **Close issue**
- перемкнути поточний **Workspace**
Claude Code — єдина інтеграція тут, яка вимагає встановленого та залогіненого CLI свого провайдера. Для Cursor CLI не потрібен.
### Сесія з issue
**Як захищається ваш обліковий запис Claude:** ця інтеграція використовує офіційний Claude Agent SDK від Anthropic і ваш встановлений Claude Code CLI. Вона не перехоплює OAuth, не витягує й не відтворює браузерні токени, не видає себе за непідтримуваний клієнт і не обходить процес автентифікації Anthropic. Усе працює через підтримуваний Anthropic шлях доступу, тож інтеграція не несе ризику блокування облікового запису, пов'язаного з перехопленням токенів або несанкціонованими способами автентифікації.
- У панелі Linear відкрийте issue й натисніть **Start session**. Кнопка лишається внизу, поки issue прокручується.
- У чаті виберіть **New Session From Linear Issue**, щоб вибрати зі списку, з опцією **Create in worktree**, якщо потрібна окрема гілка.
- У діалозі **New Worktree** виберіть **Start from Linear Issue**.
## Cursor
Сесія відкривається в проєкті, зіставленому з командою issue, а сама issue стає першим промптом. Команди зіставляються в картці Linear: **Default project** діє для всіх команд, **Team projects** перевизначає його для окремих. Для незіставленої команди спершу попросять вибрати проєкт. Перше повідомлення будується з magic prompt **Issue Review**, який можна редагувати в **Settings → Magic Prompts → Linear**.
Cursor робить доступними в OpenChamber моделі, що входять у вашу підписку Cursor.
### Прикріплення issue до повідомлення
1. Встановіть інтеграцію (вище).
2. Натисніть **Set up**, відкрийте посилання та підтвердьте доступ у браузері. API-ключ не потрібен. Список моделей завантажиться автоматично після входу.
У полі вводу чату виберіть **Link Linear Issue**. Issue піде як контекст із вашим наступним повідомленням, а панель статусу роботи сесії збереже посилання на неї.
## Оновлення та видалення
### Коментарі про сесію
- **Update** встановлює найновішу опубліковану версію плагіна.
- **Remove** видаляє плагін із конфігурації OpenCode. Провайдер перестане завантажуватися після оновлення OpenCode.
Якщо карточка повідомляє, що записи потребують ручного керування, натисніть **Manage plugins** і приберіть дублікати там.
Увімкніть **Session comments** у картці Linear, і сесія, розпочата з issue, залишатиме на ній коментар на старті, після завершення чи в разі збою, кожен із посиланням, що відкриває сесію. Коментарі публікуються лише тоді, коли цей сервер OpenChamber має публічну адресу, щоб посилання працювало для всіх у issue; на локальній чи приватній адресі нічого не публікується.
## Пов'язане
- [Провайдери, моделі та агенти](/uk/providers/) — підключення інших провайдерів і вибір моделей
- [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили
- [GitHub Issues та PR](/uk/github/) — усе, що GitHub уміє в OpenChamber
- [Worktree-сесії](/uk/worktrees/) — де можуть починатися сесії з issue
- [Magic Prompts](/uk/magic-prompts/) — редагування промпту, з якого починається сесія з Linear
+1 -1
View File
@@ -45,6 +45,6 @@ description: Підключайте AI-провайдерів, обирайте
## Пов'язане
- [Інтеграції](/uk/integrations/) — використовуйте підписки Claude або Cursor як провайдерів
- [Інтеграції](/uk/integrations/) — підключіть GitHub і Linear
- [MCP Servers](/uk/mcp/) — додайте агентам додаткові інструменти
- [Використання та квоти](/uk/usage/) — відстежуйте, скільки ви витратили
+7 -3
View File
@@ -9,11 +9,11 @@ description: 连接 GitHub 并从 issue 和拉取请求开始会话。
## 连接 GitHub
1. 打开 **Settings → Git**
2. 在 GitHub 下,选择 **Connect**。OpenChamber 会显示一个链接和一个短码。
1. 打开 **Settings → Integrations**,展开 **GitHub** 卡片
2. 选择 **Connect GitHub**。OpenChamber 会显示一个链接和一个短码。
3. 打开链接,输入短码并批准。
连接后,你的账号会显示在 GitHub 部分下。你可以连接多个账号并在它们之间切换,或随时断开连接。
连接后,你的账号会显示在卡片上。你可以连接多个账号并在它们之间切换,或随时断开连接。如果同一台机器上已登录 `gh` CLI,OpenChamber 可以将其作为备用方式。
## 从 issue 或 PR 开始工作
@@ -28,6 +28,10 @@ description: 连接 GitHub 并从 issue 和拉取请求开始会话。
在 [git 视图](/zh-cn/git/) 的 **PR** 标签页中,你可以创建拉取请求、更新它、将草稿标记为就绪或合并它。OpenChamber 可以从你的变更生成 PR 标题和描述。
## 将 issue 或 PR 关联到消息
在聊天输入框中选择 **Link GitHub Issue** 或 **Link GitHub PR**。该 issue,或带有 diff 的 PR,会作为上下文随你的下一条消息一起发送,会话的工作状态面板会保留指向它的链接。同一个选择器也可以用该 issue 作为第一条提示来开始新会话。
## 相关内容
- [Git 与 GitHub 工作流](/zh-cn/git/) — 提交和管理分支
@@ -1,54 +1,53 @@
---
title: 集成
description: 将你的 Claude 或 Cursor 订阅用作提供商
description: 将 GitHub 和 Linear 连接到 OpenChamber
---
# 集成
集成是一个小型插件,它使用你已有的订阅为 OpenChamber 添加一个提供商。你可以在 **Settings → Integrations** 中管理它们
在 **设置 → 集成** 中登录 OpenChamber 所配合使用的服务。登录信息保存在 OpenChamber 服务器上,因此网页端、桌面端和已配对的手机共用同一份登录
> **实验性功能。**我们力求遵守提供商的政策,但帐户限制和暂停仍由各提供商决定。请自行承担使用集成的风险。
## GitHub
可用的集成:
展开 **GitHub** 卡片并选择 **Connect GitHub**,用一个简短的设备码登录。连接后,OpenChamber 可以从 issue 和拉取请求开始会话、将它们附加到消息,以及创建或更新 PR。GitHub 能做的一切见 [GitHub Issue 与 PR](/zh-cn/github/)。
- **Claude Code** — 你的 Claude Pro 或 Max 套餐,无需 API 密钥
- **Cursor** — 你的 Cursor 套餐的模型额度
## Linear
## 安装集成
### 连接工作区
1. 开 **Settings → Integrations**。
2. 找到所需的集成并选择 **Install**。
3. 在提示时重启 OpenCode — 重启后提供商就会出现。
4. 选择 **Set up** 并登录。之后模型会出现在聊天室的模型选择器中。
1. 开 **Linear** 卡片并选择 **Connect**。
2. 在打开的浏览器标签页中批准访问。在此之前,卡片显示 **Waiting for Linear**。
集成按用户安装,因此在所有项目中都可用。你可以随时在同一张卡片上更新或移除它们
用 **Add workspace** 连接另一个 Linear 组织。同一时间只有一个当前工作区:用 **Switch to** 切换,**Disconnect** 只移除当前工作区。项目映射会保留
## Claude Code
### 浏览 issue
Claude Code 使用你的 Claude Pro 或 Max 套餐 — 无需 API 密钥,也无需单独的 Claude 应用。
连接工作区后,右侧上下文栏会出现 **Linear** 面板。它列出当前工作区的 issue,你可以:
1. 安装集成(见上文)。
2. 选择 **Set up** 并登录。如果你还没有 Claude Code CLI,安装向导会先提供安装,然后再登录。
- 按状态(**Backlog**、**To Do**、**In Progress**、**In Review**、**Done**、**Canceled**、**Duplicate**)、负责人(**Anyone** 或 **Assigned to me**)、团队和优先级筛选
- 按标题、标识符或 Linear URL 搜索
- 打开 issue 查看描述、评论、标签和优先级
- 修改其 **Status** 或选择 **Close issue**
- 切换当前 **Workspace**
Claude Code 是这里唯一要求安装并登录其提供商 CLI 的集成。Cursor 不需要其 CLI。
### 从 issue 开始会话
**你的 Claude 账户如何受到保护:** 此集成使用 Anthropic 官方的 Claude Agent SDK 和你已安装的 Claude Code CLI。它不会劫持 OAuth,不会提取或重放浏览器令牌,不会冒充不受支持的客户端,也不会绕过 Anthropic 的身份验证。它始终运行在 Anthropic 支持的访问路径上,因此不会带来与令牌劫持或未授权身份验证变通手段相关的封号风险
- 在 Linear 面板中打开 issue 并选择 **Start session**。滚动 issue 时按钮始终停留在底部
- 在聊天中选择 **New Session From Linear Issue** 从列表中挑选;需要新分支时选择 **Create in worktree**。
- 在 **New Worktree** 对话框中选择 **Start from Linear Issue**。
## Cursor
会话会在映射到该 issue 所属团队的项目中打开,issue 作为第一条提示。在 Linear 卡片中映射团队:**Default project** 适用于所有团队,**Team projects** 可按团队覆盖。未映射的团队会先要求你完成映射。第一条消息由 **Issue Review** 魔法提示生成,可在 **设置 → Magic Prompts → Linear** 中编辑。
Cursor 让你的 Cursor 套餐中包含的模型可以在 OpenChamber 中使用。
### 将 issue 关联到消息
1. 安装集成(见上文)
2. 选择 **Set up**,打开链接并在浏览器中授权访问。无需 API 密钥。登录后模型列表会自动加载。
在聊天输入框中选择 **Link Linear Issue**。该 issue 会作为上下文随你的下一条消息一起发送,会话的工作状态面板会保留指向它的链接
## 更新或移除
### 会话评论
- **Update** 安装插件的最新发布版本
- **Remove** 从你的 OpenCode 配置中删除该插件。OpenCode 重新加载后,该提供商将不再加载。
如果卡片提示条目需要手动管理,请选择 **Manage plugins** 并在那里清理重复项。
在 Linear 卡片中开启 **Session comments**,从 issue 开始的会话会在开始、完成或失败时在该 issue 下发布评论,每条评论都带有打开会话的链接。只有当此 OpenChamber 服务器拥有公网地址时才会发布评论,这样 issue 中的每个人都能打开链接;在本地或私有地址下不会发布任何内容
## 相关内容
- [提供商、模型与智能体](/zh-cn/providers/) — 连接其他提供商并选择模型
- [用量与配额](/zh-cn/usage/) — 跟踪你的使用量
- [GitHub Issue 与 PR](/zh-cn/github/) — GitHub 在 OpenChamber 中能做的一切
- [工作树会话](/zh-cn/worktrees/) — issue 会话可以从哪里开始
- [Magic Prompts](/zh-cn/magic-prompts/) — 编辑 Linear 会话的起始提示
@@ -45,6 +45,6 @@ description: 连接 AI 提供商、选择模型并设置智能体。
## 相关内容
- [集成](/zh-cn/integrations/) — 将 Claude 或 Cursor 订阅用作提供商
- [集成](/zh-cn/integrations/) — 连接 GitHub 和 Linear
- [MCP Servers](/zh-cn/mcp/) — 为智能体添加额外工具
- [用量与配额](/zh-cn/usage/) — 跟踪你已使用的量
@@ -52,7 +52,6 @@ export const iconSpriteData = {
"checkbox-blank-circle-fill": `<path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="currentColor"/>`,
"checkbox-circle": `<path d="M4 12C4 7.58172 7.58172 4 12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12ZM12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM17.4571 9.45711L16.0429 8.04289L11 13.0858L8.20711 10.2929L6.79289 11.7071L11 15.9142L17.4571 9.45711Z" fill="currentColor"/>`,
"checkbox-multiple": `<path d="M6.99979 7V3C6.99979 2.44772 7.4475 2 7.99979 2H20.9998C21.5521 2 21.9998 2.44772 21.9998 3V16C21.9998 16.5523 21.5521 17 20.9998 17H17V20.9925C17 21.5489 16.551 22 15.9925 22H3.00728C2.45086 22 2 21.5511 2 20.9925L2.00276 8.00748C2.00288 7.45107 2.4518 7 3.01025 7H6.99979ZM8.99979 7H15.9927C16.549 7 17 7.44892 17 8.00748V15H19.9998V4H8.99979V7ZM15 9H4.00255L4.00021 20H15V9ZM8.50242 18L4.96689 14.4645L6.3811 13.0503L8.50242 15.1716L12.7451 10.9289L14.1593 12.3431L8.50242 18Z" fill="currentColor"/>`,
"claude-code": `<path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z" fill="currentColor"/>`,
"clipboard": `<path d="M7 4V2H17V4H20.0066C20.5552 4 21 4.44495 21 4.9934V21.0066C21 21.5552 20.5551 22 20.0066 22H3.9934C3.44476 22 3 21.5551 3 21.0066V4.9934C3 4.44476 3.44495 4 3.9934 4H7ZM7 6H5V20H19V6H17V8H7V6ZM9 4V6H15V4H9Z" fill="currentColor"/>`,
"close": `<path d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z" fill="currentColor"/>`,
"close-circle": `<path d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 10.5858L14.8284 7.75736L16.2426 9.17157L13.4142 12L16.2426 14.8284L14.8284 16.2426L12 13.4142L9.17157 16.2426L7.75736 14.8284L10.5858 12L7.75736 9.17157L9.17157 7.75736L12 10.5858Z" fill="currentColor"/>`,
@@ -69,7 +68,6 @@ export const iconSpriteData = {
"computer": `<path d="M4 16H20V5H4V16ZM13 18V20H17V22H7V20H11V18H2.9918C2.44405 18 2 17.5511 2 16.9925V4.00748C2 3.45107 2.45531 3 2.9918 3H21.0082C21.556 3 22 3.44892 22 4.00748V16.9925C22 17.5489 21.5447 18 21.0082 18H13Z" fill="currentColor"/>`,
"contract-up-down": `<path d="M5.79285 5.20718 12 11.4143 18.2071 5.20718 16.7928 3.79297 12 8.58586 7.20706 3.79297 5.79285 5.20718ZM18.2072 18.7928 12.0001 12.5857 5.793 18.7928 7.20721 20.207 12.0001 15.4141 16.793 20.207 18.2072 18.7928Z" fill="currentColor"/>`,
"corner-down-left": `<path d="M19.0001 13.9999L19.0002 5L17.0002 4.99997L17.0001 11.9999L6.8283 12L10.778 8.05024L9.36382 6.63603L2.99986 13L9.36382 19.364L10.778 17.9497L6.82826 14L19.0001 13.9999Z" fill="currentColor"/>`,
"cursor": `<path d="M11.503.131 1.891 5.678a.84.84 0 0 0-.42.726v11.188c0 .3.162.575.42.724l9.609 5.55a1 1 0 0 0 .998 0l9.61-5.55a.84.84 0 0 0 .42-.724V6.404a.84.84 0 0 0-.42-.726L12.497.131a1.01 1.01 0 0 0-.996 0M2.657 6.338h18.55c.263 0 .43.287.297.515L12.23 22.918c-.062.107-.229.064-.229-.06V12.335a.59.59 0 0 0-.295-.51l-9.11-5.257c-.109-.063-.064-.23.061-.23" fill="currentColor"/>`,
"database-2": `<path d="M5 12.5C5 12.8134 5.46101 13.3584 6.53047 13.8931C7.91405 14.5849 9.87677 15 12 15C14.1232 15 16.0859 14.5849 17.4695 13.8931C18.539 13.3584 19 12.8134 19 12.5V10.3287C17.35 11.3482 14.8273 12 12 12C9.17273 12 6.64996 11.3482 5 10.3287V12.5ZM19 15.3287C17.35 16.3482 14.8273 17 12 17C9.17273 17 6.64996 16.3482 5 15.3287V17.5C5 17.8134 5.46101 18.3584 6.53047 18.8931C7.91405 19.5849 9.87677 20 12 20C14.1232 20 16.0859 19.5849 17.4695 18.8931C18.539 18.3584 19 17.8134 19 17.5V15.3287ZM3 17.5V7.5C3 5.01472 7.02944 3 12 3C16.9706 3 21 5.01472 21 7.5V17.5C21 19.9853 16.9706 22 12 22C7.02944 22 3 19.9853 3 17.5ZM12 10C14.1232 10 16.0859 9.58492 17.4695 8.89313C18.539 8.3584 19 7.81342 19 7.5C19 7.18658 18.539 6.6416 17.4695 6.10687C16.0859 5.41508 14.1232 5 12 5C9.87677 5 7.91405 5.41508 6.53047 6.10687C5.46101 6.6416 5 7.18658 5 7.5C5 7.81342 5.46101 8.3584 6.53047 8.89313C7.91405 9.58492 9.87677 10 12 10Z" fill="currentColor"/>`,
"delete-bin": `<path d="M17 6H22V8H20V21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V8H2V6H7V3C7 2.44772 7.44772 2 8 2H16C16.5523 2 17 2.44772 17 3V6ZM18 8H6V20H18V8ZM9 11H11V17H9V11ZM13 11H15V17H13V11ZM9 4V6H15V4H9Z" fill="currentColor"/>`,
"discord-fill": `<path d="M19.3034 5.33716C17.9344 4.71103 16.4805 4.2547 14.9629 4C14.7719 4.32899 14.5596 4.77471 14.411 5.12492C12.7969 4.89144 11.1944 4.89144 9.60255 5.12492C9.45397 4.77471 9.2311 4.32899 9.05068 4C7.52251 4.2547 6.06861 4.71103 4.70915 5.33716C1.96053 9.39111 1.21766 13.3495 1.5891 17.2549C3.41443 18.5815 5.17612 19.388 6.90701 19.9187C7.33151 19.3456 7.71356 18.73 8.04255 18.0827C7.41641 17.8492 6.82211 17.5627 6.24904 17.2231C6.39762 17.117 6.5462 17.0003 6.68416 16.8835C10.1438 18.4648 13.8911 18.4648 17.3082 16.8835C17.4568 17.0003 17.5948 17.117 17.7434 17.2231C17.1703 17.5627 16.576 17.8492 15.9499 18.0827C16.2789 18.73 16.6609 19.3456 17.0854 19.9187C18.8152 19.388 20.5875 18.5815 22.4033 17.2549C22.8596 12.7341 21.6806 8.80747 19.3034 5.33716ZM8.5201 14.8459C7.48007 14.8459 6.63107 13.9014 6.63107 12.7447C6.63107 11.5879 7.45884 10.6434 8.5201 10.6434C9.57071 10.6434 10.4303 11.5879 10.4091 12.7447C10.4091 13.9014 9.57071 14.8459 8.5201 14.8459ZM15.4936 14.8459C14.4535 14.8459 13.6034 13.9014 13.6034 12.7447C13.6034 11.5879 14.4323 10.6434 15.4936 10.6434C16.5442 10.6434 17.4038 11.5879 17.3825 12.7447C17.3825 13.9014 16.5548 14.8459 15.4936 14.8459Z" fill="currentColor"/>`,
@@ -6,23 +6,13 @@ import { isVSCodeRuntime } from '@/lib/desktop';
import { getRegisteredRuntimeAPIs } from '@/contexts/runtimeAPIRegistry';
import { GitHubIntegration } from './GitHubIntegration';
import { LinearSettings } from './LinearSettings';
import { ThirdPartyIntegrationsSection } from './ThirdPartyIntegrationsSection';
interface IntegrationsPageProps {
onOpenProviderSetup: (providerId: string) => Promise<boolean>;
onOpenPluginManager: () => void;
}
export const IntegrationsPage: React.FC<IntegrationsPageProps> = ({
onOpenProviderSetup,
onOpenPluginManager,
}) => {
export const IntegrationsPage: React.FC = () => {
const { t } = useI18n();
// GitHub sign-in is an OpenChamber server feature; the VS Code extension
// uses the editor's own GitHub session instead.
const hasGitHub = !isVSCodeRuntime();
const hasLinear = Boolean(getRegisteredRuntimeAPIs()?.linear);
const hasBuiltIn = hasGitHub || hasLinear;
return (
<SettingsPageLayout
@@ -30,23 +20,16 @@ export const IntegrationsPage: React.FC<IntegrationsPageProps> = ({
description={t('settings.page.integrations.description')}
showSaveStatus
>
{hasBuiltIn ? (
<SettingsSection
title={t('settings.integrations.firstParty.title')}
info={t('settings.integrations.firstParty.info')}
divider={false}
settingsItem="integrations.first-party"
contentClassName="space-y-3"
>
{hasGitHub ? <GitHubIntegration /> : null}
{hasLinear ? <LinearSettings /> : null}
</SettingsSection>
) : null}
<ThirdPartyIntegrationsSection
divider={hasBuiltIn}
onOpenProviderSetup={onOpenProviderSetup}
onOpenPluginManager={onOpenPluginManager}
/>
<SettingsSection
title={t('settings.integrations.firstParty.title')}
info={t('settings.integrations.firstParty.info')}
divider={false}
settingsItem="integrations.first-party"
contentClassName="space-y-3"
>
{hasGitHub ? <GitHubIntegration /> : null}
{hasLinear ? <LinearSettings /> : null}
</SettingsSection>
</SettingsPageLayout>
);
};
@@ -1,448 +0,0 @@
import React from 'react';
import { useShallow } from 'zustand/react/shallow';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@/components/ui/dialog';
import { toast } from '@/components/ui';
import { Icon } from '@/components/icon/Icon';
import { SettingsSection } from '@/components/sections/shared/SettingsSection';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { useI18n } from '@/lib/i18n';
import { openExternalUrl } from '@/lib/url';
import { cn } from '@/lib/utils';
import {
usePluginsStore,
type PluginMutationResult,
} from '@/stores/usePluginsStore';
import { usePendingOpenCodeRestartStore } from '@/stores/usePendingOpenCodeRestartStore';
import {
getCatalogPluginPrimaryAction,
getCatalogPluginPresentation,
getCatalogPluginState,
getLatestNpmSpec,
THIRD_PARTY_PLUGINS,
type ThirdPartyPluginDefinition,
} from './thirdPartyPlugins';
type PendingAction = 'install' | 'update' | 'setup' | 'remove';
type RemoveTarget = ThirdPartyPluginDefinition | null;
interface ThirdPartyIntegrationsSectionProps {
divider?: boolean;
onOpenProviderSetup: (providerId: string) => Promise<boolean>;
onOpenPluginManager: () => void;
}
const requiresRestart = (result: PluginMutationResult): boolean =>
result.restartDeferred === true
|| result.requiresManualRestart === true
|| result.reloadFailed === true;
export const ThirdPartyIntegrationsSection: React.FC<ThirdPartyIntegrationsSectionProps> = ({
divider = true,
onOpenProviderSetup,
onOpenPluginManager,
}) => {
const { t } = useI18n();
const {
entries,
registryInfo,
loadPlugins,
loadRegistryInfo,
createEntry,
updateEntry,
deleteEntry,
} = usePluginsStore(
useShallow((state) => ({
entries: state.entries,
registryInfo: state.registryInfo,
loadPlugins: state.loadPlugins,
loadRegistryInfo: state.loadRegistryInfo,
createEntry: state.createEntry,
updateEntry: state.updateEntry,
deleteEntry: state.deleteEntry,
})),
);
const [registryLoadFailed, setRegistryLoadFailed] = React.useState(false);
const [pendingAction, setPendingAction] = React.useState<{
pluginId: string;
action: PendingAction;
} | null>(null);
const [restartRequiredIds, setRestartRequiredIds] = React.useState<ReadonlySet<string>>(
() => new Set(),
);
const [providerUnavailableIds, setProviderUnavailableIds] = React.useState<ReadonlySet<string>>(
() => new Set(),
);
const [removeTarget, setRemoveTarget] = React.useState<RemoveTarget>(null);
const [openPluginIds, setOpenPluginIds] = React.useState<ReadonlySet<string>>(() => new Set());
const refresh = React.useCallback(async () => {
const pluginsLoaded = await loadPlugins({ force: true });
if (!pluginsLoaded) {
setRegistryLoadFailed(true);
return;
}
const latestEntries = usePluginsStore.getState().entries;
const specs = new Set(THIRD_PARTY_PLUGINS.map((plugin) => plugin.packageName));
for (const entry of latestEntries) {
if (THIRD_PARTY_PLUGINS.some((plugin) => entry.spec === plugin.packageName || entry.spec.startsWith(`${plugin.packageName}@`))) {
specs.add(entry.spec);
}
}
const registryLoaded = await loadRegistryInfo({ specs: [...specs], force: true });
setRegistryLoadFailed(!registryLoaded);
}, [loadPlugins, loadRegistryInfo]);
React.useEffect(() => {
void refresh();
}, [refresh]);
const pendingPluginRestartCount = usePendingOpenCodeRestartStore(
(state) => state.changes.filter((change) => change.scope === 'plugins').length,
);
const isApplyingRestart = usePendingOpenCodeRestartStore((state) => state.isApplying);
const previousPluginRestartCountRef = React.useRef(pendingPluginRestartCount);
// When deferred plugin restarts are applied (pending plugins scope clears), drop
// local restart/unavailable flags and reload so statuses update immediately.
React.useEffect(() => {
const previousCount = previousPluginRestartCountRef.current;
previousPluginRestartCountRef.current = pendingPluginRestartCount;
if (isApplyingRestart) {
return;
}
if (previousCount <= 0 || pendingPluginRestartCount > 0) {
return;
}
setRestartRequiredIds(new Set());
setProviderUnavailableIds(new Set());
void refresh();
}, [isApplyingRestart, pendingPluginRestartCount, refresh]);
const setRestartRequired = React.useCallback((pluginId: string, required: boolean) => {
setRestartRequiredIds((current) => {
const next = new Set(current);
if (required) next.add(pluginId);
else next.delete(pluginId);
return next;
});
}, []);
const setProviderUnavailable = React.useCallback((pluginId: string, unavailable: boolean) => {
setProviderUnavailableIds((current) => {
const next = new Set(current);
if (unavailable) next.add(pluginId);
else next.delete(pluginId);
return next;
});
}, []);
const runMutation = React.useCallback(async (
plugin: ThirdPartyPluginDefinition,
action: Exclude<PendingAction, 'setup'>,
run: () => Promise<PluginMutationResult>,
) => {
setPendingAction({ pluginId: plugin.id, action });
try {
const result = await run();
if (!result.ok) {
toast.error(t('settings.integrations.thirdParty.toast.actionFailed'));
return;
}
setProviderUnavailable(plugin.id, false);
const restartNeeded = requiresRestart(result);
setRestartRequired(plugin.id, restartNeeded);
const toastOptions = restartNeeded
? { description: t('settings.integrations.thirdParty.toast.restartRequired') }
: undefined;
if (action === 'install') {
toast.success(t('settings.integrations.thirdParty.toast.installed', { name: t(plugin.nameKey) }), toastOptions);
} else if (action === 'update') {
toast.success(t('settings.integrations.thirdParty.toast.updated', { name: t(plugin.nameKey) }), toastOptions);
} else {
toast.success(t('settings.integrations.thirdParty.toast.removed', { name: t(plugin.nameKey) }), toastOptions);
}
await refresh();
} finally {
setPendingAction(null);
}
}, [refresh, setProviderUnavailable, setRestartRequired, t]);
const handlePrimaryAction = React.useCallback(async (plugin: ThirdPartyPluginDefinition) => {
const state = getCatalogPluginState(entries, plugin.packageName, registryInfo);
const action = getCatalogPluginPrimaryAction(state, plugin.packageName);
if (action === 'manage') {
onOpenPluginManager();
return;
}
if (action === 'setup') {
setPendingAction({ pluginId: plugin.id, action });
try {
const opened = await onOpenProviderSetup(plugin.providerId);
setProviderUnavailable(plugin.id, !opened);
if (!opened) {
toast.error(t('settings.integrations.thirdParty.toast.providerUnavailable'));
}
} finally {
setPendingAction(null);
}
return;
}
const latestSpec = getLatestNpmSpec(plugin.packageName, state.registry);
if (!latestSpec) {
setRegistryLoadFailed(true);
return;
}
if (action === 'install') {
await runMutation(plugin, 'install', () => createEntry({ spec: latestSpec, scope: 'user' }));
return;
}
if (state.userEntry) {
await runMutation(plugin, 'update', () => updateEntry(state.userEntry!.id, { spec: latestSpec }));
}
}, [createEntry, entries, onOpenPluginManager, onOpenProviderSetup, registryInfo, runMutation, setProviderUnavailable, t, updateEntry]);
const handleRemove = React.useCallback(async () => {
const plugin = removeTarget;
if (!plugin) return;
const state = getCatalogPluginState(entries, plugin.packageName, registryInfo);
if (!state.userEntry || state.userEntryIsAmbiguous) {
setRemoveTarget(null);
onOpenPluginManager();
return;
}
setRemoveTarget(null);
await runMutation(plugin, 'remove', () => deleteEntry(state.userEntry!.id));
}, [deleteEntry, entries, onOpenPluginManager, registryInfo, removeTarget, runMutation]);
const setPluginOpen = React.useCallback((pluginId: string, open: boolean) => {
setOpenPluginIds((current) => {
const next = new Set(current);
if (open) next.add(pluginId);
else next.delete(pluginId);
return next;
});
}, []);
const renderPlugin = (plugin: ThirdPartyPluginDefinition) => {
const state = getCatalogPluginState(entries, plugin.packageName, registryInfo);
const primaryAction = getCatalogPluginPrimaryAction(state, plugin.packageName);
const latestSpec = getLatestNpmSpec(plugin.packageName, state.registry);
const isPending = pendingAction?.pluginId === plugin.id;
const isRestartRequired = restartRequiredIds.has(plugin.id);
const isProviderUnavailable = providerUnavailableIds.has(plugin.id);
const registryUnavailable = registryLoadFailed || state.registry?.kind === 'npm-network';
const actionDisabled = isPending
|| isRestartRequired
|| ((primaryAction === 'install' || primaryAction === 'update') && (registryUnavailable || !latestSpec));
const presentation = getCatalogPluginPresentation(state, {
registryUnavailable,
restartRequired: isRestartRequired,
providerUnavailable: isProviderUnavailable,
});
let status: string;
switch (presentation.status) {
case 'installed-version':
status = presentation.latestVersion
? t('settings.integrations.thirdParty.status.installedVersion', {
version: presentation.latestVersion,
})
: t('settings.integrations.thirdParty.status.installed');
break;
case 'update-available':
status = presentation.latestVersion
? t('settings.integrations.thirdParty.status.updateAvailable', {
version: presentation.latestVersion,
})
: t('settings.integrations.thirdParty.status.unpinned');
break;
case 'not-installed':
status = t('settings.integrations.thirdParty.status.notInstalled');
break;
case 'installed':
status = t('settings.integrations.thirdParty.status.installed');
break;
case 'unpinned':
status = t('settings.integrations.thirdParty.status.unpinned');
break;
case 'ambiguous':
status = t('settings.integrations.thirdParty.status.ambiguous');
break;
case 'restart-required':
status = t('settings.integrations.thirdParty.status.restartRequired');
break;
case 'registry-unavailable':
status = t('settings.integrations.thirdParty.status.registryUnavailable');
break;
case 'provider-unavailable':
status = t('settings.integrations.thirdParty.status.providerUnavailable');
break;
}
const statusClassName = presentation.status === 'installed-version'
? 'bg-[var(--status-success)]/15 text-[var(--status-success)]'
: presentation.status === 'update-available'
|| presentation.status === 'ambiguous'
|| presentation.status === 'restart-required'
|| presentation.status === 'registry-unavailable'
|| presentation.status === 'provider-unavailable'
? 'bg-[var(--status-warning)]/15 text-[var(--status-warning)]'
: 'bg-[var(--surface-muted)] text-muted-foreground';
const primaryLabel = {
install: t('settings.integrations.thirdParty.actions.install'),
update: t('settings.integrations.thirdParty.actions.update'),
setup: t('settings.integrations.thirdParty.actions.setup'),
manage: t('settings.integrations.thirdParty.actions.managePlugins'),
}[primaryAction];
const open = openPluginIds.has(plugin.id);
return (
<Collapsible
key={plugin.id}
open={open}
onOpenChange={(nextOpen) => setPluginOpen(plugin.id, nextOpen)}
>
<div
data-settings-item={`integrations.third-party.${plugin.id}`}
className="overflow-hidden rounded-xl border border-[var(--interactive-border)] bg-[var(--surface-elevated)]"
>
<CollapsibleTrigger
className="flex w-full min-w-0 items-center gap-3 px-4 py-3 text-left hover:bg-[var(--interactive-hover)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--interactive-focus-ring)]"
>
<div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]">
<Icon name={plugin.icon} className={cn('size-5', plugin.brandClassName)} />
</div>
<div className="min-w-0 flex-1">
<div className="truncate text-sm font-semibold text-foreground">{t(plugin.nameKey)}</div>
<p className="mt-0.5 line-clamp-1 text-xs leading-snug text-muted-foreground">
{t(plugin.descriptionKey)}
</p>
</div>
<span
aria-live="polite"
className={cn(
'max-w-36 shrink-0 truncate rounded-full px-2 py-0.5 text-[10px] font-medium',
statusClassName,
)}
>
{status}
</span>
<Icon
name="arrow-down-s"
className={cn(
'size-4 shrink-0 text-muted-foreground transition-transform duration-150 ease-out motion-reduce:transition-none',
open && 'rotate-180',
)}
/>
</CollapsibleTrigger>
<CollapsibleContent className="border-t border-[var(--interactive-border)] px-4 py-4">
<div className="space-y-3">
{state.projectEntries.length > 0 ? (
<p className="text-xs text-muted-foreground">
{t('settings.integrations.thirdParty.status.projectInstalled')}
</p>
) : null}
<div className="flex flex-wrap items-center gap-2">
<Button
type="button"
size="sm"
variant={primaryAction === 'manage' ? 'outline' : 'default'}
onClick={() => void handlePrimaryAction(plugin)}
disabled={actionDisabled}
>
{isPending ? (
<Icon name="loader-4" className="size-3.5 animate-spin" />
) : primaryAction === 'setup' ? (
<Icon name="plug-2" className="size-3.5" />
) : null}
{primaryLabel}
</Button>
<Button
type="button"
size="sm"
variant="secondary"
onClick={() => void openExternalUrl(plugin.homepage)}
>
<Icon name="external-link" className="size-3.5" />
{t('settings.integrations.thirdParty.actions.docs')}
</Button>
{state.userEntry && !state.userEntryIsAmbiguous ? (
<Button
type="button"
size="sm"
variant="destructive"
onClick={() => setRemoveTarget(plugin)}
disabled={isPending}
>
<Icon name="delete-bin" className="size-3.5" />
{t('settings.integrations.thirdParty.actions.remove')}
</Button>
) : null}
</div>
</div>
</CollapsibleContent>
</div>
</Collapsible>
);
};
return (
<>
<SettingsSection
title={t('settings.integrations.thirdParty.title')}
info={t('settings.integrations.thirdParty.info')}
divider={divider}
settingsItem="integrations.third-party"
contentClassName="space-y-3"
>
<div role="alert" className="flex items-start gap-2 rounded-lg border border-[var(--status-warning-border)] bg-[var(--status-warning-background)] p-3">
<Icon name="error-warning" className="mt-0.5 size-4 shrink-0 text-[var(--status-warning)]" />
<p className="typography-meta text-[var(--status-warning)]">
{t('settings.integrations.experimentalWarning')}
</p>
</div>
{THIRD_PARTY_PLUGINS.map(renderPlugin)}
</SettingsSection>
<Dialog open={removeTarget !== null} onOpenChange={(open) => !open && setRemoveTarget(null)}>
<DialogContent className="max-w-md">
<DialogHeader>
<DialogTitle>{t('settings.integrations.thirdParty.dialog.remove.title')}</DialogTitle>
<DialogDescription>
{t('settings.integrations.thirdParty.dialog.remove.description', {
name: removeTarget ? t(removeTarget.nameKey) : '',
})}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button type="button" size="sm" variant="ghost" onClick={() => setRemoveTarget(null)}>
{t('settings.common.actions.cancel')}
</Button>
<Button type="button" size="sm" variant="destructive" onClick={() => void handleRemove()}>
{t('settings.integrations.thirdParty.actions.remove')}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
};
@@ -1,213 +0,0 @@
import { describe, expect, test } from 'bun:test';
import type { PluginEntry, RegistryResult } from '@/stores/usePluginsStore';
import * as thirdPartyCatalog from './thirdPartyPlugins';
import {
getCatalogPluginState,
getCatalogPluginPrimaryAction,
getLatestNpmSpec,
specMatchesPackage,
} from './thirdPartyPlugins';
type CatalogPresentationStatus =
| 'not-installed'
| 'installed'
| 'installed-version'
| 'update-available'
| 'unpinned'
| 'ambiguous'
| 'restart-required'
| 'registry-unavailable'
| 'provider-unavailable';
type GetCatalogPluginPresentation = (
state: ReturnType<typeof getCatalogPluginState>,
options?: {
registryUnavailable?: boolean;
restartRequired?: boolean;
providerUnavailable?: boolean;
},
) => {
status: CatalogPresentationStatus;
latestVersion: string | null;
};
const getCatalogPluginPresentation = (
thirdPartyCatalog as unknown as {
getCatalogPluginPresentation?: GetCatalogPluginPresentation;
}
).getCatalogPluginPresentation;
const claudePackage = '@openchamber/opencode-claude';
const entry = (spec: string, scope: PluginEntry['scope'] = 'user'): PluginEntry => ({
id: `config:${scope}:${spec}`,
spec,
scope,
kind: 'config',
parsedKind: 'npm',
});
const registry = (spec: string, currentVersion: string | null, latestVersion = '0.7.0'): RegistryResult => ({
kind: 'npm-ok',
spec,
name: claudePackage,
currentVersion,
latestVersion,
versions: ['0.6.0', latestVersion],
hasUpdate: currentVersion !== null && currentVersion !== latestVersion,
});
describe('third-party plugin catalog helpers', () => {
test('derives compact-card status with explicit transient-state priority', () => {
expect(typeof getCatalogPluginPresentation).toBe('function');
if (!getCatalogPluginPresentation) return;
const notInstalled = getCatalogPluginState([], claudePackage, {});
expect(getCatalogPluginPresentation(notInstalled)).toEqual({
status: 'not-installed',
latestVersion: null,
});
const current = getCatalogPluginState(
[entry(`${claudePackage}@0.7.0`)],
claudePackage,
{ [`${claudePackage}@0.7.0`]: registry(`${claudePackage}@0.7.0`, '0.7.0') },
);
expect(getCatalogPluginPresentation(current)).toEqual({
status: 'installed-version',
latestVersion: '0.7.0',
});
const outdated = getCatalogPluginState(
[entry(`${claudePackage}@0.6.0`)],
claudePackage,
{ [`${claudePackage}@0.6.0`]: registry(`${claudePackage}@0.6.0`, '0.6.0') },
);
expect(getCatalogPluginPresentation(outdated)).toEqual({
status: 'update-available',
latestVersion: '0.7.0',
});
expect(getCatalogPluginPresentation(outdated, { registryUnavailable: true })).toEqual({
status: 'registry-unavailable',
latestVersion: '0.7.0',
});
expect(getCatalogPluginPresentation(outdated, { providerUnavailable: true })).toEqual({
status: 'provider-unavailable',
latestVersion: '0.7.0',
});
expect(getCatalogPluginPresentation(outdated, {
providerUnavailable: true,
restartRequired: true,
})).toEqual({
status: 'restart-required',
latestVersion: '0.7.0',
});
const ambiguous = getCatalogPluginState(
[entry(claudePackage), entry(`${claudePackage}@0.6.0`)],
claudePackage,
{},
);
expect(getCatalogPluginPresentation(ambiguous)).toEqual({
status: 'ambiguous',
latestVersion: null,
});
});
test('matches only a package or its versioned spec', () => {
expect(specMatchesPackage(claudePackage, claudePackage)).toBe(true);
expect(specMatchesPackage(`${claudePackage}@0.6.0`, claudePackage)).toBe(true);
expect(specMatchesPackage('@openchamber/opencode-claude-extra@0.6.0', claudePackage)).toBe(false);
});
test('points catalog plugins at the OpenChamber GitHub and npm packages', () => {
expect(thirdPartyCatalog.THIRD_PARTY_PLUGINS.map((plugin) => ({
id: plugin.id,
packageName: plugin.packageName,
homepage: plugin.homepage,
}))).toEqual([
{
id: 'opencode-claude',
packageName: '@openchamber/opencode-claude',
homepage: 'https://github.com/openchamber/opencode-claude',
},
{
id: 'opencode-cursor-oauth',
packageName: '@openchamber/opencode-cursor',
homepage: 'https://github.com/openchamber/opencode-cursor',
},
]);
});
test('uses the configured user entry and its registry result', () => {
const installed = entry(`${claudePackage}@0.6.0`);
const state = getCatalogPluginState(
[installed],
claudePackage,
{ [installed.spec]: registry(installed.spec, '0.6.0') },
);
expect(state.userEntry).toEqual(installed);
expect(state.userEntryIsAmbiguous).toBe(false);
expect(state.projectEntries).toEqual([]);
expect(state.registry).toEqual(registry(installed.spec, '0.6.0'));
});
test('does not choose an entry when multiple user specs would make a mutation ambiguous', () => {
const state = getCatalogPluginState(
[entry(claudePackage), entry(`${claudePackage}@0.6.0`), entry(claudePackage, 'project')],
claudePackage,
{},
);
expect(state.userEntry).toBeNull();
expect(state.userEntryIsAmbiguous).toBe(true);
expect(state.projectEntries).toHaveLength(1);
});
test('returns an exact latest spec only from a valid npm registry result', () => {
expect(getLatestNpmSpec(claudePackage, registry(claudePackage, null))).toBe(`${claudePackage}@0.7.0`);
expect(getLatestNpmSpec(claudePackage, {
kind: 'npm-network',
spec: claudePackage,
error: 'offline',
})).toBeNull();
});
test('chooses an update for a bare or outdated user-wide entry', () => {
const bare = getCatalogPluginState(
[entry(claudePackage)],
claudePackage,
{ [claudePackage]: registry(claudePackage, null) },
);
const outdated = getCatalogPluginState(
[entry(`${claudePackage}@0.6.0`)],
claudePackage,
{ [`${claudePackage}@0.6.0`]: registry(`${claudePackage}@0.6.0`, '0.6.0') },
);
expect(getCatalogPluginPrimaryAction(bare, claudePackage)).toBe('update');
expect(getCatalogPluginPrimaryAction(outdated, claudePackage)).toBe('update');
});
test('keeps setup as the primary action once the exact latest spec is installed', () => {
const installed = entry(`${claudePackage}@0.7.0`);
const state = getCatalogPluginState(
[installed],
claudePackage,
{ [installed.spec]: registry(installed.spec, '0.7.0') },
);
expect(getCatalogPluginPrimaryAction(state, claudePackage)).toBe('setup');
});
test('sends ambiguous entries to manual plugin management', () => {
const state = getCatalogPluginState(
[entry(claudePackage), entry(`${claudePackage}@0.6.0`)],
claudePackage,
{},
);
expect(getCatalogPluginPrimaryAction(state, claudePackage)).toBe('manage');
});
});
@@ -1,156 +0,0 @@
import type { IconName } from '@/components/icon/icons';
import type { I18nKey } from '@/lib/i18n';
import type { PluginEntry, RegistryResult } from '@/stores/usePluginsStore';
export interface ThirdPartyPluginDefinition {
id: string;
packageName: string;
providerId: string;
icon: IconName;
/** Brand mark tint (e.g. Claude orange); neutral marks use text-foreground. */
brandClassName: string;
nameKey: I18nKey;
descriptionKey: I18nKey;
homepage: string;
}
export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [
{
id: 'opencode-claude',
packageName: '@openchamber/opencode-claude',
providerId: 'claude-code',
icon: 'claude-code',
brandClassName: 'text-[#D97757]',
nameKey: 'settings.integrations.thirdParty.opencodeClaude.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
homepage: 'https://github.com/openchamber/opencode-claude',
},
{
id: 'opencode-cursor-oauth',
packageName: '@openchamber/opencode-cursor',
providerId: 'cursor',
icon: 'cursor',
brandClassName: 'text-foreground',
nameKey: 'settings.integrations.thirdParty.opencodeCursorOauth.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeCursorOauth.description',
homepage: 'https://github.com/openchamber/opencode-cursor',
},
] as const;
export interface CatalogPluginState {
userEntry: PluginEntry | null;
userEntryIsAmbiguous: boolean;
projectEntries: PluginEntry[];
registry: RegistryResult | null;
}
export type CatalogPluginPrimaryAction = 'install' | 'update' | 'setup' | 'manage';
type CatalogPluginPresentationStatus =
| 'not-installed'
| 'installed'
| 'installed-version'
| 'update-available'
| 'unpinned'
| 'ambiguous'
| 'restart-required'
| 'registry-unavailable'
| 'provider-unavailable';
interface CatalogPluginPresentationOptions {
registryUnavailable?: boolean;
restartRequired?: boolean;
providerUnavailable?: boolean;
}
interface CatalogPluginPresentation {
status: CatalogPluginPresentationStatus;
latestVersion: string | null;
}
export const specMatchesPackage = (spec: string, packageName: string): boolean =>
spec === packageName || spec.startsWith(`${packageName}@`);
export function getCatalogPluginState(
entries: PluginEntry[],
packageName: string,
registryInfo: Record<string, RegistryResult>,
): CatalogPluginState {
const matchingEntries = entries.filter((entry) => specMatchesPackage(entry.spec, packageName));
const userEntries = matchingEntries.filter((entry) => entry.scope === 'user');
const projectEntries = matchingEntries.filter((entry) => entry.scope === 'project');
const userEntry = userEntries.length === 1 ? userEntries[0] : null;
const registry = registryInfo[userEntry?.spec ?? packageName] ?? registryInfo[packageName] ?? null;
return {
userEntry,
userEntryIsAmbiguous: userEntries.length > 1,
projectEntries,
registry,
};
}
export function getLatestNpmSpec(
packageName: string,
registry: RegistryResult | null | undefined,
): string | null {
if (registry?.kind !== 'npm-ok' || registry.name !== packageName || !registry.latestVersion) {
return null;
}
return `${packageName}@${registry.latestVersion}`;
}
export function getCatalogPluginPrimaryAction(
state: CatalogPluginState,
packageName: string,
): CatalogPluginPrimaryAction {
if (state.userEntryIsAmbiguous) {
return 'manage';
}
if (!state.userEntry) {
return 'install';
}
const latestSpec = getLatestNpmSpec(packageName, state.registry);
return latestSpec && latestSpec !== state.userEntry.spec ? 'update' : 'setup';
}
/**
* Converts catalog and temporary mutation state into the one compact-card
* status. Transient states intentionally outrank installed/version metadata.
*/
export function getCatalogPluginPresentation(
state: CatalogPluginState,
options: CatalogPluginPresentationOptions = {},
): CatalogPluginPresentation {
const latestVersion = state.registry?.kind === 'npm-ok'
? state.registry.latestVersion
: null;
if (state.userEntryIsAmbiguous) {
return { status: 'ambiguous', latestVersion };
}
if (options.restartRequired) {
return { status: 'restart-required', latestVersion };
}
if (options.providerUnavailable) {
return { status: 'provider-unavailable', latestVersion };
}
if (options.registryUnavailable) {
return { status: 'registry-unavailable', latestVersion };
}
if (!state.userEntry) {
return { status: 'not-installed', latestVersion };
}
if (state.registry?.kind === 'npm-ok' && state.registry.currentVersion === state.registry.latestVersion) {
return { status: 'installed-version', latestVersion };
}
if (state.registry?.kind === 'npm-ok' && state.registry.currentVersion === null) {
return { status: 'unpinned', latestVersion };
}
if (state.registry?.kind === 'npm-ok' && latestVersion) {
return { status: 'update-available', latestVersion };
}
return { status: 'installed', latestVersion };
}
@@ -310,24 +310,6 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
setMobileStage(def.kind === 'split' ? 'page-sidebar' : 'page-content');
}, [isMobile, setSettingsPage]);
const openThirdPartyProviderSetup = React.useCallback(async (providerId: string): Promise<boolean> => {
const configStore = useConfigStore.getState();
await configStore.loadProviders({ source: 'settings:third-party-provider-setup' });
const providerAvailable = useConfigStore.getState().providers.some(
(provider) => provider.id === providerId,
);
if (!providerAvailable) {
return false;
}
configStore.setSelectedProvider(providerId);
openPage('providers');
if (isMobile) {
setMobileStage('page-content');
}
return true;
}, [isMobile, openPage]);
const activePageMeta = React.useMemo(() => {
return getSettingsPageMeta(settingsSlug);
}, [settingsSlug]);
@@ -679,12 +661,7 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
case 'git':
return <GitPage />;
case 'integrations':
return (
<IntegrationsPage
onOpenProviderSetup={openThirdPartyProviderSetup}
onOpenPluginManager={() => openPage('plugins')}
/>
);
return <IntegrationsPage />;
case 'general':
case 'appearance':
case 'chat':
@@ -700,7 +677,7 @@ export const SettingsView: React.FC<SettingsViewProps> = ({ onClose, forceMobile
default:
return null;
}
}, [openChamberSectionBySlug, openPage, openThirdPartyProviderSetup, renderUnavailable, runtimeCtx, t]);
}, [openChamberSectionBySlug, renderUnavailable, runtimeCtx, t]);
// Mobile: if opened via deep-link / palette to a non-home page, jump into it once.
React.useEffect(() => {
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go Nutzungsverfolgung',
'settings.providers.page.openCodeGo.description': 'Verbinden Sie das OpenCode Go Dashboard, um rollierenden, wöchentlichen und monatlichen Verbrauch anzuzeigen.',
@@ -2225,5 +2224,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.themeMode.dark.description': 'Immer dunkles Erscheinungsbild verwenden',
'chat.message.userText.collapseAria': 'Benutzernachricht einklappen',
...linearIntegrationI18n.de,
...thirdPartyIntegrationI18n.de,
'settings.page.integrations.title': 'Integrationen',
'settings.page.integrations.description': 'Verbinde GitHub und Linear, damit OpenChamber mit deinen Issues und Pull Requests arbeiten kann.',
};
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go usage tracking',
'settings.providers.page.openCodeGo.description': 'Connect the OpenCode Go dashboard to show rolling, weekly, and monthly quota.',
@@ -2224,5 +2223,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n.en,
...thirdPartyIntegrationI18n.en,
'settings.page.integrations.title': 'Integrations',
'settings.page.integrations.description': 'Connect GitHub and Linear so OpenChamber can work with your issues and pull requests.',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Seguimiento de uso de OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Conecta el panel de OpenCode Go para ver las cuotas móvil, semanal y mensual.',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...linearIntegrationI18n.es,
...thirdPartyIntegrationI18n.es,
'settings.page.integrations.title': 'Integraciones',
'settings.page.integrations.description': 'Conecta GitHub y Linear para que OpenChamber pueda trabajar con tus issues y pull requests.',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Suivi de lutilisation dOpenCode Go',
'settings.providers.page.openCodeGo.description': 'Connectez le tableau de bord OpenCode Go pour afficher les quotas glissant, hebdomadaire et mensuel.',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n.fr,
...thirdPartyIntegrationI18n.fr,
'settings.page.integrations.title': 'Intégrations',
'settings.page.integrations.description': 'Connectez GitHub et Linear pour quOpenChamber puisse travailler avec vos issues et pull requests.',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 使用量追跡',
'settings.providers.page.openCodeGo.description': 'OpenCode Go ダッシュボードを接続して、ローリング、週間、月間のクォータを表示します。',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'ステア',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'キュー',
...linearIntegrationI18n.ja,
...thirdPartyIntegrationI18n.ja,
'settings.page.integrations.title': '連携',
'settings.page.integrations.description': 'GitHub と Linear を接続すると、OpenChamber が Issue やプルリクエストを扱えるようになります。',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 사용량 추적',
'settings.providers.page.openCodeGo.description': 'OpenCode Go 대시보드를 연결하여 롤링, 주간 및 월간 할당량을 표시합니다.',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n.ko,
...thirdPartyIntegrationI18n.ko,
'settings.page.integrations.title': '통합',
'settings.page.integrations.description': 'GitHub와 Linear를 연결하면 OpenChamber가 이슈와 풀 리퀘스트를 다룰 수 있습니다.',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Śledzenie użycia OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Połącz panel OpenCode Go, aby wyświetlać limity kroczące, tygodniowe i miesięczne.',
@@ -2227,5 +2226,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n.pl,
...thirdPartyIntegrationI18n.pl,
'settings.page.integrations.title': 'Integracje',
'settings.page.integrations.description': 'Połącz GitHub i Linear, aby OpenChamber mógł pracować z Twoimi issue i pull requestami.',
};
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Monitoramento de uso do OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Conecte o painel do OpenCode Go para exibir as cotas móvel, semanal e mensal.',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...linearIntegrationI18n['pt-BR'],
...thirdPartyIntegrationI18n['pt-BR'],
'settings.page.integrations.title': 'Integrações',
'settings.page.integrations.description': 'Conecte o GitHub e o Linear para que o OpenChamber possa trabalhar com suas issues e pull requests.',
} as const;
@@ -1,28 +0,0 @@
import { describe, expect, test } from 'bun:test';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
const locales = ['en', 'de', 'fr', 'es', 'ja', 'pt-BR', 'uk', 'ko', 'pl', 'zh-CN', 'zh-TW', 'tr'] as const;
const requiredKeys = [
'settings.page.integrations.title',
'settings.page.integrations.description',
'settings.integrations.experimentalWarning',
'settings.integrations.thirdParty.title',
'settings.integrations.thirdParty.actions.install',
'settings.integrations.thirdParty.actions.update',
'settings.integrations.thirdParty.actions.setup',
'settings.integrations.thirdParty.actions.remove',
'settings.integrations.thirdParty.status.notInstalled',
'settings.integrations.thirdParty.opencodeClaude.description',
'settings.integrations.thirdParty.opencodeCursorOauth.description',
] as const;
describe('third-party integration translations', () => {
test('provides every required key in every supported locale', () => {
for (const locale of locales) {
for (const key of requiredKeys) {
expect(thirdPartyIntegrationI18n[locale][key]).toBeTruthy();
}
}
});
});
@@ -1,423 +0,0 @@
/** Third-party integration settings strings — merged into each locale's settings dictionary. */
export const thirdPartyIntegrationI18n = {
en: {
'settings.page.integrations.title': 'Integrations',
'settings.page.integrations.description': 'Add third-party subscriptions to use as OpenChamber providers.',
'settings.integrations.experimentalWarning': 'Experimental feature. We aim to respect provider policies, but account restrictions and suspensions remain each provider\'s decision. Use integrations at your own risk.',
'settings.integrations.thirdParty.title': 'Third-party integrations',
'settings.integrations.thirdParty.info': 'Install a provider plugin, then set up your subscription so OpenChamber can use it.',
'settings.integrations.thirdParty.actions.install': 'Install',
'settings.integrations.thirdParty.actions.update': 'Update',
'settings.integrations.thirdParty.actions.setup': 'Set up',
'settings.integrations.thirdParty.actions.remove': 'Remove',
'settings.integrations.thirdParty.actions.docs': 'Docs',
'settings.integrations.thirdParty.actions.managePlugins': 'Manage plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Not installed',
'settings.integrations.thirdParty.status.installed': 'Installed',
'settings.integrations.thirdParty.status.installedVersion': 'Installed {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Update available: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Following the latest release',
'settings.integrations.thirdParty.status.projectInstalled': 'Also configured for this project',
'settings.integrations.thirdParty.status.ambiguous': 'Multiple user-wide plugin entries need manual management',
'settings.integrations.thirdParty.status.restartRequired': 'Restart OpenCode before setting up this provider.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Could not check npm right now.',
'settings.integrations.thirdParty.status.providerUnavailable': 'The provider is not available yet. Restart OpenCode and try again.',
'settings.integrations.thirdParty.dialog.remove.title': 'Remove integration',
'settings.integrations.thirdParty.dialog.remove.description': 'Remove {name} from your user-wide OpenCode configuration? The provider will no longer load after OpenCode refreshes.',
'settings.integrations.thirdParty.toast.installed': '{name} installed',
'settings.integrations.thirdParty.toast.updated': '{name} updated',
'settings.integrations.thirdParty.toast.removed': '{name} removed',
'settings.integrations.thirdParty.toast.actionFailed': 'Could not update the integration',
'settings.integrations.thirdParty.toast.providerUnavailable': 'The provider could not be opened yet',
'settings.integrations.thirdParty.toast.restartRequired': 'Restart OpenCode for changes to take effect',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use your Claude Pro/Max plan — no API keys, no Claude apps.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursors generous in-house model limits, now in OpenChamber.',
},
de: {
'settings.page.integrations.title': 'Integrationen',
'settings.page.integrations.description': 'Füge Drittanbieter-Abonnements hinzu, um sie als OpenChamber-Provider zu nutzen.',
'settings.integrations.experimentalWarning': 'Experimentelle Funktion. Wir bemühen uns, die Richtlinien der Anbieter zu respektieren, aber Kontobeschränkungen und Sperrungen liegen bei jedem Anbieter. Nutze Integrationen auf eigenes Risiko.',
'settings.integrations.thirdParty.title': 'Drittanbieter-Integrationen',
'settings.integrations.thirdParty.info': 'Installiere ein Provider-Plugin und richte dein Abonnement ein, damit OpenChamber es nutzen kann.',
'settings.integrations.thirdParty.actions.install': 'Installieren',
'settings.integrations.thirdParty.actions.update': 'Aktualisieren',
'settings.integrations.thirdParty.actions.setup': 'Einrichten',
'settings.integrations.thirdParty.actions.remove': 'Entfernen',
'settings.integrations.thirdParty.actions.docs': 'Dokumentation',
'settings.integrations.thirdParty.actions.managePlugins': 'Plugins verwalten',
'settings.integrations.thirdParty.status.notInstalled': 'Nicht installiert',
'settings.integrations.thirdParty.status.installed': 'Installiert',
'settings.integrations.thirdParty.status.installedVersion': '{version} installiert',
'settings.integrations.thirdParty.status.updateAvailable': 'Aktualisierung verfügbar: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Folgt der neuesten Version',
'settings.integrations.thirdParty.status.projectInstalled': 'Auch für dieses Projekt konfiguriert',
'settings.integrations.thirdParty.status.ambiguous': 'Mehrere benutzerweite Plugin-Einträge müssen manuell verwaltet werden',
'settings.integrations.thirdParty.status.restartRequired': 'Starte OpenCode neu, bevor du diesen Provider einrichtest.',
'settings.integrations.thirdParty.status.registryUnavailable': 'npm konnte gerade nicht geprüft werden.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Der Provider ist noch nicht verfügbar. Starte OpenCode neu und versuche es erneut.',
'settings.integrations.thirdParty.dialog.remove.title': 'Integration entfernen',
'settings.integrations.thirdParty.dialog.remove.description': '{name} aus deiner benutzerweiten OpenCode-Konfiguration entfernen? Der Provider wird nach der Aktualisierung von OpenCode nicht mehr geladen.',
'settings.integrations.thirdParty.toast.installed': '{name} installiert',
'settings.integrations.thirdParty.toast.updated': '{name} aktualisiert',
'settings.integrations.thirdParty.toast.removed': '{name} entfernt',
'settings.integrations.thirdParty.toast.actionFailed': 'Die Integration konnte nicht aktualisiert werden',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Der Provider konnte noch nicht geöffnet werden',
'settings.integrations.thirdParty.toast.restartRequired': 'Starte OpenCode neu, damit die Änderungen wirksam werden',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Nutze deinen Claude-Pro/Max-Plan — ohne API-Keys, ohne Claude-Apps.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Die großzügigen Limits der Cursor-eigenen Modelle jetzt in OpenChamber.',
},
fr: {
'settings.page.integrations.title': 'Intégrations',
'settings.page.integrations.description': 'Ajoutez des abonnements tiers à utiliser comme fournisseurs OpenChamber.',
'settings.integrations.experimentalWarning': 'Fonctionnalité expérimentale. Nous cherchons à respecter les règles des fournisseurs, mais les restrictions et suspensions de compte relèvent de leur décision. Utilisez les intégrations à vos risques.',
'settings.integrations.thirdParty.title': 'Intégrations tierces',
'settings.integrations.thirdParty.info': 'Installez un plugin de fournisseur, puis configurez votre abonnement pour quOpenChamber puisse lutiliser.',
'settings.integrations.thirdParty.actions.install': 'Installer',
'settings.integrations.thirdParty.actions.update': 'Mettre à jour',
'settings.integrations.thirdParty.actions.setup': 'Configurer',
'settings.integrations.thirdParty.actions.remove': 'Supprimer',
'settings.integrations.thirdParty.actions.docs': 'Documentation',
'settings.integrations.thirdParty.actions.managePlugins': 'Gérer les plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Non installé',
'settings.integrations.thirdParty.status.installed': 'Installé',
'settings.integrations.thirdParty.status.installedVersion': '{version} installé',
'settings.integrations.thirdParty.status.updateAvailable': 'Mise à jour disponible : {version}',
'settings.integrations.thirdParty.status.unpinned': 'Suit la dernière version',
'settings.integrations.thirdParty.status.projectInstalled': 'Également configuré pour ce projet',
'settings.integrations.thirdParty.status.ambiguous': 'Plusieurs entrées de plugin globales doivent être gérées manuellement',
'settings.integrations.thirdParty.status.restartRequired': 'Redémarrez OpenCode avant de configurer ce fournisseur.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Impossible de vérifier npm pour le moment.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Le fournisseur nest pas encore disponible. Redémarrez OpenCode et réessayez.',
'settings.integrations.thirdParty.dialog.remove.title': 'Supprimer lintégration',
'settings.integrations.thirdParty.dialog.remove.description': 'Supprimer {name} de votre configuration OpenCode globale ? Le fournisseur ne sera plus chargé après lactualisation dOpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} installé',
'settings.integrations.thirdParty.toast.updated': '{name} mis à jour',
'settings.integrations.thirdParty.toast.removed': '{name} supprimé',
'settings.integrations.thirdParty.toast.actionFailed': 'Impossible de mettre à jour lintégration',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Le fournisseur na pas encore pu être ouvert',
'settings.integrations.thirdParty.toast.restartRequired': 'Redémarrez OpenCode pour que les modifications prennent effet',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Utilisez votre forfait Claude Pro/Max — sans clés API, sans apps Claude.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Les généreuses limites des modèles internes Cursor, désormais dans OpenChamber.',
},
es: {
'settings.page.integrations.title': 'Integraciones',
'settings.page.integrations.description': 'Añade suscripciones de terceros para usarlas como proveedores de OpenChamber.',
'settings.integrations.experimentalWarning': 'Función experimental. Buscamos respetar las políticas de los proveedores, pero las restricciones y suspensiones de cuentas son decisión de cada proveedor. Usa las integraciones bajo tu propia responsabilidad.',
'settings.integrations.thirdParty.title': 'Integraciones de terceros',
'settings.integrations.thirdParty.info': 'Instala un plugin de proveedor y configura tu suscripción para que OpenChamber pueda usarla.',
'settings.integrations.thirdParty.actions.install': 'Instalar',
'settings.integrations.thirdParty.actions.update': 'Actualizar',
'settings.integrations.thirdParty.actions.setup': 'Configurar',
'settings.integrations.thirdParty.actions.remove': 'Quitar',
'settings.integrations.thirdParty.actions.docs': 'Documentación',
'settings.integrations.thirdParty.actions.managePlugins': 'Administrar plugins',
'settings.integrations.thirdParty.status.notInstalled': 'No instalado',
'settings.integrations.thirdParty.status.installed': 'Instalado',
'settings.integrations.thirdParty.status.installedVersion': '{version} instalado',
'settings.integrations.thirdParty.status.updateAvailable': 'Actualización disponible: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Sigue la versión más reciente',
'settings.integrations.thirdParty.status.projectInstalled': 'También configurado para este proyecto',
'settings.integrations.thirdParty.status.ambiguous': 'Hay varias entradas de plugin globales que requieren gestión manual',
'settings.integrations.thirdParty.status.restartRequired': 'Reinicia OpenCode antes de configurar este proveedor.',
'settings.integrations.thirdParty.status.registryUnavailable': 'No se pudo comprobar npm ahora mismo.',
'settings.integrations.thirdParty.status.providerUnavailable': 'El proveedor todavía no está disponible. Reinicia OpenCode e inténtalo de nuevo.',
'settings.integrations.thirdParty.dialog.remove.title': 'Quitar integración',
'settings.integrations.thirdParty.dialog.remove.description': '¿Quitar {name} de tu configuración global de OpenCode? El proveedor dejará de cargarse después de actualizar OpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} instalado',
'settings.integrations.thirdParty.toast.updated': '{name} actualizado',
'settings.integrations.thirdParty.toast.removed': '{name} eliminado',
'settings.integrations.thirdParty.toast.actionFailed': 'No se pudo actualizar la integración',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Todavía no se pudo abrir el proveedor',
'settings.integrations.thirdParty.toast.restartRequired': 'Reinicia OpenCode para que los cambios surtan efecto',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Usa tu plan Claude Pro/Max: sin claves API ni apps de Claude.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Los generosos límites de los modelos internos de Cursor, ahora en OpenChamber.',
},
ja: {
'settings.page.integrations.title': '連携',
'settings.page.integrations.description': 'サードパーティのサブスクリプションを追加して、OpenChamber のプロバイダーとして使います。',
'settings.integrations.experimentalWarning': '実験的な機能です。プロバイダーの方針を尊重するよう努めていますが、アカウントの制限や停止は各プロバイダーの判断に委ねられます。自己責任で連携を使用してください。',
'settings.integrations.thirdParty.title': 'サードパーティー連携',
'settings.integrations.thirdParty.info': 'プロバイダープラグインをインストールし、サブスクリプションを設定して OpenChamber で使えるようにします。',
'settings.integrations.thirdParty.actions.install': 'インストール',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '設定',
'settings.integrations.thirdParty.actions.remove': '削除',
'settings.integrations.thirdParty.actions.docs': 'ドキュメント',
'settings.integrations.thirdParty.actions.managePlugins': 'プラグインを管理',
'settings.integrations.thirdParty.status.notInstalled': '未インストール',
'settings.integrations.thirdParty.status.installed': 'インストール済み',
'settings.integrations.thirdParty.status.installedVersion': '{version} をインストール済み',
'settings.integrations.thirdParty.status.updateAvailable': '更新があります: {version}',
'settings.integrations.thirdParty.status.unpinned': '最新リリースを追跡中',
'settings.integrations.thirdParty.status.projectInstalled': 'このプロジェクトにも設定済み',
'settings.integrations.thirdParty.status.ambiguous': '複数のユーザー全体プラグインエントリーは手動で管理する必要があります',
'settings.integrations.thirdParty.status.restartRequired': 'このプロバイダーを設定する前に OpenCode を再起動してください。',
'settings.integrations.thirdParty.status.registryUnavailable': '現在 npm を確認できません。',
'settings.integrations.thirdParty.status.providerUnavailable': 'プロバイダーはまだ利用できません。OpenCode を再起動して再試行してください。',
'settings.integrations.thirdParty.dialog.remove.title': '連携を削除',
'settings.integrations.thirdParty.dialog.remove.description': '{name} をユーザー全体の OpenCode 設定から削除しますか?OpenCode の更新後、このプロバイダーは読み込まれなくなります。',
'settings.integrations.thirdParty.toast.installed': '{name} をインストールしました',
'settings.integrations.thirdParty.toast.updated': '{name} を更新しました',
'settings.integrations.thirdParty.toast.removed': '{name} を削除しました',
'settings.integrations.thirdParty.toast.actionFailed': '連携を更新できませんでした',
'settings.integrations.thirdParty.toast.providerUnavailable': 'プロバイダーをまだ開けませんでした',
'settings.integrations.thirdParty.toast.restartRequired': '変更を反映するには OpenCode を再起動してください',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max プランを利用 — API キーも Claude アプリも不要。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内蔵モデルの余裕ある制限が、OpenChamber で使えます。',
},
ko: {
'settings.page.integrations.title': '통합',
'settings.page.integrations.description': '타사 구독을 추가해 OpenChamber 프로바이더로 사용하세요.',
'settings.integrations.experimentalWarning': '실험 단계 기능입니다. 프로바이더 정책을 존중하려 노력하지만, 계정 제한과 정지는 각 프로바이더의 결정입니다. 본인의 책임 아래 통합 기능을 사용하세요.',
'settings.integrations.thirdParty.title': '서드파티 통합',
'settings.integrations.thirdParty.info': '프로바이더 플러그인을 설치한 뒤 구독을 설정하면 OpenChamber에서 사용할 수 있습니다.',
'settings.integrations.thirdParty.actions.install': '설치',
'settings.integrations.thirdParty.actions.update': '업데이트',
'settings.integrations.thirdParty.actions.setup': '설정',
'settings.integrations.thirdParty.actions.remove': '제거',
'settings.integrations.thirdParty.actions.docs': '문서',
'settings.integrations.thirdParty.actions.managePlugins': '플러그인 관리',
'settings.integrations.thirdParty.status.notInstalled': '설치되지 않음',
'settings.integrations.thirdParty.status.installed': '설치됨',
'settings.integrations.thirdParty.status.installedVersion': '{version} 설치됨',
'settings.integrations.thirdParty.status.updateAvailable': '업데이트 가능: {version}',
'settings.integrations.thirdParty.status.unpinned': '최신 릴리스 추적 중',
'settings.integrations.thirdParty.status.projectInstalled': '이 프로젝트에도 구성됨',
'settings.integrations.thirdParty.status.ambiguous': '여러 사용자 전체 플러그인 항목은 수동으로 관리해야 합니다',
'settings.integrations.thirdParty.status.restartRequired': '이 프로바이더를 설정하기 전에 OpenCode를 다시 시작하세요.',
'settings.integrations.thirdParty.status.registryUnavailable': '지금은 npm을 확인할 수 없습니다.',
'settings.integrations.thirdParty.status.providerUnavailable': '프로바이더를 아직 사용할 수 없습니다. OpenCode를 다시 시작한 후 재시도하세요.',
'settings.integrations.thirdParty.dialog.remove.title': '통합 제거',
'settings.integrations.thirdParty.dialog.remove.description': '사용자 전체 OpenCode 구성에서 {name}을(를) 제거할까요? OpenCode가 새로 고쳐진 후 프로바이더가 더 이상 로드되지 않습니다.',
'settings.integrations.thirdParty.toast.installed': '{name} 설치됨',
'settings.integrations.thirdParty.toast.updated': '{name} 업데이트됨',
'settings.integrations.thirdParty.toast.removed': '{name} 제거됨',
'settings.integrations.thirdParty.toast.actionFailed': '통합을 업데이트하지 못했습니다',
'settings.integrations.thirdParty.toast.providerUnavailable': '프로바이더를 아직 열 수 없습니다',
'settings.integrations.thirdParty.toast.restartRequired': '변경 사항을 적용하려면 OpenCode를 다시 시작하세요',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max 요금제를 사용하세요. API 키와 Claude 앱은 필요 없습니다.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 자체 모델의 넉넉한 한도를 이제 OpenChamber에서.',
},
pl: {
'settings.page.integrations.title': 'Integracje',
'settings.page.integrations.description': 'Dodaj subskrypcje zewnętrzne, aby używać ich jako dostawców OpenChamber.',
'settings.integrations.experimentalWarning': 'Funkcja eksperymentalna. Staramy się przestrzegać zasad dostawców, ale ograniczenia i zawieszenia kont pozostają decyzją każdego dostawcy. Używaj integracji na własne ryzyko.',
'settings.integrations.thirdParty.title': 'Integracje zewnętrzne',
'settings.integrations.thirdParty.info': 'Zainstaluj wtyczkę dostawcy, a następnie skonfiguruj subskrypcję, aby OpenChamber mógł z niej korzystać.',
'settings.integrations.thirdParty.actions.install': 'Zainstaluj',
'settings.integrations.thirdParty.actions.update': 'Aktualizuj',
'settings.integrations.thirdParty.actions.setup': 'Skonfiguruj',
'settings.integrations.thirdParty.actions.remove': 'Usuń',
'settings.integrations.thirdParty.actions.docs': 'Dokumentacja',
'settings.integrations.thirdParty.actions.managePlugins': 'Zarządzaj wtyczkami',
'settings.integrations.thirdParty.status.notInstalled': 'Nie zainstalowano',
'settings.integrations.thirdParty.status.installed': 'Zainstalowano',
'settings.integrations.thirdParty.status.installedVersion': 'Zainstalowano {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Dostępna aktualizacja: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Śledzi najnowsze wydanie',
'settings.integrations.thirdParty.status.projectInstalled': 'Skonfigurowano także dla tego projektu',
'settings.integrations.thirdParty.status.ambiguous': 'Wiele globalnych wpisów wtyczki wymaga ręcznego zarządzania',
'settings.integrations.thirdParty.status.restartRequired': 'Uruchom ponownie OpenCode przed konfiguracją tego dostawcy.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Nie można teraz sprawdzić npm.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Dostawca nie jest jeszcze dostępny. Uruchom ponownie OpenCode i spróbuj ponownie.',
'settings.integrations.thirdParty.dialog.remove.title': 'Usuń integrację',
'settings.integrations.thirdParty.dialog.remove.description': 'Usunąć {name} z globalnej konfiguracji OpenCode? Dostawca przestanie być ładowany po odświeżeniu OpenCode.',
'settings.integrations.thirdParty.toast.installed': 'Zainstalowano {name}',
'settings.integrations.thirdParty.toast.updated': 'Zaktualizowano {name}',
'settings.integrations.thirdParty.toast.removed': 'Usunięto {name}',
'settings.integrations.thirdParty.toast.actionFailed': 'Nie udało się zaktualizować integracji',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Nie można jeszcze otworzyć dostawcy',
'settings.integrations.thirdParty.toast.restartRequired': 'Uruchom ponownie OpenCode, aby zastosować zmiany',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Korzystaj z planu Claude Pro/Max — bez kluczy API i aplikacji Claude.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Hojne limity wewnętrznych modeli Cursor teraz w OpenChamber.',
},
'pt-BR': {
'settings.page.integrations.title': 'Integrações',
'settings.page.integrations.description': 'Adicione assinaturas de terceiros para usar como provedores do OpenChamber.',
'settings.integrations.experimentalWarning': 'Recurso experimental. Buscamos respeitar as políticas dos provedores, mas restrições e suspensões de conta continuam sendo decisão de cada provedor. Use as integrações por sua conta e risco.',
'settings.integrations.thirdParty.title': 'Integrações de terceiros',
'settings.integrations.thirdParty.info': 'Instale um plugin de provedor e configure sua assinatura para o OpenChamber poder usá-la.',
'settings.integrations.thirdParty.actions.install': 'Instalar',
'settings.integrations.thirdParty.actions.update': 'Atualizar',
'settings.integrations.thirdParty.actions.setup': 'Configurar',
'settings.integrations.thirdParty.actions.remove': 'Remover',
'settings.integrations.thirdParty.actions.docs': 'Documentação',
'settings.integrations.thirdParty.actions.managePlugins': 'Gerenciar plugins',
'settings.integrations.thirdParty.status.notInstalled': 'Não instalado',
'settings.integrations.thirdParty.status.installed': 'Instalado',
'settings.integrations.thirdParty.status.installedVersion': '{version} instalado',
'settings.integrations.thirdParty.status.updateAvailable': 'Atualização disponível: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Acompanha a versão mais recente',
'settings.integrations.thirdParty.status.projectInstalled': 'Também configurado para este projeto',
'settings.integrations.thirdParty.status.ambiguous': 'Várias entradas de plugin globais precisam de gerenciamento manual',
'settings.integrations.thirdParty.status.restartRequired': 'Reinicie o OpenCode antes de configurar este provedor.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Não foi possível verificar o npm agora.',
'settings.integrations.thirdParty.status.providerUnavailable': 'O provedor ainda não está disponível. Reinicie o OpenCode e tente novamente.',
'settings.integrations.thirdParty.dialog.remove.title': 'Remover integração',
'settings.integrations.thirdParty.dialog.remove.description': 'Remover {name} da sua configuração global do OpenCode? O provedor deixará de ser carregado após a atualização do OpenCode.',
'settings.integrations.thirdParty.toast.installed': '{name} instalado',
'settings.integrations.thirdParty.toast.updated': '{name} atualizado',
'settings.integrations.thirdParty.toast.removed': '{name} removido',
'settings.integrations.thirdParty.toast.actionFailed': 'Não foi possível atualizar a integração',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Ainda não foi possível abrir o provedor',
'settings.integrations.thirdParty.toast.restartRequired': 'Reinicie o OpenCode para que as alterações entrem em vigor',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Use seu plano Claude Pro/Max — sem chaves de API nem apps da Claude.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Os limites generosos dos modelos internos do Cursor, agora no OpenChamber.',
},
uk: {
'settings.page.integrations.title': 'Інтеграції',
'settings.page.integrations.description': 'Додайте сторонні підписки, щоб використовувати їх як провайдери OpenChamber.',
'settings.integrations.experimentalWarning': 'Експериментальна функція. Ми прагнемо дотримуватися політик провайдерів, але обмеження та блокування облікових записів залишаються рішенням кожного провайдера. Використовуйте інтеграції на власний ризик.',
'settings.integrations.thirdParty.title': 'Сторонні інтеграції',
'settings.integrations.thirdParty.info': 'Установіть плагін провайдера, а потім налаштуйте підписку, щоб OpenChamber міг її використовувати.',
'settings.integrations.thirdParty.actions.install': 'Встановити',
'settings.integrations.thirdParty.actions.update': 'Оновити',
'settings.integrations.thirdParty.actions.setup': 'Налаштувати',
'settings.integrations.thirdParty.actions.remove': 'Видалити',
'settings.integrations.thirdParty.actions.docs': 'Документація',
'settings.integrations.thirdParty.actions.managePlugins': 'Керувати плагінами',
'settings.integrations.thirdParty.status.notInstalled': 'Не встановлено',
'settings.integrations.thirdParty.status.installed': 'Встановлено',
'settings.integrations.thirdParty.status.installedVersion': 'Встановлено {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Доступне оновлення: {version}',
'settings.integrations.thirdParty.status.unpinned': 'Відстежує найновіший випуск',
'settings.integrations.thirdParty.status.projectInstalled': 'Також налаштовано для цього проєкту',
'settings.integrations.thirdParty.status.ambiguous': 'Кілька глобальних записів плагіна потребують ручного керування',
'settings.integrations.thirdParty.status.restartRequired': 'Перезапустіть OpenCode перед налаштуванням цього провайдера.',
'settings.integrations.thirdParty.status.registryUnavailable': 'Зараз не вдалося перевірити npm.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Провайдер ще недоступний. Перезапустіть OpenCode й спробуйте знову.',
'settings.integrations.thirdParty.dialog.remove.title': 'Видалити інтеграцію',
'settings.integrations.thirdParty.dialog.remove.description': 'Видалити {name} з вашої глобальної конфігурації OpenCode? Після оновлення OpenCode провайдер більше не завантажуватиметься.',
'settings.integrations.thirdParty.toast.installed': '{name} встановлено',
'settings.integrations.thirdParty.toast.updated': '{name} оновлено',
'settings.integrations.thirdParty.toast.removed': '{name} видалено',
'settings.integrations.thirdParty.toast.actionFailed': 'Не вдалося оновити інтеграцію',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Провайдера ще не вдалося відкрити',
'settings.integrations.thirdParty.toast.restartRequired': 'Перезапустіть OpenCode, щоб застосувати зміни',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max за підпискою — без API-ключів і без додатків Claude.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Щедрі ліміти внутрішніх моделей Cursor — тепер в OpenChamber.',
},
'zh-CN': {
'settings.page.integrations.title': '集成',
'settings.page.integrations.description': '添加第三方订阅,将其用作 OpenChamber 提供商。',
'settings.integrations.experimentalWarning': '实验性功能。我们力求遵守提供商的政策,但帐户限制和暂停仍由各提供商决定。请自行承担使用集成的风险。',
'settings.integrations.thirdParty.title': '第三方集成',
'settings.integrations.thirdParty.info': '安装提供商插件并设置订阅,以便 OpenChamber 可以使用它。',
'settings.integrations.thirdParty.actions.install': '安装',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '设置',
'settings.integrations.thirdParty.actions.remove': '移除',
'settings.integrations.thirdParty.actions.docs': '文档',
'settings.integrations.thirdParty.actions.managePlugins': '管理插件',
'settings.integrations.thirdParty.status.notInstalled': '未安装',
'settings.integrations.thirdParty.status.installed': '已安装',
'settings.integrations.thirdParty.status.installedVersion': '已安装 {version}',
'settings.integrations.thirdParty.status.updateAvailable': '有可用更新:{version}',
'settings.integrations.thirdParty.status.unpinned': '跟踪最新版本',
'settings.integrations.thirdParty.status.projectInstalled': '也已为此项目配置',
'settings.integrations.thirdParty.status.ambiguous': '多个用户级插件条目需要手动管理',
'settings.integrations.thirdParty.status.restartRequired': '请先重启 OpenCode,再设置此提供商。',
'settings.integrations.thirdParty.status.registryUnavailable': '当前无法检查 npm。',
'settings.integrations.thirdParty.status.providerUnavailable': '该提供商尚不可用。请重启 OpenCode 后重试。',
'settings.integrations.thirdParty.dialog.remove.title': '移除集成',
'settings.integrations.thirdParty.dialog.remove.description': '要从用户级 OpenCode 配置中移除 {name} 吗?OpenCode 刷新后将不再加载该提供商。',
'settings.integrations.thirdParty.toast.installed': '已安装 {name}',
'settings.integrations.thirdParty.toast.updated': '已更新 {name}',
'settings.integrations.thirdParty.toast.removed': '已移除 {name}',
'settings.integrations.thirdParty.toast.actionFailed': '无法更新集成',
'settings.integrations.thirdParty.toast.providerUnavailable': '暂时无法打开该提供商',
'settings.integrations.thirdParty.toast.restartRequired': '请重启 OpenCode 以使更改生效',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 套餐——无需 API 密钥,也无需 Claude 应用。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 内部模型的充足额度,现已可用于 OpenChamber。',
},
'zh-TW': {
'settings.page.integrations.title': '整合',
'settings.page.integrations.description': '新增第三方訂閱,將其用作 OpenChamber 供應商。',
'settings.integrations.experimentalWarning': '實驗性功能。我們致力遵守供應商的政策,但帳戶限制和停用仍由各供應商決定。請自行承擔使用整合的風險。',
'settings.integrations.thirdParty.title': '第三方整合',
'settings.integrations.thirdParty.info': '安裝供應商外掛並設定訂閱,以便 OpenChamber 可以使用它。',
'settings.integrations.thirdParty.actions.install': '安裝',
'settings.integrations.thirdParty.actions.update': '更新',
'settings.integrations.thirdParty.actions.setup': '設定',
'settings.integrations.thirdParty.actions.remove': '移除',
'settings.integrations.thirdParty.actions.docs': '文件',
'settings.integrations.thirdParty.actions.managePlugins': '管理外掛',
'settings.integrations.thirdParty.status.notInstalled': '未安裝',
'settings.integrations.thirdParty.status.installed': '已安裝',
'settings.integrations.thirdParty.status.installedVersion': '已安裝 {version}',
'settings.integrations.thirdParty.status.updateAvailable': '有可用更新:{version}',
'settings.integrations.thirdParty.status.unpinned': '追蹤最新版本',
'settings.integrations.thirdParty.status.projectInstalled': '也已為此專案設定',
'settings.integrations.thirdParty.status.ambiguous': '多個使用者層級外掛項目需要手動管理',
'settings.integrations.thirdParty.status.restartRequired': '請先重新啟動 OpenCode,再設定此供應商。',
'settings.integrations.thirdParty.status.registryUnavailable': '目前無法檢查 npm。',
'settings.integrations.thirdParty.status.providerUnavailable': '供應商尚不可用。請重新啟動 OpenCode 後再試一次。',
'settings.integrations.thirdParty.dialog.remove.title': '移除整合',
'settings.integrations.thirdParty.dialog.remove.description': '要從使用者層級 OpenCode 設定中移除 {name} 嗎?OpenCode 重新整理後將不再載入此供應商。',
'settings.integrations.thirdParty.toast.installed': '已安裝 {name}',
'settings.integrations.thirdParty.toast.updated': '已更新 {name}',
'settings.integrations.thirdParty.toast.removed': '已移除 {name}',
'settings.integrations.thirdParty.toast.actionFailed': '無法更新整合',
'settings.integrations.thirdParty.toast.providerUnavailable': '暫時無法開啟供應商',
'settings.integrations.thirdParty.toast.restartRequired': '請重新啟動 OpenCode 以使變更生效',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': '使用 Claude Pro/Max 方案——無需 API 金鑰,也無需 Claude 應用程式。',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor 內部模型的充足額度,現已可用於 OpenChamber。',
},
tr: {
'settings.integrations.experimentalWarning': 'Deneysel özellik. Provider politikalarına saygı göstermeye çalışıyoruz, ancak hesap kısıtlamaları ve askıya almalar her provider\'ın kararıdır. Entegrasyonları kendi riskinize kullanın.',
'settings.page.integrations.title': 'Entegrasyonlar',
'settings.page.integrations.description': 'OpenChamber provider olarak kullanmak için üçüncü taraf abonelikler ekleyin.',
'settings.integrations.thirdParty.title': 'Üçüncü taraf entegrasyonlar',
'settings.integrations.thirdParty.info': 'Bir provider eklentisi kurun, ardından aboneliğinizi ayarlayın ki OpenChamber onu kullanabilsin.',
'settings.integrations.thirdParty.actions.install': 'Kur',
'settings.integrations.thirdParty.actions.update': 'Güncelle',
'settings.integrations.thirdParty.actions.setup': 'Ayarla',
'settings.integrations.thirdParty.actions.remove': 'Kaldır',
'settings.integrations.thirdParty.actions.docs': 'Dokümanlar',
'settings.integrations.thirdParty.actions.managePlugins': 'Eklentileri yönet',
'settings.integrations.thirdParty.status.notInstalled': 'Kurulu değil',
'settings.integrations.thirdParty.status.installed': 'Kurulu',
'settings.integrations.thirdParty.status.installedVersion': 'Kurulu: {version}',
'settings.integrations.thirdParty.status.updateAvailable': 'Güncelleme var: {version}',
'settings.integrations.thirdParty.status.unpinned': 'En son release takip ediliyor',
'settings.integrations.thirdParty.status.projectInstalled': 'Ayrıca bu proje için yapılandırıldı',
'settings.integrations.thirdParty.status.ambiguous': 'Birden çok kullanıcı genelinde eklenti girdisi elle yönetilmeli',
'settings.integrations.thirdParty.status.restartRequired': 'Bu provider\'ı ayarlamadan önce OpenCode\'u yeniden başlatın.',
'settings.integrations.thirdParty.status.registryUnavailable': 'npm şu anda denetlenemedi.',
'settings.integrations.thirdParty.status.providerUnavailable': 'Provider henüz kullanılabilir değil. OpenCode\'u yeniden başlatıp tekrar deneyin.',
'settings.integrations.thirdParty.dialog.remove.title': 'Entegrasyonu kaldır',
'settings.integrations.thirdParty.dialog.remove.description': '{name}, kullanıcı genelindeki OpenCode yapılandırmanızdan kaldırılsın mı? OpenCode yenilendikten sonra provider artık yüklenmeyecek.',
'settings.integrations.thirdParty.toast.installed': '{name} kuruldu',
'settings.integrations.thirdParty.toast.updated': '{name} güncellendi',
'settings.integrations.thirdParty.toast.removed': '{name} kaldırıldı',
'settings.integrations.thirdParty.toast.actionFailed': 'Entegrasyon güncellenemedi',
'settings.integrations.thirdParty.toast.providerUnavailable': 'Provider henüz açılamadı',
'settings.integrations.thirdParty.toast.restartRequired': 'Değişikliklerin geçerli olması için OpenCode\'u yeniden başlatın',
'settings.integrations.thirdParty.opencodeClaude.name': 'Claude Code',
'settings.integrations.thirdParty.opencodeClaude.description': 'Claude Pro/Max planınızı kullanın — API anahtarı gerekmez, Claude uygulamaları gerekmez.',
'settings.integrations.thirdParty.opencodeCursorOauth.name': 'Cursor',
'settings.integrations.thirdParty.opencodeCursorOauth.description': 'Cursor\'ın cömert kendi model limitleri artık OpenChamber\'da.',
},
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go kullanım takibi',
'settings.providers.page.openCodeGo.description': 'Kayan, haftalık ve aylık kotayı göstermek için OpenCode Go kontrol panelini bağlayın.',
@@ -2223,6 +2222,7 @@ export const settingsDict = {
'settings.openchamber.visual.field.sessionTabs': 'Session\'ları başlıkta sekme olarak göster',
'settings.openchamber.visual.field.sessionTabsAria': 'Başlıktaki session sekmelerini aç/kapat',
'settings.openchamber.visual.field.sessionTabsInfo': 'Açtığınız session\'lar başlıkta sekmeler olarak dizilir. Kapatırsanız düz session başlığına döner.',
...thirdPartyIntegrationI18n.tr,
'settings.page.integrations.title': 'Entegrasyonlar',
'settings.page.integrations.description': 'OpenChamber’ın issuelar ve pull requestlerle çalışabilmesi için GitHub ve Linear’ı bağlayın.',
...linearIntegrationI18n.tr,
};
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'Відстеження використання OpenCode Go',
'settings.providers.page.openCodeGo.description': 'Підключіть панель OpenCode Go, щоб бачити ковзну, тижневу та місячну квоту.',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
"settings.openchamber.visual.option.followUpBehavior.steer.label": "Steer",
"settings.openchamber.visual.option.followUpBehavior.queue.label": "Queue",
...linearIntegrationI18n.uk,
...thirdPartyIntegrationI18n.uk,
'settings.page.integrations.title': 'Інтеграції',
'settings.page.integrations.description': 'Підключіть GitHub і Linear, щоб OpenChamber міг працювати з вашими задачами та pull request-ами.',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 用量跟踪',
'settings.providers.page.openCodeGo.description': '连接 OpenCode Go 控制面板以显示滚动、每周和每月配额。',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n['zh-CN'],
...thirdPartyIntegrationI18n['zh-CN'],
'settings.page.integrations.title': '集成',
'settings.page.integrations.description': '连接 GitHub 和 Linear,让 OpenChamber 可以处理你的 issue 和拉取请求。',
} as const;
@@ -1,5 +1,4 @@
import { linearIntegrationI18n } from './linear-integration.i18n';
import { thirdPartyIntegrationI18n } from './third-party-integrations.i18n';
export const settingsDict = {
'settings.providers.page.openCodeGo.title': 'OpenCode Go 用量追蹤',
'settings.providers.page.openCodeGo.description': '連接 OpenCode Go 控制面板以顯示滾動、每週和每月配額。',
@@ -2234,5 +2233,6 @@ export const settingsDict = {
'settings.openchamber.visual.option.followUpBehavior.steer.label': 'Steer',
'settings.openchamber.visual.option.followUpBehavior.queue.label': 'Queue',
...linearIntegrationI18n['zh-TW'],
...thirdPartyIntegrationI18n['zh-TW'],
'settings.page.integrations.title': '整合',
'settings.page.integrations.description': '連接 GitHub 和 Linear,讓 OpenChamber 可以處理你的 issue 和 pull request。',
} as const;
+1 -1
View File
@@ -202,7 +202,7 @@ export const SETTINGS_PAGE_METADATA: readonly SettingsPageMeta[] = [
{ slug: 'voice', title: 'Voice', group: 'general', kind: 'single', keywords: ['tts', 'speech', 'voice'], isAvailable: (ctx) => !ctx.isVSCode },
{ slug: 'tunnel', title: 'External Tunnel', group: 'projects', kind: 'single', keywords: ['tunnel', 'external', 'cloudflare', 'qr', 'remote', 'mobile', 'share'], isAvailable: (ctx) => !ctx.isVSCode },
{ slug: 'about', title: 'About', group: 'general', kind: 'single', keywords: ['about', 'version', 'updates', 'release', 'changelog'], isAvailable: (ctx) => ctx.isMobile && !ctx.isVSCode },
{ slug: 'integrations', title: 'Integrations', group: 'general', kind: 'single', keywords: ['integration', 'plugin', 'provider', 'oauth', 'claude', 'cursor', 'command code', 'connect', 'discord', 'telegram', 'messenger', 'github', 'linear'] },
{ slug: 'integrations', title: 'Integrations', group: 'general', kind: 'single', keywords: ['integration', 'connect', 'oauth', 'github', 'linear'], isAvailable: (ctx) => !ctx.isVSCode },
] as const;
const LEGACY_SIDEBAR_SECTION_TO_SETTINGS_SLUG: Record<SidebarSection, SettingsPageSlug> = {
@@ -17,28 +17,6 @@ const runtimeCtx = {
};
describe('settings search', () => {
test('finds the Claude Code third-party integration', () => {
const results = buildSettingsSearchResults({
query: 'claude',
runtimeCtx,
t,
getPageTitle: (page) => page,
});
expect(results.some((result) => result.id === 'integrations.third-party.opencode-claude')).toBe(true);
});
test('finds third-party integrations by OpenChamber npm package names', () => {
const results = buildSettingsSearchResults({
query: '@openchamber/opencode-cursor',
runtimeCtx,
t,
getPageTitle: (page) => page,
});
expect(results.some((result) => result.id === 'integrations.third-party.opencode-cursor-oauth')).toBe(true);
});
test('finds Linear connect on the integrations page', () => {
const results = buildSettingsSearchResults({
query: 'linear',
-20
View File
@@ -1018,26 +1018,6 @@ const SETTINGS_SEARCH_ITEMS: readonly SettingsSearchItem[] = [
keywords: ['linear', 'project', 'team', 'map', 'workspace', 'directory'],
isAvailable: (ctx) => !ctx.isVSCode,
},
{
id: 'integrations.third-party',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.title',
keywords: ['plugin', 'provider', 'oauth', 'install', 'update', 'remove'],
},
{
id: 'integrations.third-party.opencode-claude',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.opencodeClaude.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
keywords: ['claude', 'anthropic', 'claude code', 'pro', 'max', 'agent sdk', '@openchamber/opencode-claude'],
},
{
id: 'integrations.third-party.opencode-cursor-oauth',
page: 'integrations',
titleKey: 'settings.integrations.thirdParty.opencodeCursorOauth.name',
descriptionKey: 'settings.integrations.thirdParty.opencodeCursorOauth.description',
keywords: ['cursor', 'oauth', 'subscription', 'openai compatible', '@openchamber/opencode-cursor'],
},
] as const;
interface BuildSettingsSearchResultsOptions {
+1 -1
View File
@@ -36,7 +36,7 @@ export interface PluginDraft {
content: string;
}
export type PluginMutationResult = {
type PluginMutationResult = {
ok: boolean;
reloadFailed?: boolean;
message?: string;