Skip to main content
ClaudeWave
Skill1.9k estrellas del repoactualizado 3d ago

penguin-orchestration

Drive PenguinHarness itself from a shell — list and create agents and sessions, send and steer messages mid-flight, and query costs and scheduled tasks via the penguin CLI over the local server.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/Prism-Shadow/penguin-harness /tmp/penguin-orchestration && cp -r /tmp/penguin-orchestration/packages/skills/skills/penguin-orchestration ~/.claude/skills/penguin-orchestration
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Penguin Orchestration

The `penguin` CLI is a thin client of the PenguinHarness server. Inside a harness agent session it reaches the same server that is running you, so you can orchestrate the platform yourself: list and create agents, start conversations with them, steer those conversations while they run, and query costs and scheduled tasks.

## Before you start

If the user's message only invokes this skill (e.g. "use penguin-orchestration skill") without a concrete request, ask the user what they want to orchestrate. Read-only commands (`project ls`, `agent ls`, `ls`, `logs`, `cost`, `schedule ls`) are always safe; do not create agents, start sessions or send messages until the goal is clear.

## How the connection works

- **Inside a harness agent session** (you, now): every command subprocess has `PENGUIN_API_URL`, `PENGUIN_API_TOKEN`, `PENGUIN_PROJECT_ID`, `PENGUIN_AGENT_ID` and `PENGUIN_SESSION_ID` injected, so `penguin` commands automatically reach your own server with your project and agent as the defaults — no login step.
- **Outside an agent** (a human shell): the CLI attaches to the running local server via its lock file, or auto-starts one; the local `<data-root>/api-token` file (0600) authenticates it.
- You are operating the same server that runs you: sessions and agents you create appear live in the web UI, where the user sees and owns everything you spawn.
- The injected token is admin-equivalent. Act accordingly: stick to what the task requires, and prefer read-only commands until a mutation is clearly needed.

## Orient first

Before mutating anything, see what exists:

```bash
penguin project ls        # projects on this server
penguin agent ls          # agents in the current project
penguin ls --json         # the project's sessions, with running state
```

`--json` on any listing gives machine-parseable output.

## Command surface

```
penguin run -m <msg> [--project-id <id>] [--agent-id <id>] [--workspace <path>]
            [--model-id <id> --provider <p>] [--approve <mode>] [--thinking <level>]
            [--session <session_id>] [--background] [--timeout <duration>]
            [--goal [budget]] [--json]
penguin ls [--project-id <id>] [--agent-id <id>] [--days <n>] [-a|--all] [--json]
penguin input [session_id] [-m <text>] [--timeout <duration>]
              [--project-id <id>] [--agent-id <id>] [--json] [--server <url>]
penguin logs [session_id] [--project-id <id>] [--agent-id <id>] [--tail <n>]
             [-f|--follow] [--timeout <duration>] [--json]
penguin agent ls [--project-id <id>] [--json]
penguin agent create --agent-id <id> [--name <s>] [--description <s>] [--skills <a,b>]
                     [--project-id <id>] [--json]
penguin project ls [--json]
penguin cost [--days <n>] [--from <d> --to <d>] [--by date|agent|model|session]
             [--project-id <id>] [--agent-id <id>] [--json]
penguin schedule ls [--project-id <id>] [--agent-id <id>] [--json]
penguin schedule add <name> --prompt <s> --start-at <ISO|now> [--period <duration>]
                    [--end-at <ISO>] [--session-id <id> | --workspace <path>
                    [--model-id <id> --provider <p>]] [--disabled]
                    [--project-id <id>] [--agent-id <id>]
penguin schedule update <name> [<same field flags>] [--enable|--disable]
                    [--project-id <id>] [--agent-id <id>]
penguin schedule rm <name> [--project-id <id>] [--agent-id <id>]
```

- `run` starts a task and waits, rendering the conversation, unless `--background` — then it prints the new session id and exits while the server keeps running the task. `--session <session_id>` runs the task in an existing session instead of creating one; the model reference is the `--provider` + `--model-id` pair (both or neither); `--goal [budget]` runs in goal mode — the session loops until the agent declares the goal complete, with an optional spend budget.
- **Caller-context defaults.** Inside a harness agent, a session-creating `run` fills every field you leave unspecified from your own live session, per field independently: `--workspace`, the `--model-id`/`--provider` pair, `--approve` and `--thinking` inherit the caller's values — the same convention as `run_subagent` parent inheritance. Precedence: explicit flag > caller value > plain fallback (cwd, the Project default model, `allow-all`, none — used wholesale if the caller lookup fails, with a dim stderr note). So inside an agent, `penguin run -m "..."` alone typically does the right thing; pass flags only to diverge.
- `--timeout <duration>` (`30s`, `5m`, `2h`, or bare seconds) bounds the wait of a foreground `run`, an `input`, or a `logs -f`. Expiry is a soft yield, not an error: the command exits 0 while the task keeps running server-side, printing a still-running note that names the follow-up commands (`--json` prints `{sessionId, status: "running", text}` with the text so far). `--timeout 0` (also `0s`) returns immediately after delivery — the same note without collected text (`--json`: `{sessionId, status: "running"}`); on a bare poll it snapshots a running session instantly. `run --background` stays the idiomatic fire-and-forget for new tasks and rejects `--timeout`; `logs --timeout` requires `-f`.
- `input` with `-m` steers a **running** session mid-turn (the agent absorbs it as a course correction within the current task) or starts a new turn on an idle one; it waits for the reply unless a `--timeout` bounds the wait (`--timeout 0` = deliver and return at once). Bare `input [session_id]` (no `-m`) **polls**: it prints the session's most recent complete assistant text — an idempotent snapshot that skips user/thinking/tool output and never touches approvals, mirroring `input_subagent`'s empty-prompt semantics. A running session is waited on first (bounded by `--timeout`, else indefinitely); a session with no reply yet prints `(no assistant reply yet)`. `--json` reports `{sessionId, status, text}` — `idle`/`running` when polling, `completed`/`aborted