Skip to content
Open
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
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ RUN apt-get update && \

RUN bash /opt/install-scripts/install-go.sh "${GO_VERSION}"
RUN bash /opt/install-scripts/install-nodejs.sh
RUN npm install -g @openai/codex @anthropic-ai/claude-code && npm cache clean --force
RUN bash /opt/install-scripts/install-postgresql-client.sh
RUN bash /opt/install-scripts/install-gomigrate.sh
RUN bash /opt/install-scripts/install-protoc.sh
Expand Down
60 changes: 60 additions & 0 deletions docs/components/Claude.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { CardGrid, LinkCard } from "@astrojs/starlight/components";

<CardGrid>
<LinkCard title="Run Claude Agent" href="#run-claude-agent" description="Runs a Claude Managed Agent in Anthropic’s managed environment and waits until the session is idle or terminated." />
<LinkCard title="Run Claude Code" href="#run-claude-code" description="Run Claude Code non-interactively on a local workspace" />
<LinkCard title="Text Prompt" href="#text-prompt" description="Generate a response using Anthropic's Claude models via the Messages API" />
</CardGrid>

Expand Down Expand Up @@ -55,6 +56,65 @@ Emits a finished payload with **session** status, **session id**, and the final
}
```

<a id="run-claude-code"></a>

## Run Claude Code

**Component key:** `claude.runClaudeCode`

The Run Claude Code component runs the Claude Code CLI in non-interactive print mode from the SuperPlane app container.

### Use Cases

- **Repository analysis**: Ask Claude Code to inspect code and summarize risks
- **Automated implementation tasks**: Run coding tasks from upstream workflow events
- **Code review**: Generate review feedback or remediation guidance
- **Local workflow automation**: Use SuperPlane events to start Claude Code tasks in a mounted workspace

### Configuration

- **Model**: Claude Code model alias or full model name. Defaults to `sonnet`.
- **Prompt**: The task sent to Claude Code (supports expressions).
- **Permission Mode**: Claude Code permission mode. Defaults to plan mode for read-only behavior. Write-capable and bypass modes should only be used in trusted local/dev environments.
- **Working Directory**: Directory used as the Claude Code process working directory. Defaults to `/app`.
- **Max Turns**: Maximum number of agentic turns in non-interactive mode. Defaults to 3.
- **Timeout**: Maximum runtime in seconds. Defaults to 600 seconds.

### Output

Routes to one of two channels:
- **success**: Claude Code exits with code 0 and does not report an error result
- **failed**: Claude Code exits non-zero, times out, or reports an error result

The payload includes the final Claude Code result text, exit code, timeout flag, selected model, permission mode, working directory, max turns, duration, parsed JSON response when available, and stderr/stdout for failures.

### Notes

- Requires the Claude Code CLI on the app container PATH.
- Requires a valid Claude API key configured on the Claude integration.
- The API key is passed only to the Claude Code subprocess and is never emitted in the payload.
- The component uses Claude Code `--bare` and `--no-session-persistence` modes to reduce local side effects.

### Example Output

```json
{
"data": {
"durationMs": 10180,
"exitCode": 0,
"isError": false,
"maxTurns": 3,
"model": "sonnet",
"permissionMode": "plan",
"text": "I inspected the requested files and drafted the implementation plan.",
"timedOut": false,
"workingDirectory": "/app"
},
"timestamp": "2026-05-30T12:00:00Z",
"type": "claude.codeAgent.finished"
}
```

<a id="text-prompt"></a>

## Text Prompt
Expand Down
57 changes: 57 additions & 0 deletions docs/components/OpenAI.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,66 @@ import { CardGrid, LinkCard } from "@astrojs/starlight/components";
## Actions

<CardGrid>
<LinkCard title="Run Codex Agent" href="#run-codex-agent" description="Run OpenAI Codex CLI non-interactively on a local workspace" />
<LinkCard title="Text Prompt" href="#text-prompt" description="Generate a text response using OpenAI" />
</CardGrid>

<a id="run-codex-agent"></a>

## Run Codex Agent

**Component key:** `openai.runCodexAgent`

The Run Codex Agent component runs the OpenAI Codex CLI in non-interactive mode from the SuperPlane app container.

### Use Cases

- **Repository analysis**: Ask Codex to inspect a codebase and summarize findings
- **Automated code review**: Run targeted review prompts against a mounted repository
- **Local coding tasks**: Let Codex propose or make workspace changes when write-capable sandbox modes are explicitly selected
- **Workflow automation**: Convert upstream events into coding-agent tasks

### Configuration

- **Model**: Codex model to use. Defaults to `gpt-5.1-codex-mini`.
- **Prompt**: The task sent to Codex (supports expressions).
- **Sandbox**: CLI sandbox mode. Defaults to read-only. Workspace write and full access modes should only be used in trusted local/dev environments.
- **Working Directory**: Directory passed to Codex as the workspace root. Defaults to `/app`.
- **Timeout**: Maximum runtime in seconds. Defaults to 600 seconds.

### Output

Routes to one of two channels:
- **success**: Codex exits with code 0
- **failed**: Codex exits non-zero or times out

The payload includes the final Codex message, exit code, timeout flag, selected model, sandbox mode, working directory, duration, parsed JSONL events when available, and stderr/stdout for failures.

### Notes

- Requires the Codex CLI on the app container PATH.
- Requires a valid OpenAI API key configured on the OpenAI integration.
- The API key is passed only to the Codex subprocess and is never emitted in the payload.
- The component runs locally in the SuperPlane app container, so sandbox modes should be chosen carefully.

### Example Output

```json
{
"data": {
"durationMs": 12420,
"exitCode": 0,
"model": "gpt-5.1-codex-mini",
"sandbox": "read-only",
"text": "I reviewed the repository and found no obvious regression in the requested files.",
"timedOut": false,
"workingDirectory": "/app"
},
"timestamp": "2026-05-30T12:00:00Z",
"type": "openai.codexAgent.finished"
}
```

<a id="text-prompt"></a>

## Text Prompt
Expand Down
88 changes: 88 additions & 0 deletions pkg/integrations/agentcli/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package agentcli

import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"time"
)

type Command struct {
Name string
Args []string
Dir string
Env map[string]string
Timeout time.Duration
}

type Result struct {
Stdout string
Stderr string
ExitCode int
TimedOut bool
Duration time.Duration
}

type Runner interface {
Run(ctx context.Context, command Command) (Result, error)
}

type OSRunner struct{}

func (r OSRunner) Run(ctx context.Context, command Command) (Result, error) {
if command.Name == "" {
return Result{}, fmt.Errorf("command name is required")
}

if command.Timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, command.Timeout)
defer cancel()
}

cmd := exec.CommandContext(ctx, command.Name, command.Args...)
cmd.Dir = command.Dir
cmd.Env = commandEnvironment(command.Env)

var stdout bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

startedAt := time.Now()
err := cmd.Run()
result := Result{
Stdout: stdout.String(),
Stderr: stderr.String(),
Duration: time.Since(startedAt),
}

if errors.Is(ctx.Err(), context.DeadlineExceeded) {
result.TimedOut = true
result.ExitCode = -1
return result, nil
}

if err == nil {
return result, nil
}

var exitErr *exec.ExitError
if errors.As(err, &exitErr) {
result.ExitCode = exitErr.ExitCode()
return result, nil
}

return result, err
}

func commandEnvironment(overrides map[string]string) []string {
env := os.Environ()
for key, value := range overrides {
env = append(env, key+"="+value)
}
return env
}
1 change: 1 addition & 0 deletions pkg/integrations/claude/claude.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (i *Claude) Actions() []core.Action {
return []core.Action{
&TextPrompt{},
&runagent.RunAgent{},
&RunClaudeCode{},
}
}

Expand Down
Loading