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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,20 @@ For link discovery, browser-only use, Android/iOS installation, notifications, a

All listed agents are discovered automatically, accept direct input, and can be launched from ChatMux. Indexed histories render as conversations; live CLI output is always available.

| Agent | Chat view |
|---|---|
| **Claude Code** | After history is indexed |
| **Codex CLI** | After history is indexed |
| **Cursor CLI** | After history is indexed |
| **OpenCode** | After history is indexed |
| **Oh My OpenAgent** (`omo`) | After history is indexed |
| **Oh My Pi** | After history is indexed |
| **Gajae Code (GJC)** | Native |
| Agent | Chat view | Full access at launch |
|---|---|---|
| **Claude Code** | After history is indexed | Yes |
| **Codex CLI** | After history is indexed | Yes |
| **Cursor CLI** | After history is indexed | No |
| **OpenCode** | After history is indexed | Yes |
| **Oh My OpenAgent** (`omo`) | After history is indexed | Yes |
| **Oh My Pi** | After history is indexed | Yes |
| **Gajae Code (GJC)** | Native | Not applicable |

SSH tmux and local shells are also supported as terminal-only connections.

**Full access** is an explicit, per-session option for newly launched local sessions. It is not saved and does not affect existing or remote sessions. Depending on the CLI, it selects that provider's verified auto-approval or full-access mode, so tools, shell commands, and file changes may proceed without another confirmation. GJC keeps its native default-allow policy and has no separate launch switch; Cursor has no verified interactive full-access flag.

<sub>Cursor sessions use the documented <code>agent</code> command; the legacy <code>cursor-agent</code> alias remains supported for older installations.</sub>

## Remote access
Expand Down
20 changes: 11 additions & 9 deletions docs/readme/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,20 @@ Linux x86_64 (glibc 2.35+)、tmux、ユーザーレベルの systemd、`curl`/`t

以下のエージェントはすべて自動検出され、直接入力と ChatMux からの新規セッション開始に対応します。インデックス済みの履歴は会話として表示され、ライブ CLI 出力はいつでも確認できます。

| エージェント | チャットビュー |
|---|---|
| **Claude Code** | 履歴のインデックス後 |
| **Codex CLI** | 履歴のインデックス後 |
| **Cursor CLI** | 履歴のインデックス後 |
| **OpenCode** | 履歴のインデックス後 |
| **Oh My OpenAgent** (`omo`) | 履歴のインデックス後 |
| **Oh My Pi** | 履歴のインデックス後 |
| **Gajae Code (GJC)** | ネイティブ対応 |
| エージェント | チャットビュー | 起動時のフルアクセス |
|---|---|---|
| **Claude Code** | 履歴のインデックス後 | 対応 |
| **Codex CLI** | 履歴のインデックス後 | 対応 |
| **Cursor CLI** | 履歴のインデックス後 | 非対応 |
| **OpenCode** | 履歴のインデックス後 | 対応 |
| **Oh My OpenAgent** (`omo`) | 履歴のインデックス後 | 対応 |
| **Oh My Pi** | 履歴のインデックス後 | 対応 |
| **Gajae Code (GJC)** | ネイティブ対応 | 該当なし |

SSH tmux とローカルシェルも、ターミナル専用接続として利用できます。

**フルアクセス**は、新しく起動するローカルセッションごとに明示的に選択するオプションです。設定は保存されず、既存またはリモートのセッションには影響しません。CLI に応じて、そのプロバイダーで検証済みの自動承認またはフルアクセスモードを選択するため、ツール、シェルコマンド、ファイル変更が追加確認なしで実行される場合があります。GJC は独自のデフォルト許可ポリシーを使用し、個別の起動スイッチはありません。Cursor には検証済みの対話型フルアクセスフラグがありません。

<sub>Cursor セッションはドキュメントに記載された <code>agent</code> コマンドを使用します。古いインストール向けにレガシーの <code>cursor-agent</code> エイリアスも引き続きサポートされます。</sub>

## リモートアクセス
Expand Down
20 changes: 11 additions & 9 deletions docs/readme/README.ko.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,20 @@ Linux x86_64(glibc 2.35+)와 tmux, 사용자 레벨 systemd, `curl`/`tar`/`sha25

아래 에이전트는 모두 자동으로 발견되며 직접 입력과 ChatMux에서의 새 세션 시작을 지원합니다. 인덱싱된 히스토리는 대화로 표시되고, 실시간 CLI 출력은 언제든 볼 수 있습니다.

| 에이전트 | 채팅 뷰 |
|---|---|
| **Claude Code** | 히스토리 인덱싱 후 |
| **Codex CLI** | 히스토리 인덱싱 후 |
| **Cursor CLI** | 히스토리 인덱싱 후 |
| **OpenCode** | 히스토리 인덱싱 후 |
| **Oh My OpenAgent** (`omo`) | 히스토리 인덱싱 후 |
| **Oh My Pi** | 히스토리 인덱싱 후 |
| **Gajae Code (GJC)** | 기본 지원 |
| 에이전트 | 채팅 뷰 | 시작 시 모두 허용 |
|---|---|---|
| **Claude Code** | 히스토리 인덱싱 후 | 지원 |
| **Codex CLI** | 히스토리 인덱싱 후 | 지원 |
| **Cursor CLI** | 히스토리 인덱싱 후 | 미지원 |
| **OpenCode** | 히스토리 인덱싱 후 | 지원 |
| **Oh My OpenAgent** (`omo`) | 히스토리 인덱싱 후 | 지원 |
| **Oh My Pi** | 히스토리 인덱싱 후 | 지원 |
| **Gajae Code (GJC)** | 기본 지원 | 해당 없음 |

SSH tmux와 로컬 셸도 터미널 전용 연결로 지원합니다.

**모두 허용**은 새로 시작하는 로컬 세션마다 명시적으로 선택하는 옵션입니다. 선택은 저장되지 않으며 기존 세션이나 원격 세션에는 영향을 주지 않습니다. CLI에 따라 해당 프로바이더에서 검증된 자동 승인 또는 전체 권한 모드를 사용하므로, 도구 실행과 셸 명령, 파일 변경이 추가 확인 없이 진행될 수 있습니다. GJC는 자체 기본 허용 정책을 사용하고 별도 시작 옵션이 없으며, Cursor는 검증된 대화형 전체 권한 옵션이 없습니다.

<sub>Cursor 세션은 문서화된 <code>agent</code> 명령을 사용합니다. 구형 설치를 위한 레거시 <code>cursor-agent</code> 별칭도 계속 지원됩니다.</sub>

## 원격 접속
Expand Down
20 changes: 11 additions & 9 deletions docs/readme/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,20 @@ curl -fsSL https://github.com/devswha/chatmux/releases/latest/download/install.s

以下代理均会被自动发现,支持直接输入,也可从 ChatMux 启动新会话。已索引的历史记录会显示为对话,实时 CLI 输出则始终可用。

| 代理 | 聊天视图 |
|---|---|
| **Claude Code** | 历史索引后 |
| **Codex CLI** | 历史索引后 |
| **Cursor CLI** | 历史索引后 |
| **OpenCode** | 历史索引后 |
| **Oh My OpenAgent** (`omo`) | 历史索引后 |
| **Oh My Pi** | 历史索引后 |
| **Gajae Code (GJC)** | 原生支持 |
| 代理 | 聊天视图 | 启动时完全访问 |
|---|---|---|
| **Claude Code** | 历史索引后 | 支持 |
| **Codex CLI** | 历史索引后 | 支持 |
| **Cursor CLI** | 历史索引后 | 不支持 |
| **OpenCode** | 历史索引后 | 支持 |
| **Oh My OpenAgent** (`omo`) | 历史索引后 | 支持 |
| **Oh My Pi** | 历史索引后 | 支持 |
| **Gajae Code (GJC)** | 原生支持 | 不适用 |

SSH tmux 和本地 shell 也可作为纯终端连接使用。

**完全访问**是为每个新启动的本地会话明确选择的选项。该选项不会保存,也不会影响现有会话或远程会话。根据 CLI,它会选择该提供商已验证的自动批准或完全访问模式,因此工具、Shell 命令和文件更改可能无需再次确认即可执行。GJC 使用其原生的默认允许策略,没有单独的启动开关;Cursor 没有经过验证的交互式完全访问参数。

<sub>Cursor 会话使用文档中的 <code>agent</code> 命令;为旧安装保留了传统的 <code>cursor-agent</code> 别名。</sub>

## 远程访问
Expand Down
29 changes: 29 additions & 0 deletions server/modules/providers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,35 @@ Here, `omo` is the CLI/provider id for **Oh My OpenAgent**.
Those ids are mirrored in backend unions and frontend provider constants. If
adding a new provider, update every place that hardcodes this list.

## External Session Startup Capabilities

The new-session form can opt a newly launched local native CLI into that
provider's verified interactive auto-approval or full-access mode. This is a
per-request boolean: it is off by default, is not persisted, and is not sent to
remote fleet spawns or applied to existing sessions.

`shared/external-cli-spawn.ts` is the shared capability list. The client uses it
to enable the checkbox, but `provider.routes.ts` remains authoritative: it
validates the boolean, rejects unsupported providers, and passes only fixed
server-owned arguments to the tmux launcher. Never accept arbitrary launch
arguments from the browser.

| Provider | Full-access startup | Native interactive arguments |
| --- | --- | --- |
| Claude | Supported | `--dangerously-skip-permissions` |
| Codex | Supported | `--dangerously-bypass-approvals-and-sandbox` |
| Cursor | Unsupported | No verified interactive full-access flag |
| OpenCode | Supported | `--auto` |
| GJC | Not applicable | Guarded tools use the native default-allow policy; there is no per-launch switch |
| Oh My Pi (`omp`) | Supported | `--approval-mode=yolo` |
| Oh My OpenAgent (`omo`) | Supported | `--approve --permission-preset full-access` |

These provider modes are not semantically identical. Document them as
auto-approval or full-access modes rather than claiming that every provider
disables the same sandbox boundary. Keep the UI warning visible when the option
is selected: tools, shell commands, and file changes may proceed without another
approval in that session.

## Current File Layout

Each provider lives under its own folder in `server/modules/providers/list/`:
Expand Down
21 changes: 18 additions & 3 deletions server/modules/providers/provider.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ import type {
import { resolveWorkspaceDirectoryWithinRoot } from '@/shared/workspace-paths.js';
import { AppError, asyncHandler, createApiSuccessResponse } from '@/shared/utils.js';

import { EXTERNAL_SPAWN_CLIS, supportsExternalCliFullAccess } from '../../../shared/external-cli-spawn.js';

import { attachCapabilityService } from './services/attach-capability.service.js';


Expand Down Expand Up @@ -979,14 +981,14 @@ router.post(
router.post(
'/sessions/external/spawn',
asyncHandler(async (req: Request, res: Response) => {
const body = (req.body ?? {}) as { name?: unknown; cwd?: unknown; cli?: unknown };
const body = (req.body ?? {}) as { name?: unknown; cwd?: unknown; cli?: unknown; fullAccess?: unknown };
if (!isValidSpawnName(body.name)) {
throw new AppError('A valid session name is required (alphanumeric, not "company").', {
code: 'INVALID_SPAWN_NAME',
statusCode: 400,
});
}
const supportedClis: ExternalSpawnCli[] = ['claude', 'codex', 'cursor', 'opencode', 'omp', 'omo'];
const supportedClis: readonly ExternalSpawnCli[] = EXTERNAL_SPAWN_CLIS;
if (body.cli !== undefined && !supportedClis.includes(body.cli as ExternalSpawnCli)) {
throw new AppError(`cli must be one of: ${supportedClis.join(', ')}.`, {
code: 'INVALID_CLI',
Expand All @@ -996,6 +998,19 @@ router.post(
const cli: ExternalSpawnCli = body.cli === undefined
? 'codex'
: body.cli as ExternalSpawnCli;
if (body.fullAccess !== undefined && typeof body.fullAccess !== 'boolean') {
throw new AppError('fullAccess must be a boolean.', {
code: 'INVALID_FULL_ACCESS',
statusCode: 400,
});
}
const fullAccess = body.fullAccess === true;
if (fullAccess && !supportsExternalCliFullAccess(cli)) {
throw new AppError(`${cli} does not support full-access startup.`, {
code: 'UNSUPPORTED_FULL_ACCESS',
statusCode: 400,
});
}
const cwdInput = typeof body.cwd === 'string' ? body.cwd.trim() : '';
if (!cwdInput) {
throw new AppError('cwd is required.', { code: 'EMPTY_CWD', statusCode: 400 });
Expand All @@ -1008,7 +1023,7 @@ router.post(
});
}
try {
await spawnExternalCliSession(cli, body.name, cwd);
await spawnExternalCliSession(cli, body.name, cwd, { fullAccess });
} catch {
throw new AppError('The external CLI session could not be created; the tmux name may already exist.', {
code: 'EXTERNAL_CLI_SPAWN_FAILED',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export { selectMostRecentCodexThreadId, selectObservedCodexThread, isCodexMainTh
export { parseClaudeRuntimeSession, isCodexRuntimeProcess, isClaudeRuntimeProcess, classifyExternalSessions, selectPrimaryCodexProcessPid } from './external-cli-sessions/process-classification.js';
export type { ExternalCliSessionCommandRunner } from './external-cli-sessions/process-classification.js';
export { extractContainedTranscriptSessionId, applyInferredProviderSessionIds, claudeReceiptPaneTag, isRunningProcess, selectClaudePaneReceipt, selectParkedClaudeReceipt } from './external-cli-sessions/provider-runtime-inference.js';
export { normalizeExternalPaneOutput, resolveExternalCliCwd, withoutNodeModulesBins, buildExternalCliRuntimePath, resolveExternalCliExecutable, buildExternalCliTmuxSpawnArgs, spawnExternalCliSession } from './external-cli-sessions/inference-and-spawn.js';
export { normalizeExternalPaneOutput, resolveExternalCliCwd, withoutNodeModulesBins, buildExternalCliRuntimePath, resolveExternalCliExecutable, buildExternalCliTmuxSpawnArgs, externalCliFullAccessArgs, spawnExternalCliSession } from './external-cli-sessions/inference-and-spawn.js';
export type { ExternalSpawnCli, CurrentTmuxPaneIdentity } from './external-cli-sessions/inference-and-spawn.js';
export { getCurrentTmuxPaneIdentityState, getCurrentTmuxPaneIdentity, resolveCodexRolloutPath, createExternalCliSessionDiscovery, getExternalCliSessionsDetailed } from './external-cli-sessions/discovery.js';
export type { ExternalCliSessionDiscovery, ExternalCliSessionDiscoveryOptions } from './external-cli-sessions/discovery.js';
Expand Down
Loading
Loading