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
102 changes: 101 additions & 1 deletion CLI/CLI+AgentWrappers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import LocalAuthentication
import Security
#endif

extension CMUXCLI {
extension ProgramaCLI {
private func isProgramaClaudeWrapper(at path: String) -> Bool {
guard let data = FileManager.default.contents(atPath: path) else { return false }
let prefixData = data.prefix(512)
Expand Down Expand Up @@ -890,4 +890,104 @@ extension CMUXCLI {
)
)
}

/// Subcommand help text for AgentWrappers commands, split out of the
/// central `subcommandUsage` switch (programa.swift) so each domain's
/// help text lives next to its command descriptors. Refs #101.
func agentWrapperSubcommandUsage(_ command: String) -> String? {
switch command {
case "claude-teams":
return String(localized: "cli.claude-teams.usage", defaultValue: """
Usage: programa claude-teams [claude-args...]

Launch Claude Code with agent teams enabled.

This command:
- defaults Claude teammate mode to auto
- sets a tmux-like environment so Claude auto mode uses programa splits
- sets CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1
- prepends a private tmux shim to PATH
- forwards all remaining arguments to claude

The tmux shim translates supported tmux window/pane commands into programa
workspace and split operations in the current programa session.

Examples:
programa claude-teams
programa claude-teams --continue
programa claude-teams --model sonnet
""")
case "omo":
return String(localized: "cli.omo.usage", defaultValue: """
Usage: programa omo [opencode-args...]

Launch OpenCode with oh-my-openagent in a programa-aware environment.

oh-my-openagent orchestrates multiple AI models as specialized agents in
parallel. This command sets up a tmux shim so agent panes become native
programa splits with sidebar metadata and notifications.

This command:
- sets a tmux-like environment so oh-my-openagent uses programa splits
- prepends a private tmux shim to PATH
- forwards all remaining arguments to opencode

The tmux shim translates tmux window/pane commands into programa workspace
and split operations in the current programa session.

Examples:
programa omo
programa omo --continue
programa omo --model claude-sonnet-4-6
""")
case "omx":
return String(localized: "cli.omx.usage", defaultValue: """
Usage: programa omx [omx-args...]

Launch Oh My Codex (OMX) with native programa pane integration.

OMX is a multi-agent orchestration layer for OpenAI Codex CLI. This
command sets up a tmux shim so OMX team mode, HUD, and agent panes
become native programa splits.

This command:
- sets a tmux-like environment so OMX uses programa splits
- prepends a private tmux shim to PATH
- forwards all remaining arguments to omx

Install: npm install -g oh-my-codex

Examples:
programa omx
programa omx --madmax --high
programa omx team
""")
case "omc":
return String(localized: "cli.omc.usage", defaultValue: """
Usage: programa omc [omc-args...]

Launch Oh My Claude Code (OMC) with native programa pane integration.

OMC is a multi-agent orchestration system for Claude Code with
specialized agents, smart model routing, and team pipelines. This
command sets up a tmux shim so OMC team mode and agent panes become
native programa splits.

This command:
- sets a tmux-like environment so OMC uses programa splits
- prepends a private tmux shim to PATH
- injects NODE_OPTIONS restore module for Claude compatibility
- forwards all remaining arguments to omc

Install: npm install -g oh-my-claude-sisyphus

Examples:
programa omc
programa omc team 3:claude "implement feature"
programa omc --watch
""")
default:
return nil
}
}
}
92 changes: 91 additions & 1 deletion CLI/CLI+Browser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import LocalAuthentication
import Security
#endif

extension CMUXCLI {
extension ProgramaCLI {
func runBrowserCommand(
commandArgs: [String],
client: SocketClient,
Expand Down Expand Up @@ -1307,4 +1307,94 @@ extension CMUXCLI {

throw CLIError(message: "Unsupported browser subcommand: \(subcommand)")
}

/// Subcommand help text for Browser commands, split out of the
/// central `subcommandUsage` switch (programa.swift) so each domain's
/// help text lives next to its command descriptors. Refs #101.
func browserSubcommandUsage(_ command: String) -> String? {
switch command {
case "browser":
return """
Usage: programa browser [--surface <id|ref|index> | <surface>] <subcommand> [args]

Browser automation commands. Most subcommands require a surface handle.
A surface can be passed as `--surface <handle>` or as the first positional token.
`open`/`open-split`/`new`/`identify` can run without an explicit surface.

Subcommands:
open|open-split|new [url] [--workspace <id|ref|index>] [--window <id|ref|index>]
open/open-split/new default to $PROGRAMA_WORKSPACE_ID when --workspace is omitted and --window is not set
goto|navigate <url> [--snapshot-after]
back|forward|reload [--snapshot-after]
url|get-url
focus-webview | is-webview-focused
snapshot [--interactive|-i] [--cursor] [--compact] [--max-depth <n>] [--selector <css>]
eval [--script <js> | <js>]
wait [--selector <css>] [--text <text>] [--url-contains <text>|--url <text>] [--load-state <interactive|complete>] [--function <js>] [--timeout-ms <ms>|--timeout <seconds>]
click|dblclick|hover|focus|check|uncheck|scroll-into-view [--selector <css> | <css>] [--snapshot-after]
type|fill [--selector <css> | <css>] [--text <text> | <text>] [--snapshot-after]
press|key|keydown|keyup [--key <key> | <key>] [--snapshot-after]
select [--selector <css> | <css>] [--value <value> | <value>] [--snapshot-after]
scroll [--selector <css>] [--dx <n>] [--dy <n>] [--snapshot-after]
screenshot [--out <path>]
get <url|title|text|html|value|attr|count|box|styles> [...]
text|html|value|count|box|styles|attr: [--selector <css> | <css>]
attr: [--attr <name> | <name>]
styles: [--property <name>]
is <visible|enabled|checked> [--selector <css> | <css>]
find <role|text|label|placeholder|alt|title|testid|first|last|nth> [...]
role: [--name <text>] [--exact] <role>
text|label|placeholder|alt|title|testid: [--exact] <text>
first|last: [--selector <css> | <css>]
nth: [--index <n> | <n>] [--selector <css> | <css>]
frame <main|selector> [--selector <css>]
dialog <accept|dismiss> [text]
download [wait] [--path <path>] [--timeout-ms <ms>|--timeout <seconds>]
cookies <get|set|clear> [--name <name>] [--value <value>] [--url <url>] [--domain <domain>] [--path <path>] [--expires <unix>] [--secure] [--all]
storage <local|session> <get|set|clear> [...]
tab <new|list|switch|close|<index>> [...]
console <list|clear>
errors <list|clear>
highlight [--selector <css> | <css>]
state <save|load> <path>
addinitscript|addscript [--script <js> | <js>]
addstyle [--css <css> | <css>]
viewport <width> <height>
geolocation|geo <latitude> <longitude>
offline <true|false>
trace <start|stop> [path]
network <route|unroute|requests> ...
route <pattern> [--abort] [--body <text>]
unroute <pattern>
screencast <start|stop>
input <mouse|keyboard|touch> [args...]
input_mouse | input_keyboard | input_touch
identify [--surface <id|ref|index>]

Example:
programa browser open https://example.com
programa browser surface:1 navigate https://google.com
programa browser --surface surface:1 snapshot --interactive
"""
// Legacy browser aliases — point users to `programa browser --help`
case "open-browser":
return "Legacy alias for 'programa browser open'. Run 'programa browser --help' for details."
case "navigate":
return "Legacy alias for 'programa browser navigate'. Run 'programa browser --help' for details."
case "browser-back":
return "Legacy alias for 'programa browser back'. Run 'programa browser --help' for details."
case "browser-forward":
return "Legacy alias for 'programa browser forward'. Run 'programa browser --help' for details."
case "browser-reload":
return "Legacy alias for 'programa browser reload'. Run 'programa browser --help' for details."
case "get-url":
return "Legacy alias for 'programa browser get-url'. Run 'programa browser --help' for details."
case "focus-webview":
return "Legacy alias for 'programa browser focus-webview'. Run 'programa browser --help' for details."
case "is-webview-focused":
return "Legacy alias for 'programa browser is-webview-focused'. Run 'programa browser --help' for details."
default:
return nil
}
}
}
Loading
Loading