From 57ba468fead5ea20e3ee89b9296b19f57b0c5484 Mon Sep 17 00:00:00 2001 From: Harshit Singh Bhandari Date: Fri, 3 Jul 2026 18:11:15 +0530 Subject: [PATCH] feat(skills): add using-ao skill, install it under the data dir, and wire it into session prompts (#2365) * feat(prompt): point sessions at using-ao skill for CLI usage Append a short standing-prompt pointer to skills/using-ao/SKILL.md so orchestrator and worker sessions read the skill catalog before using the ao CLI, instead of inlining the whole command surface. * docs(skills): add using-ao skill cataloging the ao CLI Full command catalog sourced verbatim from 'ao --help' recursively: SKILL.md (top-level catalog), commands/*.md (one per command with every subcommand, flag, and examples), and references.md (natural-language to command table). * feat(skills): install using-ao skill under the data dir on daemon boot A repo-relative skills/ path only resolves when a worker's project is the AO repo itself; the ao CLI is used in every session regardless of project. Move the skill into the Go module, embed it, and clobber-install it into /skills/using-ao at daemon boot (before any session spawns, so no locking is needed). The embedded copy is the single source of truth: a new daemon build always refreshes it, so there is no version marker to drift. Flip the session-prompt pointer to the absolute installed path so it resolves from any project's worktree. * fix(skillassets): tighten install perms to satisfy gosec golangci-lint gosec flagged G301 (dir perms) and G306 (file perms). Use 0o750 for dirs and 0o600 for files, matching the repo convention for daemon-owned single-user state. * Update preview.md with dev server instructions Added note about using the correct URL for the dev server. --------- Co-authored-by: Vaibhaav Tiwari <155460282+Vaibhaav-Tiwari@users.noreply.github.com> --- backend/internal/daemon/daemon.go | 8 + backend/internal/session_manager/manager.go | 17 +- .../internal/session_manager/manager_test.go | 3 + backend/internal/skillassets/skillassets.go | 65 ++++++ .../internal/skillassets/skillassets_test.go | 41 ++++ .../internal/skillassets/using-ao/SKILL.md | 36 +++ .../skillassets/using-ao/commands/doctor.md | 27 +++ .../skillassets/using-ao/commands/import.md | 35 +++ .../using-ao/commands/orchestrator.md | 40 ++++ .../skillassets/using-ao/commands/preview.md | 62 ++++++ .../skillassets/using-ao/commands/project.md | 163 ++++++++++++++ .../skillassets/using-ao/commands/review.md | 45 ++++ .../skillassets/using-ao/commands/send.md | 28 +++ .../skillassets/using-ao/commands/session.md | 206 ++++++++++++++++++ .../skillassets/using-ao/commands/spawn.md | 38 ++++ .../skillassets/using-ao/commands/start.md | 27 +++ .../skillassets/using-ao/commands/status.md | 27 +++ .../skillassets/using-ao/commands/stop.md | 28 +++ .../skillassets/using-ao/references.md | 26 +++ 19 files changed, 921 insertions(+), 1 deletion(-) create mode 100644 backend/internal/skillassets/skillassets.go create mode 100644 backend/internal/skillassets/skillassets_test.go create mode 100644 backend/internal/skillassets/using-ao/SKILL.md create mode 100644 backend/internal/skillassets/using-ao/commands/doctor.md create mode 100644 backend/internal/skillassets/using-ao/commands/import.md create mode 100644 backend/internal/skillassets/using-ao/commands/orchestrator.md create mode 100644 backend/internal/skillassets/using-ao/commands/preview.md create mode 100644 backend/internal/skillassets/using-ao/commands/project.md create mode 100644 backend/internal/skillassets/using-ao/commands/review.md create mode 100644 backend/internal/skillassets/using-ao/commands/send.md create mode 100644 backend/internal/skillassets/using-ao/commands/session.md create mode 100644 backend/internal/skillassets/using-ao/commands/spawn.md create mode 100644 backend/internal/skillassets/using-ao/commands/start.md create mode 100644 backend/internal/skillassets/using-ao/commands/status.md create mode 100644 backend/internal/skillassets/using-ao/commands/stop.md create mode 100644 backend/internal/skillassets/using-ao/references.md diff --git a/backend/internal/daemon/daemon.go b/backend/internal/daemon/daemon.go index 891838815..4f798cb7c 100644 --- a/backend/internal/daemon/daemon.go +++ b/backend/internal/daemon/daemon.go @@ -24,6 +24,7 @@ import ( importsvc "github.com/aoagents/agent-orchestrator/backend/internal/service/importer" notificationsvc "github.com/aoagents/agent-orchestrator/backend/internal/service/notification" projectsvc "github.com/aoagents/agent-orchestrator/backend/internal/service/project" + "github.com/aoagents/agent-orchestrator/backend/internal/skillassets" "github.com/aoagents/agent-orchestrator/backend/internal/storage/sqlite" "github.com/aoagents/agent-orchestrator/backend/internal/terminal" ) @@ -61,6 +62,13 @@ func Run() error { } defer func() { _ = store.Close() }() + // Refresh the embedded using-ao skill into the data dir so worker sessions + // in any project can read the ao CLI catalog from a stable absolute path. + // Non-fatal: the skill is an enhancement over `ao --help`, not required. + if err := skillassets.Install(cfg.DataDir); err != nil { + log.Warn("install using-ao skill", "err", err) + } + telemetrySink := newTelemetrySink(cfg, store, log) defer func() { _ = telemetrySink.Close(context.Background()) }() telemetrySink.Emit(context.Background(), ports.TelemetryEvent{ diff --git a/backend/internal/session_manager/manager.go b/backend/internal/session_manager/manager.go index 6a9c887e4..4a808c24a 100644 --- a/backend/internal/session_manager/manager.go +++ b/backend/internal/session_manager/manager.go @@ -17,6 +17,7 @@ import ( "github.com/aoagents/agent-orchestrator/backend/internal/domain" "github.com/aoagents/agent-orchestrator/backend/internal/ports" aoprocess "github.com/aoagents/agent-orchestrator/backend/internal/process" + "github.com/aoagents/agent-orchestrator/backend/internal/skillassets" ) // Sentinel errors returned by the Session Manager; callers match them with @@ -1000,7 +1001,21 @@ func (m *Manager) buildSystemPrompt(ctx context.Context, kind domain.SessionKind if base == "" { return "", nil } - return base + systemPromptGuard, nil + return base + m.aoSkillPointer() + systemPromptGuard, nil +} + +// aoSkillPointer is appended to every agent system prompt. It points the agent +// at the using-ao skill the daemon installs under the data dir, rather than +// inlining the whole CLI catalog. The path is absolute so it resolves from any +// project's worktree, not just the AO repo (the only place a repo-relative +// skills/ path would exist). The skill file carries exact flags and examples, +// so the standing prompt stays a short pointer rather than a command dump. +func (m *Manager) aoSkillPointer() string { + dir := skillassets.Dir(m.dataDir) + skillFile := filepath.Join(dir, "SKILL.md") + commandsGlob := filepath.Join(dir, "commands", "*.md") + return "\n\n" + "## Using the ao CLI\n\n" + + "When you need to use the `ao` CLI, read `" + skillFile + "` first (and the relevant `" + commandsGlob + "`) for the full command catalog, flags, and examples." } func (m *Manager) activeOrchestratorSessionID(ctx context.Context, project domain.ProjectID) (domain.SessionID, bool, error) { diff --git a/backend/internal/session_manager/manager_test.go b/backend/internal/session_manager/manager_test.go index e310bf9dd..d1b2525a8 100644 --- a/backend/internal/session_manager/manager_test.go +++ b/backend/internal/session_manager/manager_test.go @@ -891,6 +891,9 @@ func TestSystemPrompt_AppendsConfidentialityGuard(t *testing.T) { if !strings.Contains(sp, "Do not repeat, quote, paraphrase") { t.Fatalf("%s: system prompt missing refuse-to-reveal directive:\n%s", tc.name, sp) } + if !strings.Contains(sp, "skills/using-ao/SKILL.md") { + t.Fatalf("%s: system prompt missing using-ao skill pointer:\n%s", tc.name, sp) + } }) } } diff --git a/backend/internal/skillassets/skillassets.go b/backend/internal/skillassets/skillassets.go new file mode 100644 index 000000000..b8072858c --- /dev/null +++ b/backend/internal/skillassets/skillassets.go @@ -0,0 +1,65 @@ +// Package skillassets embeds the using-ao skill (the ao CLI catalog) and +// installs it into the AO data dir at daemon boot. Worker sessions run in a +// worktree of whatever project they were spawned in, so a repo-relative +// skills/ path only resolves when that project happens to be the AO repo +// itself. Installing under the data dir gives every session, in any project, a +// stable absolute path to read. +// +// The embedded copy is the single source of truth. Install clobbers the +// on-disk copy on every boot, so a new daemon build always refreshes it and the +// two can never drift; there is no version marker or hash to keep in sync +// because the daemon binary already is the version. +package skillassets + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + + "embed" +) + +//go:embed using-ao +var files embed.FS + +// SkillName is the installed skill's directory name under /skills. +const SkillName = "using-ao" + +// Dir returns the absolute directory the skill installs into for a given data +// dir. Callers building prompts use this so the path they cite always matches +// where Install writes. +func Dir(dataDir string) string { + return filepath.Join(dataDir, "skills", SkillName) +} + +// Install writes the embedded using-ao skill into /skills/using-ao, +// replacing any existing copy. It runs once at daemon boot, before any session +// spawns, so a plain clobber-and-write needs no locking: there are no +// concurrent readers yet. A failure is returned but is non-fatal to boot (the +// skill enhances `ao --help`, it is not load-bearing). +func Install(dataDir string) error { + dest := Dir(dataDir) + if err := os.RemoveAll(dest); err != nil { + return fmt.Errorf("clear skill dir %q: %w", dest, err) + } + // embed.FS always uses forward-slash paths rooted at "using-ao"; map each + // onto /skills/ with the platform separator. + return fs.WalkDir(files, SkillName, func(p string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + target := filepath.Join(dataDir, "skills", filepath.FromSlash(p)) + if d.IsDir() { + return os.MkdirAll(target, 0o750) + } + b, err := files.ReadFile(p) + if err != nil { + return fmt.Errorf("read embedded %q: %w", p, err) + } + if err := os.WriteFile(target, b, 0o600); err != nil { + return fmt.Errorf("write %q: %w", target, err) + } + return nil + }) +} diff --git a/backend/internal/skillassets/skillassets_test.go b/backend/internal/skillassets/skillassets_test.go new file mode 100644 index 000000000..a8d06564b --- /dev/null +++ b/backend/internal/skillassets/skillassets_test.go @@ -0,0 +1,41 @@ +package skillassets + +import ( + "os" + "path/filepath" + "testing" +) + +// TestInstall_WritesSkillAndIsIdempotent: Install must lay down the embedded +// skill (SKILL.md plus a commands file) under /skills/using-ao, and a +// second run must clobber cleanly, leaving no stale files. This is the whole +// contract the daemon boot hook relies on. +func TestInstall_WritesSkillAndIsIdempotent(t *testing.T) { + dataDir := t.TempDir() + + if err := Install(dataDir); err != nil { + t.Fatalf("Install: %v", err) + } + + skillFile := filepath.Join(Dir(dataDir), "SKILL.md") + if b, err := os.ReadFile(skillFile); err != nil { + t.Fatalf("read %s: %v", skillFile, err) + } else if len(b) == 0 { + t.Fatalf("SKILL.md is empty") + } + if _, err := os.Stat(filepath.Join(Dir(dataDir), "commands", "spawn.md")); err != nil { + t.Fatalf("commands/spawn.md missing: %v", err) + } + + // A stale file inside the skill dir must not survive a reinstall (clobber). + stale := filepath.Join(Dir(dataDir), "stale.md") + if err := os.WriteFile(stale, []byte("old"), 0o644); err != nil { + t.Fatalf("seed stale file: %v", err) + } + if err := Install(dataDir); err != nil { + t.Fatalf("reinstall: %v", err) + } + if _, err := os.Stat(stale); !os.IsNotExist(err) { + t.Fatalf("stale file survived reinstall (err=%v)", err) + } +} diff --git a/backend/internal/skillassets/using-ao/SKILL.md b/backend/internal/skillassets/using-ao/SKILL.md new file mode 100644 index 000000000..7be54f5ba --- /dev/null +++ b/backend/internal/skillassets/using-ao/SKILL.md @@ -0,0 +1,36 @@ +--- +name: using-ao +description: Catalog of the AO (Agent Orchestrator) `ao` CLI: spawning workers, managing sessions and projects, sending messages, previewing pages, and daemon control. Use when using the ao CLI, spawning workers, or managing AO sessions in an AO workspace. +trigger: Using the ao CLI in an AO workspace: spawning workers, managing sessions/projects, sending messages, previewing pages. +--- + +# AO CLI Catalog + +`ao` is a thin CLI over the local AO daemon. Every command is `ao --help` for the authoritative flag list. + +| Command | What it does | When to use | Details | +|---|---|---|---| +| `spawn` | Spawn a worker agent in a fresh git worktree | Starting a new task or issue | [commands/spawn.md](commands/spawn.md) | +| `session` | Manage agent sessions (list, kill, rename, restore, etc.) | Inspecting or controlling running/terminated sessions | [commands/session.md](commands/session.md) | +| `project` | Register, inspect, configure, or remove projects | Setting up or managing repos AO knows about | [commands/project.md](commands/project.md) | +| `orchestrator` | List orchestrator sessions | Viewing which sessions are orchestrators | [commands/orchestrator.md](commands/orchestrator.md) | +| `review` | Submit a reviewer result for a worker's PR | Completing a code review loop | [commands/review.md](commands/review.md) | +| `send` | Send a message to a running agent session | Correcting or directing a live agent | [commands/send.md](commands/send.md) | +| `preview` | Open a URL in the desktop browser panel | Demoing a local server or file from inside a session | [commands/preview.md](commands/preview.md) | +| `start` | Fetch (if needed) and open the AO desktop app | Launching the app | [commands/start.md](commands/start.md) | +| `stop` | Stop the AO daemon | Shutting down AO | [commands/stop.md](commands/stop.md) | +| `status` | Show daemon status | Verifying the daemon is up and healthy | [commands/status.md](commands/status.md) | +| `doctor` | Run local health checks | Diagnosing AO setup problems | [commands/doctor.md](commands/doctor.md) | +| `import` | Import projects from a legacy AO install | Migrating from the old flat-file store | [commands/import.md](commands/import.md) | +| `version` | Print version information | Checking installed version | - | +| `completion` | Generate shell completion scripts | Setting up tab completion | - | + +## Conventions + +- Most read commands accept `--json` for machine-readable output. +- `-p / --project` scopes session subcommand lookups to one project. +- Session and project ids are shown by `ao session ls` and `ao project ls`. +- `--agent` is an alias for `--harness` on `ao spawn`. +- Every command accepts `-h / --help` for the full flag list. + +See [references.md](references.md) for natural-language-to-command mappings. diff --git a/backend/internal/skillassets/using-ao/commands/doctor.md b/backend/internal/skillassets/using-ao/commands/doctor.md new file mode 100644 index 000000000..f406cc21b --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/doctor.md @@ -0,0 +1,27 @@ +# ao doctor + +Run local AO health checks. Use this to diagnose setup problems or verify the environment is correctly configured. + +## Syntax + +``` +ao doctor [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output health checks as JSON | - | + +## Examples + +```bash +# Run health checks +ao doctor +``` + +```bash +# Get health check results as JSON +ao doctor --json +``` diff --git a/backend/internal/skillassets/using-ao/commands/import.md b/backend/internal/skillassets/using-ao/commands/import.md new file mode 100644 index 000000000..a2d64721b --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/import.md @@ -0,0 +1,35 @@ +# ao import + +Import reads the legacy Agent Orchestrator flat-file store (`~/.agent-orchestrator`) read-only and ports its projects and per-project settings into the rewrite database. Legacy files are never modified, and a re-run skips rows that already exist, so it is safe to run more than once. The daemon must be stopped before running: it is the sole writer of the database. + +## Syntax + +``` +ao import [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--dry-run` | Parse and report the planned import without writing | - | +| `--from string` | Legacy AO root to read | `~/.agent-orchestrator` | +| `--json` | Output the import report as JSON | - | +| `-y, --yes` | Skip the confirmation prompt (for non-interactive use) | - | + +## Examples + +```bash +# Preview what would be imported without writing anything +ao import --dry-run +``` + +```bash +# Run the import non-interactively +ao import -y +``` + +```bash +# Import from a custom legacy path +ao import --from /tmp/old-agent-orchestrator -y +``` diff --git a/backend/internal/skillassets/using-ao/commands/orchestrator.md b/backend/internal/skillassets/using-ao/commands/orchestrator.md new file mode 100644 index 000000000..9f2f2ceec --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/orchestrator.md @@ -0,0 +1,40 @@ +# ao orchestrator + +Manage orchestrator sessions. + +## Syntax + +``` +ao orchestrator [flags] +``` + +## Subcommands + +--- + +### ao orchestrator ls + +List orchestrator sessions. Aliases: `ls`, `list`. + +**Syntax:** +``` +ao orchestrator ls [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output as JSON | - | + +## Examples + +```bash +# List all orchestrator sessions +ao orchestrator ls +``` + +```bash +# List orchestrator sessions as JSON +ao orchestrator ls --json +``` diff --git a/backend/internal/skillassets/using-ao/commands/preview.md b/backend/internal/skillassets/using-ao/commands/preview.md new file mode 100644 index 000000000..e2de8d586 --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/preview.md @@ -0,0 +1,62 @@ +# ao preview + +Open a URL in the desktop browser panel for the current session. With no argument it opens the workspace's static entry point, falling back to this session's existing preview target when no entry point exists. A local file can be opened by its absolute `file://` URL. Use `ao preview clear` to empty the panel. + +## Syntax + +``` +ao preview [url] [flags] +ao preview [command] +``` + +## Flags + +No flags beyond `-h / --help`. + +## Subcommands + +--- + +### ao preview (bare form) + +Open the workspace's static entry point, or the session's existing preview target. + +**Examples:** + +```bash +# Open the default entry point for this session's workspace +ao preview +``` + +```bash +# Open a local dev server +ao preview http://localhost:5173 +(or wherever the dev server is running) +``` + +```bash +# Open a local HTML file +ao preview file://$(pwd)/index.html +``` + +--- + +### ao preview clear + +Clear the desktop browser panel for the current session. + +**Syntax:** +``` +ao preview clear [flags] +``` + +**Flags:** + +No flags beyond `-h / --help`. + +**Examples:** + +```bash +# Clear the preview panel +ao preview clear +``` diff --git a/backend/internal/skillassets/using-ao/commands/project.md b/backend/internal/skillassets/using-ao/commands/project.md new file mode 100644 index 000000000..a58bac309 --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/project.md @@ -0,0 +1,163 @@ +# ao project + +Manage projects: register repos, inspect, configure per-project settings, and remove. + +## Syntax + +``` +ao project [args] [flags] +``` + +## Subcommands + +--- + +### ao project add + +Register a local git repo as a project so sessions can be spawned in it. The path must be an existing git repository on disk. With `--as-workspace`, the path may be a parent folder containing direct child git repositories; AO initializes/adopts the parent as the root repo and gitignores children. + +**Syntax:** +``` +ao project add [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--as-workspace` | Register a parent folder as a workspace project (root-as-repo plus direct child repos) | - | +| `--id string` | Project id | Derived by the daemon from the path | +| `--name string` | Display name | - | +| `--orchestrator-agent string` | Default orchestrator session agent | - | +| `--path string` | Absolute path to the local git repo | Required | +| `--worker-agent string` | Default worker session agent | - | + +**Examples:** + +```bash +# Register a repo as a project +ao project add --path /Users/harshit/Downloads/side-quests/agent-orchestrator --name "agent-orchestrator" +``` + +```bash +# Register a workspace (parent folder containing multiple repos) +ao project add --path /Users/harshit/Downloads/side-quests --as-workspace --name "side-quests" +``` + +--- + +### ao project ls + +List registered projects. Aliases: `ls`, `list`. + +**Syntax:** +``` +ao project ls [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output projects as JSON | - | + +**Examples:** + +```bash +# List all registered projects +ao project ls +``` + +--- + +### ao project get + +Fetch one registered project. + +**Syntax:** +``` +ao project get [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output project as JSON | - | + +**Examples:** + +```bash +# Get details for the agent-orchestrator project +ao project get agent-orchestrator +``` + +--- + +### ao project rm + +Remove a registered project. Aliases: `rm`, `remove`, `delete`. + +**Syntax:** +``` +ao project rm [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output removal result as JSON | - | +| `-y, --yes` | Skip confirmation prompt | - | + +**Examples:** + +```bash +# Remove a project (with confirmation) +ao project rm agent-orchestrator +``` + +```bash +# Remove without prompt +ao project rm agent-orchestrator -y +``` + +--- + +### ao project set-config + +Replace a project's per-project config (branch, session prefix, env, symlinks, post-create, agent model/permissions, role overrides). The config is resolved when a session spawns. Set fields via flags, pass the whole object with `--config-json`, or `--clear` to remove all config. + +**Syntax:** +``` +ao project set-config [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--clear` | Clear all config | - | +| `--config-json string` | Full config as a JSON object (overrides field flags) | - | +| `--default-branch string` | Base branch new session worktrees are created from | - | +| `--env stringArray` | Env var `KEY=VALUE` forwarded into sessions (repeatable) | - | +| `--json` | Output the updated project as JSON | - | +| `--model string` | Agent model override (e.g. `claude-opus-4-5`) | - | +| `--orchestrator-agent string` | Harness override for orchestrator sessions | - | +| `--permission string` | Permission mode: `default`, `accept-edits`, `auto`, `bypass-permissions` | - | +| `--post-create stringArray` | Command to run after workspace creation (repeatable) | - | +| `--session-prefix string` | Displayed session-id prefix | - | +| `--symlink stringArray` | Repo-relative path to symlink into workspaces (repeatable) | - | +| `--worker-agent string` | Harness override for worker sessions | - | + +**Examples:** + +```bash +# Set default branch and model for a project +ao project set-config agent-orchestrator --default-branch main --model claude-opus-4-5 +``` + +```bash +# Set an env var and a post-create command +ao project set-config agent-orchestrator --env "NODE_ENV=development" --post-create "npm install" +``` diff --git a/backend/internal/skillassets/using-ao/commands/review.md b/backend/internal/skillassets/using-ao/commands/review.md new file mode 100644 index 000000000..9677ad5fc --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/review.md @@ -0,0 +1,45 @@ +# ao review + +Manage AO code reviews of a worker's PR. + +## Syntax + +``` +ao review [args] [flags] +``` + +## Subcommands + +--- + +### ao review submit + +Record a reviewer's result for a worker's PR. + +**Syntax:** +``` +ao review submit [worker-session-id] [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--body string` | Review body: a path to a Markdown file, or `-` to read from stdin | - | +| `--review-id string` | Id of the GitHub PR review just posted (the `.id` from the `gh api` POST that created the review) | - | +| `--reviews string` | JSON review results array or object: a path, or `-` to read from stdin | - | +| `--run string` | Review run id | Required | +| `--session string` | Worker session id (or pass it as the positional argument) | - | +| `--verdict string` | Review verdict: `approved` or `changes_requested` | Required | + +## Examples + +```bash +# Submit an approved review for session mer-3 +ao review submit mer-3 --run review-run-1 --verdict approved +``` + +```bash +# Submit a changes-requested review with a body from stdin +echo "Please fix the null check on line 42." | ao review submit --session mer-3 --run review-run-1 --verdict changes_requested --body - +``` diff --git a/backend/internal/skillassets/using-ao/commands/send.md b/backend/internal/skillassets/using-ao/commands/send.md new file mode 100644 index 000000000..08565d3be --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/send.md @@ -0,0 +1,28 @@ +# ao send + +Send a message to a running agent session. Use this to correct or direct a live agent mid-stream without killing and respawning it. + +## Syntax + +``` +ao send [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--message string` | Message body | Required | +| `--session string` | Session id | Required | + +## Examples + +```bash +# Send a correction to a running session +ao send --session mer-3 --message "Focus only on the backend; ignore frontend files." +``` + +```bash +# Give the agent new instructions mid-task +ao send --session mer-3 --message "The issue is in session_manager.go line 142, not in the CLI. Investigate there." +``` diff --git a/backend/internal/skillassets/using-ao/commands/session.md b/backend/internal/skillassets/using-ao/commands/session.md new file mode 100644 index 000000000..29ba2ae3b --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/session.md @@ -0,0 +1,206 @@ +# ao session + +Manage agent sessions: list, inspect, rename, kill, restore, clean up, and claim PRs. + +## Syntax + +``` +ao session [args] [flags] +``` + +## Subcommands + +--- + +### ao session ls + +List sessions. + +**Syntax:** +``` +ao session ls [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `-a, --all` | Include orchestrator sessions | - | +| `--include-terminated` | Include terminated sessions | - | +| `--json` | Output as JSON | - | +| `-p, --project string` | Filter by project ID | - | + +**Examples:** + +```bash +# List all active worker sessions +ao session ls +``` + +```bash +# List all sessions including terminated, scoped to one project +ao session ls --include-terminated -p agent-orchestrator +``` + +--- + +### ao session get + +Fetch one session. + +**Syntax:** +``` +ao session get [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output as JSON | - | +| `-p, --project string` | Project id to scope the lookup | - | + +**Examples:** + +```bash +# Get details for session mer-3 +ao session get mer-3 +``` + +```bash +# Get session details as JSON +ao session get mer-3 --json +``` + +--- + +### ao session kill + +Terminate a session. + +**Syntax:** +``` +ao session kill [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `-p, --project string` | Project id to scope the lookup | - | + +**Examples:** + +```bash +# Kill session mer-3 +ao session kill mer-3 +``` + +--- + +### ao session rename + +Rename a session. + +**Syntax:** +``` +ao session rename [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `-p, --project string` | Project id to scope the lookup | - | + +**Examples:** + +```bash +# Rename session mer-3 to a new display name +ao session rename mer-3 "fix-auth-bug" +``` + +--- + +### ao session restore + +Relaunch a terminated session. + +**Syntax:** +``` +ao session restore [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `-p, --project string` | Project id to scope the lookup | - | + +**Examples:** + +```bash +# Restore a terminated session +ao session restore mer-3 +``` + +--- + +### ao session cleanup + +Clean up terminated sessions by reclaiming eligible workspaces. Dirty worktrees are skipped by the daemon. + +**Syntax:** +``` +ao session cleanup [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `-p, --project string` | Filter by project ID | - | +| `-y, --yes` | Skip confirmation prompt | - | + +**Examples:** + +```bash +# Clean up all terminated sessions (skip prompt) +ao session cleanup -y +``` + +```bash +# Clean up terminated sessions for one project +ao session cleanup -p agent-orchestrator +``` + +--- + +### ao session claim-pr + +Attach an existing PR to a session. + +**Syntax:** +``` +ao session claim-pr [flags] +``` + +**Flags:** + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output as JSON | - | +| `--no-takeover` | Refuse if another active session owns the PR | - | +| `-p, --project string` | Project id to scope the lookup | - | + +**Examples:** + +```bash +# Attach PR 88 to session mer-3 +ao session claim-pr mer-3 88 +``` + +```bash +# Claim PR 88 but refuse if another session already owns it +ao session claim-pr mer-3 88 --no-takeover +``` diff --git a/backend/internal/skillassets/using-ao/commands/spawn.md b/backend/internal/skillassets/using-ao/commands/spawn.md new file mode 100644 index 000000000..8fe31bde4 --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/spawn.md @@ -0,0 +1,38 @@ +# ao spawn + +Spawn a worker agent session in a registered project. The session runs the chosen agent in a fresh git worktree. Register the project first with `ao project add`. + +## Syntax + +``` +ao spawn [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--branch string` | Branch for the session worktree | `ao//root` | +| `--claim-pr string` | Immediately claim an existing PR for the spawned session | - | +| `--harness string` | Agent harness to use (see list below) | Project `worker.agent`; required if the project has none | +| `--issue string` | Issue id to associate with the session | - | +| `--name string` | Display name shown in the sidebar (max 20 characters) | Required | +| `--no-takeover` | Refuse if another active session owns the claimed PR (requires `--claim-pr`) | - | +| `--project string` | Project id to spawn the session in | Required | +| `--prompt string` | Initial prompt for the agent | - | + +`--agent` is an alias for `--harness`. + +Available harnesses: `claude-code`, `codex`, `aider`, `opencode`, `grok`, `droid`, `amp`, `agy`, `crush`, `cursor`, `qwen`, `copilot`, `goose`, `auggie`, `continue`, `devin`, `cline`, `kimi`, `kiro`, `kilocode`, `vibe`, `pi`, `autohand`. + +## Examples + +```bash +# Spawn a worker for issue 142 in the agent-orchestrator project +ao spawn --project agent-orchestrator --issue 142 --name "fix-session-leak" --prompt "Fix the session leak described in issue 142. Branch off upstream/main." +``` + +```bash +# Spawn a worker and immediately claim an open PR +ao spawn --project agent-orchestrator --name "review-pr-88" --claim-pr 88 --harness claude-code +``` diff --git a/backend/internal/skillassets/using-ao/commands/start.md b/backend/internal/skillassets/using-ao/commands/start.md new file mode 100644 index 000000000..33937a8ce --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/start.md @@ -0,0 +1,27 @@ +# ao start + +Fetch (if needed) and open the Agent Orchestrator desktop app. The desktop app owns the daemon, state, and updates. `ao start` no longer runs a daemon: it resolves the installed app (or downloads the latest release), opens it, and exits. + +## Syntax + +``` +ao start [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output start result as JSON | - | + +## Examples + +```bash +# Open the AO desktop app +ao start +``` + +```bash +# Open the app and get the result as JSON +ao start --json +``` diff --git a/backend/internal/skillassets/using-ao/commands/status.md b/backend/internal/skillassets/using-ao/commands/status.md new file mode 100644 index 000000000..65a587717 --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/status.md @@ -0,0 +1,27 @@ +# ao status + +Show AO daemon status. Use this to verify the daemon is up and check which port it is bound to. + +## Syntax + +``` +ao status [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output status as JSON | - | + +## Examples + +```bash +# Check daemon status +ao status +``` + +```bash +# Get status as JSON (e.g. to check port programmatically) +ao status --json +``` diff --git a/backend/internal/skillassets/using-ao/commands/stop.md b/backend/internal/skillassets/using-ao/commands/stop.md new file mode 100644 index 000000000..dd731542f --- /dev/null +++ b/backend/internal/skillassets/using-ao/commands/stop.md @@ -0,0 +1,28 @@ +# ao stop + +Stop the AO daemon. + +## Syntax + +``` +ao stop [flags] +``` + +## Flags + +| Flag | Meaning | Default / Required | +|---|---|---| +| `--json` | Output stop result as JSON | - | +| `--timeout duration` | How long to wait for daemon shutdown | `10s` | + +## Examples + +```bash +# Stop the daemon +ao stop +``` + +```bash +# Stop with a longer timeout +ao stop --timeout 30s +``` diff --git a/backend/internal/skillassets/using-ao/references.md b/backend/internal/skillassets/using-ao/references.md new file mode 100644 index 000000000..ef9fc5507 --- /dev/null +++ b/backend/internal/skillassets/using-ao/references.md @@ -0,0 +1,26 @@ +# Quick Reference + +Natural-language-to-command mappings for common AO tasks. + +| You want to... | Command | +|---|---| +| Show me this webpage / open this page | `ao preview ""` | +| Spawn a worker on issue N | `ao spawn --project

--issue N --name "<=20 chars>" --prompt "..."` | +| Message a running agent | `ao send --session --message "..."` | +| Kill a session | `ao session kill ` | +| List sessions | `ao session ls` | +| Register a repo as a project | `ao project add --path --name ` | +| List projects | `ao project ls` | +| Rename a session | `ao session rename ""` | +| Restore a killed session | `ao session restore ` | +| Clean up terminated sessions | `ao session cleanup` | +| See a session's details | `ao session get ` | +| Open the desktop app | `ao start` | +| Check the daemon is up | `ao status` | +| Run health checks | `ao doctor` | +| Clear the preview panel | `ao preview clear` | +| List orchestrator sessions | `ao orchestrator ls` | +| Claim an existing PR for a session | `ao session claim-pr ` | +| Submit a code review verdict | `ao review submit --run --verdict approved` | +| Configure a project's default branch or model | `ao project set-config --default-branch --model ` | +| Import projects from a legacy AO install | `ao import --dry-run` (preview), then `ao import -y` |