agy-crew 0.0.0-stage → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +315 -2
- package/README.zh-CN.md +314 -0
- package/companion/accounts.mjs +300 -0
- package/companion/agy-companion.mjs +2136 -0
- package/companion/identity.mjs +25 -0
- package/companion/install.mjs +443 -0
- package/companion/observation.mjs +147 -0
- package/companion/pool/env.mjs +14 -0
- package/companion/pool/lease.mjs +89 -0
- package/companion/pool/loans.mjs +46 -0
- package/companion/pool/quota.mjs +142 -0
- package/companion/pool/results.mjs +41 -0
- package/companion/pool/select.mjs +115 -0
- package/companion/pool/state.mjs +104 -0
- package/companion/pool/token.mjs +25 -0
- package/companion/state-lock.mjs +103 -0
- package/companion/stream-worker.mjs +361 -0
- package/docs/INSTALL_FOR_AGENTS.md +213 -0
- package/docs/REFERENCE.md +509 -0
- package/docs/REFERENCE.zh-CN.md +619 -0
- package/opencode-skills/agy-crew-accounts/SKILL.md +85 -0
- package/opencode-skills/agy-crew-ask/SKILL.md +46 -0
- package/opencode-skills/agy-crew-implementer/SKILL.md +56 -0
- package/opencode-skills/agy-crew-jobs/SKILL.md +99 -0
- package/opencode-skills/agy-crew-jobs/references/setup.md +41 -0
- package/opencode-skills/agy-crew-jobs/references/troubleshooting.md +35 -0
- package/opencode-skills/agy-crew-lead/SKILL.md +39 -0
- package/opencode-skills/agy-crew-researcher/SKILL.md +52 -0
- package/opencode-skills/agy-crew-reviewer/SKILL.md +62 -0
- package/opencode-skills/agy-crew-reviewer/references/code-review.md +46 -0
- package/opencode-skills/agy-crew-reviewer/references/general-review.md +22 -0
- package/opencode-skills/agy-crew-staffer/SKILL.md +54 -0
- package/opencode.mjs +14 -0
- package/package.json +53 -4
- package/pi-skills/agy-crew-accounts/SKILL.md +85 -0
- package/pi-skills/agy-crew-ask/SKILL.md +46 -0
- package/pi-skills/agy-crew-implementer/SKILL.md +56 -0
- package/pi-skills/agy-crew-jobs/SKILL.md +99 -0
- package/pi-skills/agy-crew-jobs/references/setup.md +41 -0
- package/pi-skills/agy-crew-jobs/references/troubleshooting.md +35 -0
- package/pi-skills/agy-crew-lead/SKILL.md +39 -0
- package/pi-skills/agy-crew-researcher/SKILL.md +52 -0
- package/pi-skills/agy-crew-reviewer/SKILL.md +62 -0
- package/pi-skills/agy-crew-reviewer/references/code-review.md +46 -0
- package/pi-skills/agy-crew-reviewer/references/general-review.md +22 -0
- package/pi-skills/agy-crew-staffer/SKILL.md +54 -0
- package/scripts/generate-skills.mjs +138 -0
- package/skills/accounts/SKILL.md +78 -0
- package/skills/ask/SKILL.md +40 -0
- package/skills/implementer/SKILL.md +50 -0
- package/skills/jobs/SKILL.md +93 -0
- package/skills/jobs/references/setup.md +39 -0
- package/skills/jobs/references/troubleshooting.md +33 -0
- package/skills/lead/SKILL.md +32 -0
- package/skills/researcher/SKILL.md +46 -0
- package/skills/reviewer/SKILL.md +56 -0
- package/skills/reviewer/references/code-review.md +44 -0
- package/skills/reviewer/references/general-review.md +20 -0
- package/skills/staffer/SKILL.md +48 -0
- package/templates/ask.md +5 -0
- package/templates/harness-compatibility.md +5 -0
- package/templates/implement.md +39 -0
- package/templates/research.md +37 -0
- package/templates/review.md +27 -0
- package/templates/staffer.md +19 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# agy-crew — Full reference
|
|
2
|
+
|
|
3
|
+
Back to the [README](../README.md). See the [Chinese reference](REFERENCE.zh-CN.md).
|
|
4
|
+
|
|
5
|
+
## Modes and defaults
|
|
6
|
+
|
|
7
|
+
| Persona (skill) | Companion mode | What it is | Default model | Profile | Execution |
|
|
8
|
+
|---|---|---|---|---|---|
|
|
9
|
+
| `ask` | `ask` | Cheap zero-tool one-shot Q&A (~3s); doubles as the post-install smoke test | `gemini-3.8-flash-low` | restricted (prompt-only) | synchronous — the answer comes back in the same call |
|
|
10
|
+
| `staffer` | `staffer` | General-purpose delegation without a specialist role or fixed output format; shared operational guardrails still apply | `gemini-3.8-flash-medium` | unrestricted | background job — returns a job id |
|
|
11
|
+
| `researcher` | `research` | Deep survey with cited sources and explicit unverified-claims marking | `gemini-3.8-flash-high` | unrestricted | background job — returns a job id |
|
|
12
|
+
| `reviewer` | `review` | Second-opinion verifier, two flavors routed by subject: code review (severity-ranked findings with `file:line` refs) and general review (multi-angle challenge of a plan, design, or decision) | `gemini-3.8-flash-medium` | unrestricted | background job — returns a job id |
|
|
13
|
+
| `implementer` | `implement` | Well-scoped coding task; agy edits the working tree and can perform explicitly requested Git delivery | `gemini-3.8-flash-high` | unrestricted | background job — returns a job id |
|
|
14
|
+
|
|
15
|
+
`lead` provides task orchestration guidance for the current agent, reusing the existing companion modes without adding a mode of its own; invoke `/agy-crew:lead` in Claude Code, `$agy-crew:lead` in Codex, `/skill:agy-crew-lead` in Pi, or `/agy-crew-lead` in OpenCode.
|
|
16
|
+
|
|
17
|
+
Execution style is fixed per mode and cannot be overridden by a flag. `continue` inherits the resolved mode's style (continuing an `ask` stays synchronous; continuing the others returns a job id).
|
|
18
|
+
|
|
19
|
+
Claude Code, Codex, Pi, and OpenCode surface the same personas, backed by one companion script (`companion/agy-companion.mjs`, Node stdlib only) and shared prompt templates (`templates/`). Invocation tokens: `/agy-crew-<persona>` on every harness once installed with `agy-crew install` (Codex lists these as `$agy-crew-<persona>`); through the plugin routes, `/agy-crew:<persona>` on Claude Code, `$agy-crew:<persona>` on Codex, `/skill:agy-crew-<persona>` on Pi, and `/agy-crew-<persona>` on OpenCode. Pi's manifest exposes only `pi-skills/`, generated mechanically from canonical `skills/` via `npm run generate:pi`. Generated skills use `agy-crew-` prefixes, rewrite sibling references, and append `templates/harness-compatibility.md` (directing the host to adapt missing tools to equivalent methods without dropping requirements, or ask for help). Job management (`wait`/`status`/`result`/`cancel`/`continue`/`setup`) lives in `jobs` (`agy-crew-jobs` on Pi and OpenCode) plus the companion CLI — ask for it in natural language ("is the agy job done?").
|
|
20
|
+
|
|
21
|
+
## The two-profile permission model
|
|
22
|
+
|
|
23
|
+
Every mode runs under exactly one of two profiles. **Every tool-using mode defaults to `unrestricted`**, so the plugin works out of the box with no allowlist and no setup; `--restricted` is the opt-in hardening flag. `--restricted`/`--unrestricted` override per call (`ask` is tool-free and forced restricted — it ignores both, and passing `--unrestricted` to it prints a note and proceeds restricted).
|
|
24
|
+
|
|
25
|
+
The profile for a run is resolved in this order: CLI flag > recorded conversation profile (when continuing) > per-repo policy ([`setup --restrict`](#per-repo-policy-setup---restrict)) > built-in default.
|
|
26
|
+
|
|
27
|
+
| | **unrestricted** (default: staffer, research, review, implement) | **restricted** (opt-in hardening; forced for ask) |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| agy invocation | `--dangerously-skip-permissions` | no permission skipping — fail-closed, every unlisted tool call is auto-denied |
|
|
30
|
+
| What agy can do | anything, including editing files and running commands | workspace file reads plus `git gh cat head ls grep find rg wc`, with five targeted git/gh deny prefixes (AGY permission rules) |
|
|
31
|
+
| Safety net | prompt-level guardrails (default-deny on irreversible/costly actions) + the tiered git guards below | agy stays inside agy's own permission enforcement |
|
|
32
|
+
| Typical use | the normal path: Q&A, surveys, reviews, coding tasks | hardened runs: untrusted input, or machines where skipping agy's permission prompts is unacceptable |
|
|
33
|
+
|
|
34
|
+
`--restricted` and `--unrestricted` are mutually exclusive; passing both is an error. Two things to know before hardening: `--restricted` is only useful once setup's allowlist is installed (otherwise agy denies its own evidence gathering and the run comes back empty), and some native tools ignore allow-rules in headless mode entirely — a restricted run can be thinner than an unrestricted one.
|
|
35
|
+
|
|
36
|
+
### Tiered git guards
|
|
37
|
+
|
|
38
|
+
The guards apply to **unrestricted runs only** and differ by mode:
|
|
39
|
+
|
|
40
|
+
| Mode | Inside a git repo | Not a git repo |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `implement` | dirty workspaces are allowed. If the repo already has changes, the companion adds a short pre-run status summary to agy's prompt so it knows which paths were already touched and must treat them as user-owned work. The summary is capped; agy should run `git status --porcelain` and inspect diffs when ownership is unclear. Afterward the companion reports whether the workspace is clean, changed, or still dirty | warns that agy's edits cannot be reviewed or rolled back via git, then proceeds |
|
|
43
|
+
| `research`, `review` | never blocked, no clean-tree check. The worker snapshots `git status --porcelain` before the run and compares afterwards; if agy introduced changes, the result carries a warning listing the delta plus a rollback hint | nothing to compare — silent |
|
|
44
|
+
| `staffer` | same snapshot/report as research/review, but neutrally worded: a general task may legitimately edit files, so the delta is information for the caller ("verify the task asked for it"), not an accusation | nothing to compare — silent |
|
|
45
|
+
|
|
46
|
+
Silence is the normal case for `research`/`review`: the delta warning shows up only when agy touched the working tree, which the templates tell it not to do.
|
|
47
|
+
|
|
48
|
+
### Prompt-level guardrails: default-deny, prompt-opens
|
|
49
|
+
|
|
50
|
+
The `staffer`, `research`, `review` and `implement` templates deny irreversible or costly side effects **by default**:
|
|
51
|
+
|
|
52
|
+
- no commits, pushes, PR writes or history rewrites unless the task explicitly asks for that exact Git delivery;
|
|
53
|
+
- no deleting files outside the workspace;
|
|
54
|
+
- no side-effectful network calls;
|
|
55
|
+
- no commands that burn paid API quota or tokens (e.g. an e2e suite that bills a live API).
|
|
56
|
+
|
|
57
|
+
Scratch scripts go in a temp dir, and everything the run does inside the workspace stays git-revertible.
|
|
58
|
+
|
|
59
|
+
**The default is closed, not locked.** If your request explicitly authorizes one of those operations ("commit this", "open a draft PR", "run the e2e tests", "call the staging API"), agy does exactly what was authorized and reports what it ran — so pass such authorizations through verbatim when you delegate. `review` in particular may run read-only commands, scratch scripts and tests to verify a finding; what it must not do is modify tracked files, commit or push.
|
|
60
|
+
|
|
61
|
+
### Reviewing untrusted content
|
|
62
|
+
|
|
63
|
+
Under `unrestricted`, prompt injection is code execution. If you point `review` or `research` at content written by someone you do not trust — a PR from a stranger, a vendored dependency, an issue body full of instructions — text inside that content can tell agy to run arbitrary commands, and an unrestricted agy will run them.
|
|
64
|
+
|
|
65
|
+
Two mitigations, neither of them the default:
|
|
66
|
+
|
|
67
|
+
- **`--restricted`** — agy's own permission enforcement applies, so unlisted tools are auto-denied. Caveats as above: it needs setup's allowlist to be useful, the allowlist is prefix-matched rather than read-only, and native tools that ignore allow-rules may fail-close and thin out the review. It shrinks the blast radius; it is not a sandbox.
|
|
68
|
+
- **An isolated checkout** — review it in a throwaway clone, container or VM with no credentials worth stealing.
|
|
69
|
+
|
|
70
|
+
The default optimizes for the common case: your own code on your own machine. Untrusted input is the case where you should reach for one of the two.
|
|
71
|
+
|
|
72
|
+
### Optional hardening (setup)
|
|
73
|
+
|
|
74
|
+
`setup` is an optional companion management command handled by the `jobs` skill. Ask your host agent to configure agy's restricted mode when you need it. The command checks the `agy` binary and previews **evidence-gathering allow/deny rules** for `~/.gemini/antigravity-cli/settings.json`. Only after explicit confirmation does it back up the file and append the configuration. Default unrestricted tasks and tool-free ask do not depend on setup.
|
|
75
|
+
|
|
76
|
+
Two properties of these rules you should know before applying them:
|
|
77
|
+
|
|
78
|
+
- **It allows broad commands with a small deny list.** Setup keeps `command(git)` / `command(gh)` and adds deny prefixes for `git push`, `git reset --hard`, `git clean`, `gh pr merge` and `gh release delete`. [AGY evaluates deny before ask before allow](https://www.antigravity.google/docs/cli/permissions/); the companion only installs configuration, with no command parser or per-task allowlist. Existing allow/deny/ask rules are preserved. Applying setup to an earlier narrow configuration adds the broad grants shown in its dry run. These prefixes prevent common mistakes, not all irreversible actions: other argument arrangements, aliases, scripts, APIs and other allowed commands are not comprehensively covered. The setup is not a read-only boundary. A denied operation stays denied even if requested in the task; change the settings explicitly when needed.
|
|
79
|
+
- **It is global.** The file is `~/.gemini/antigravity-cli/settings.json`, so the rules apply to every `agy` run on the machine, not only to agy-crew jobs. That is the intended product path ("set up once, use everywhere").
|
|
80
|
+
|
|
81
|
+
Web search is not in the allowlist and does not need to be: on the tested agy (v1.1.13) `search_web` runs headless without an allow rule.
|
|
82
|
+
|
|
83
|
+
### Per-repo policy (`setup --restrict`)
|
|
84
|
+
|
|
85
|
+
If you want some modes to run restricted every time *in a particular repository* — say, a repo where you routinely review strangers' PRs — you can declare that once instead of remembering the flag:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
setup --restrict review,research # these modes default to restricted in this repo
|
|
89
|
+
setup --restrict none # back to the built-in defaults
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The policy is written to `<repo>/.agy-crew/config.json` and applied automatically (the run prints a note that the profile came from the project policy). Three properties:
|
|
93
|
+
|
|
94
|
+
- **Precedence.** Explicit `--restricted`/`--unrestricted` flags override the policy. Continuations without an explicit override inherit their recorded profile; new tasks use the repository policy or built-in defaults. `ask` is tool-free and always restricted.
|
|
95
|
+
- **Scope.** `.agy-crew/` is normally git-ignored, so the policy is a personal, per-machine preference — it is not shared with your team through the repo.
|
|
96
|
+
- **What it is not.** This is a run policy for consistency and accident prevention, not a security boundary: it feeds the same `--restricted` machinery, with the same caveats (needs the global allowlist, prefix-matched, some tools ignore allow-rules headless). For genuinely untrusted input, use an isolated checkout.
|
|
97
|
+
|
|
98
|
+
Note the two files are different things: the **allow/deny rules** (what a restricted agy may execute) is global by agy's design; the **policy** (which modes default to restricted) is per-repo by ours.
|
|
99
|
+
|
|
100
|
+
### Advanced: project-scoped permissions
|
|
101
|
+
|
|
102
|
+
If a machine-wide allowlist is too broad for you, agy also supports project-scoped permission rules (it treats them as highest priority) tied to its `--project` system. That would let you grant the evidence rules only inside the repos where you delegate.
|
|
103
|
+
|
|
104
|
+
Caveat, stated plainly: **the exact project-settings file path is undocumented and unverified against the current agy release**, so agy-crew does not write it and this document does not guess it. If you want project scoping, check `agy` interactively for where it reads project-level rules from, and configure it yourself. Until then, either accept the global scope or skip setup entirely — the default unrestricted profile bypasses agy's permission system rather than depending on it, and `ask` needs no allowlist at all; skipping setup only costs you the ability to harden a run with `--restricted`.
|
|
105
|
+
|
|
106
|
+
## Flags (uniform across modes)
|
|
107
|
+
|
|
108
|
+
| Flag | Meaning |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `--conversation <id>` | resume a specific agy conversation |
|
|
111
|
+
| `--continue` | reuse this mode's last conversation id from state |
|
|
112
|
+
| `--model <id>` | explicit agy model (see `agy models`). Ids are effort-suffixed (`gemini-3.8-flash-low`); the companion normalizes bare families (`gemini-3.8-flash` + `--effort`) and the aliases `flash`/`pro`, and rejects unknown ids pre-flight |
|
|
113
|
+
| `--effort low\|medium\|high` | shorthand for `gemini-3.8-flash-<effort>` |
|
|
114
|
+
| `--restricted` / `--unrestricted` | permission profile override (ignored by `ask`). `unrestricted` is the default for `staffer`/`research`/`review`/`implement`, so `--restricted` is the flag you actually reach for |
|
|
115
|
+
| `--restrict <modes\|none>` | (setup) per-repo policy: the listed modes default to restricted in this repository; `none` clears it. See [Per-repo policy](#per-repo-policy-setup---restrict) |
|
|
116
|
+
| `--json` | (review) schema-enforced JSON findings; default is free-form markdown. Meant for the code-review flavor |
|
|
117
|
+
| `--account auto|live|<name>` | which agy account runs the task (default `$AGY_CREW_ACCOUNT`, else `auto`). Accepted by `ask`, `staffer`, `research`, `review`, `implement`, `continue` and `restart`. See [Accounts](#accounts) |
|
|
118
|
+
| `--timeout <dur>` | Background worker hard limit (default 60m, maximum 120m). AGY receives the selected response timeout. For synchronous ask: AGY response timeout, default 2m |
|
|
119
|
+
| `--prompt <text>` | the task text as one argument. Quote it; whatever is inside is opaque |
|
|
120
|
+
| `--prompt-file <path>` | read the task text from a file — for long prompts, instead of shell quoting |
|
|
121
|
+
| `--stdin` | read the task text from stdin. Exactly one task source per call: `--prompt`, `--prompt-file`, or `--stdin` |
|
|
122
|
+
|
|
123
|
+
That table is the whole public surface. There is no flag for execution style — see the modes table above.
|
|
124
|
+
|
|
125
|
+
## Task text
|
|
126
|
+
|
|
127
|
+
This section is about the **companion CLI**, not about how you invoke a persona. You type your task as plain text after the slash command (`/agy-crew:reviewer Review PR #730`); the skill reads it and composes the `--prompt` call below. You never type `--prompt` yourself.
|
|
128
|
+
|
|
129
|
+
Every run command (`staffer`, `research`, `review`, `implement`, `ask`, `continue`) takes its task from **exactly one** of three sources:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
ask --prompt "what does git diff --check verify?"
|
|
133
|
+
research --prompt-file /tmp/task.md
|
|
134
|
+
review --stdin < /tmp/task.md
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Giving two at once is an error (`task text given more than one way (…) — use exactly one`), and giving none is an error too.
|
|
138
|
+
|
|
139
|
+
**The opacity guarantee.** The companion parses the shell's argv once, exactly as the shell delivered it: it re-splits no argument, interprets no quotes, and inspects no byte of a task value. Your task reaches agy byte for byte — whitespace, quotes and newlines included — and flag-like text inside it (`--check`, `--json`, `--timeout`, an unknown `--whatever`) is prompt content, never a companion option. The same holds for `--prompt-file` and `--stdin` contents.
|
|
140
|
+
|
|
141
|
+
`--prompt` accepts a value that starts with `--` when it is a real sentence, meaning one that contains whitespace: `ask --prompt "--check means what?"` works. A flag-shaped value with no whitespace reads as a forgotten value and is rejected. `--` itself carries no special meaning; it parses as an unknown flag.
|
|
142
|
+
|
|
143
|
+
Value flags (`--conversation`, `--model`, `--effort`, `--timeout`, `--restrict`, `--account`, `--prompt`, `--prompt-file`) require a value. A missing one, an empty one, and — apart from the `--prompt` sentences above — a flag-shaped one are all errors, so `--model ""` is an error.
|
|
144
|
+
|
|
145
|
+
Each flag is its own argument. Flags packed into a single quoted string (`review "--restricted Review PR #730"`) are an error that names the fix rather than a guess at where the flags end and the task begins.
|
|
146
|
+
|
|
147
|
+
## Review is prompt-based
|
|
148
|
+
|
|
149
|
+
`review` takes a subject description and gathers the evidence itself with the tools it has (`gh pr view`/`gh pr diff` for PRs, `git diff`/`git log` for refs and the working tree, reading files for patches). There is no flag that hands it a diff; describe the subject in the prompt instead:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
review --prompt "Review PR #730"
|
|
153
|
+
review --prompt "Review the current working tree"
|
|
154
|
+
review --prompt "Review changes against master"
|
|
155
|
+
review --prompt "Review the patch at /tmp/change.patch"
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
An empty task string is an error — `review` needs a subject. If the subject is ambiguous, agy is instructed to report the ambiguity rather than guess at what you meant.
|
|
159
|
+
|
|
160
|
+
The review template itself is a neutral skeleton (reviewer stance, evidence discipline, guardrails). Everything flavor-specific — the evidence-gathering menu, review axes, severity ranking, and output format for code reviews; the multi-angle challenge framing for plan/decision reviews — travels in the task string, composed by the `reviewer` skill from `skills/reviewer/references/{code-review,general-review}.md`.
|
|
161
|
+
|
|
162
|
+
## State and background jobs
|
|
163
|
+
|
|
164
|
+
**Output split.** stdout carries the result and any guard warning about the working tree; the `[agy-crew]` telemetry line (mode, profile, model, duration, tokens, conversation id, account) goes to stderr, and for background jobs into `jobs/<id>.log`. Telemetry is metadata for the calling agent — it is not part of the deliverable and is not stored in `jobs/<id>.result.md`.
|
|
165
|
+
|
|
166
|
+
`staffer`, `research`, `review` and `implement` return stable job handles promptly. Default flow: prepare the prompt, dispatch, wait for the final result, then validate as needed. While running, do not proactively observe, read logs or inspect intermediate artifacts, including for routine updates. Observe progress only when the user explicitly asks; diagnose after a failure or a result requiring intervention. Each detached worker continuously drains AGY `stream-json`, even with no observers. There is no additional daemon or scheduler.
|
|
167
|
+
|
|
168
|
+
- `wait [id] [--timeout <dur>]` waits for completion or its wait timeout. Completion delivers the existing result; soft expiry returns a JSON observation snapshot directly and leaves execution running. Ordinary tool activity does not end the wait early. Bare wait defaults to 100s; skills recommend an explicit 10m wait. On exit 2, wait again for the same job without extra progress checks; the returned snapshot does not require intervention.
|
|
169
|
+
- `observe [id]` always returns bounded JSON (at most 8 KiB): current progress while running; terminal status, result path/availability and collection instructions when finished. Error/canceled/crashed states include bounded diagnostic and recovery metadata, never the full report. It reads job state independently of any wait, without resetting deadlines or consuming another observer’s history.
|
|
170
|
+
- `status [id]` lists jobs or shows state and a bounded diagnostic log tail. `result [id]` reprints stored output.
|
|
171
|
+
- `cancel <id>` requests cancellation and returns success after the worker stores its report and publishes `canceled`. It preserves crash diagnostics and never signals an unverified stored PID. Legacy jobs without a cancellation channel fail explicitly. A cancellation error requires checking the job and logs; it does not establish that execution stopped. Interrupting a wait does not cancel the worker.
|
|
172
|
+
- `continue --job <id> --prompt "..."` resumes the known conversation with its original mode/model/profile and a linked new job. `continue --conversation <id>` also resolves configuration from that known conversation, never an unrelated last mode.
|
|
173
|
+
- `restart <id>` explicitly relaunches the original task/configuration without a conversation, linked to the original job. Inspect partial workspace changes with `git status` and `git diff` before either recovery action. New runs regenerate workspace context. Legacy specifications label historical snapshots and append current context.
|
|
174
|
+
|
|
175
|
+
Continuation/restart can be invoked from any directory within the same worktree and execute in the original cwd. Generic `continue` rejects unrecorded conversation IDs without launching AGY or searching other worktrees. Continuing a conversation whose job is still running (generic `continue`, or a mode's `--continue`/`--conversation`) is refused with exit 1 and the job ID and status; the follow-up is not queued, and the caller waits or cancels first. For continuation, explicit model/profile flags override the recorded values; otherwise those values are inherited. A new recovery budget defaults to 60m unless overridden.
|
|
176
|
+
|
|
177
|
+
Exit codes for wait/observe/status-with-id: **0** done, **2** running, **3** error/crashed, **4** canceled, **5** attention (resumable timeout), **1** command error. `result` also exits 5 for attention; its legacy exit behavior for other states is unchanged. Observe exit 0 means the job is finished, not that its report was delivered. Collect an already pending wait session; otherwise call result. Wait/result keep their existing full-result contract. A `done` status means invocation and response delivery ended, not that the task was accepted. Successful calls with warnings include an 8 KiB log tail on stderr and the full-log path; native status and exit code are recorded in that log. The orchestrator assesses completion and inspects further only when needed. Intermediate tool errors are retained internally and are not automatically promoted to warnings in successful delivery. A running snapshot contains timestamps, elapsed time, the latest five tool activities with input/output excerpts and the latest response text merged by step. Unknown states, incomplete text and truncation are labeled; a tool finishing is not proof of useful progress. UTF-8 JSON budgets are 1 KiB per activity, 2 KiB for text and 8 KiB total. For a user-requested progress answer or diagnosis after failure/required intervention, read bounded `details` excerpts only if the returned information is insufficient.
|
|
178
|
+
|
|
179
|
+
The worker passes the selected timeout to AGY and independently enforces an overall limit including initialization: default 60m, configurable up to 120m with launch `--timeout`. If response text arrived before hard-expiry cleanup, it is delivered with a warning; an empty or absent response needs attention when a conversation is known, otherwise it remains a failure. Wait/observe cannot renew it. Without a response, hard expiry produces `reason=hard_timeout`; an explicit TIMEOUT status or AGY's exact `ERROR` plus `timeout waiting for response` produces `reason=response_timeout`. A known conversation yields `status=attention` and exit 5; without one the status is `error`. Reports retain the last snapshot, logs, original configuration and pre-run/current workspace status (porcelain cannot detect content changes to an already dirty file; inspect diffs). Recovery metadata includes `requires_user_confirmation`, `suggested_timeout` (double the previous timeout, capped at 120m for background jobs) and an exact continuation command. At the ceiling, narrow the task. Calling agents must ask whether to continue or stop and inspect, and recover only after explicit user confirmation. Explicit recovery creates a linked new job with a fresh budget, preserving the old terminal record; the companion never retries automatically.
|
|
180
|
+
|
|
181
|
+
Wait is silent until completion or soft expiry. Only an explicit user progress question warrants observation while running; keep the pending wait open and do not turn the question into recurring checks. Host session collection (such as Codex `write_stdin`) retrieves the pending command’s output, which may include a soft-expiry snapshot; it does not independently read AGY progress. Prefer background completion delivery or a long supported blocking wait. Avoid short empty polls, sleep/observe loops and progress queries for routine updates.
|
|
182
|
+
|
|
183
|
+
Use one independent background wait per job where the harness supports it, never serialize multiple jobs in one shell. Otherwise use the longest practical wait within the host's tool-call limit. Completion ends an outstanding wait, but the outer harness controls when the model receives it. Bash + skills cannot universally wake an idle model; a timer instruction alone does not schedule another invocation.
|
|
184
|
+
|
|
185
|
+
Per-repository state lives in `<repo>/.agy-crew/`. `state.json` stores conversations, configuration history indexed by conversation ID (including foreground ask), and lifecycle records, protected by short write transactions; observation reads remain read-only. `config.json` holds optional permission policy. Each job has a spec, diagnostic log, result, final status sidecar, raw stdout (`.events.jsonl`) and atomically published bounded snapshot (`.progress.json`). Raw records may include unknown/malformed events. Missing activity files on legacy jobs yield a status-only snapshot.
|
|
186
|
+
|
|
187
|
+
After warning-free success, results and metadata become durable before the raw stream/snapshot are deleted. Failures, cancellation, hard timeout and warning results retain intermediates. Results, diagnostic logs, conversation metadata and AGY's own conversation storage are retained. Readers racing with cleanup recheck terminal state: observe returns terminal metadata; wait returns the result. Observe never reads result-file contents, even after successful intermediates have been deleted. Crash-without-result reports include dispatch/worker-start evidence, process IDs, log existence/size and next-inspection/recovery commands without copying prompts or environment values.
|
|
188
|
+
|
|
189
|
+
### Keeping `.agy-crew/` out of git
|
|
190
|
+
|
|
191
|
+
Automatic since 0.4: when the companion creates `.agy-crew/` for the first time in a repo, it appends `.agy-crew/` to `.git/info/exclude` (repo-local, untracked) unless the path is already ignored. It never touches the tracked `.gitignore` — the state directory is local scratch, and adding it to a shared, committed file would change the repo for everyone else.
|
|
192
|
+
|
|
193
|
+
## Accounts
|
|
194
|
+
|
|
195
|
+
The account pool lets concurrent jobs run on different agy accounts and tracks quota per account and per model family. It is global to the user, not per repository.
|
|
196
|
+
|
|
197
|
+
**Two kinds of account.**
|
|
198
|
+
|
|
199
|
+
- **live** is the user's own agy login (`os.homedir()`, whose credential may sit in the OS credential store). It is never part of the pool: `auto` never picks it, it never lends a credential and never borrows one. It is used only when requested with `--account live`, or when the pool has no enabled account. An empty pool therefore behaves exactly as 0.8.0 did.
|
|
200
|
+
- **Pool accounts** are named, private HOME directories at `~/.agy-crew/accounts/<name>/home/`, each holding a file-backed agy token at `home/.gemini/antigravity-cli/antigravity-oauth-token`. Names match `^[a-z0-9][a-z0-9._-]{0,31}$`; `live` and `auto` are reserved. An account's email is read from the token's `id_token`, and the same email cannot be added twice.
|
|
201
|
+
|
|
202
|
+
Every agy process for a pool account runs with its own HOME (and `USERPROFILE` on Windows) plus SSH-style environment markers (`SSH_CONNECTION`, `SSH_CLIENT`, `SSH_TTY`) that make agy store its token in a file instead of the OS keyring. Live runs use the unchanged environment.
|
|
203
|
+
|
|
204
|
+
### Commands
|
|
205
|
+
|
|
206
|
+
| Command | Effect |
|
|
207
|
+
|---|---|
|
|
208
|
+
| `accounts list [--json]` | Name, email, state (`ready`, `busy n`, `cooling <family> until <time>`, `needs login`, `disabled`), last use and cached quota summary, plus a line for live: `live (your own agy login; never pooled)` |
|
|
209
|
+
| `accounts login <name>` | Interactive sign-in for a new account, or a re-login of an existing one. See [Login](#login) |
|
|
210
|
+
| `accounts import <name> --home <dir>` | Copy the token (and `settings.json` when present) from an existing HOME-shaped directory, such as an agy-cli-manager account directory (`~/.agy-cli-manager/accounts/<name>`). Same email and duplicate checks as login. Refuses the live home |
|
|
211
|
+
| `accounts quota [<name>...] [--refresh] [--json]` | Print cached quota snapshots and cooldowns. With `--refresh`, query Google's Cloud Code service first. See [Quota snapshots](#quota-snapshots) |
|
|
212
|
+
| `accounts enable <name>` / `accounts disable <name>` | Include or exclude an account from selection. Disabled accounts also never lend |
|
|
213
|
+
| `accounts cooldown clear <name> [--family <f>]` | Drop the recorded cooldown for an account, for one model family or for all |
|
|
214
|
+
| `accounts remove <name> [--yes]` | Without `--yes`, print what would be deleted and exit 0. With `--yes`, delete the account directory, its cooldowns, quota snapshot and conversation bindings, and report how many conversations became unusable. Refused while the account is in a lease or loan |
|
|
215
|
+
|
|
216
|
+
`--json` prints machine-readable output. These commands exit 0 on success and 1 on error. They never create per-repository state, so they work from any directory.
|
|
217
|
+
|
|
218
|
+
### Login
|
|
219
|
+
|
|
220
|
+
`accounts login <name>` is **interactive**: agy opens a browser sign-in. Run it in your own terminal, not through an agent. A new account is enrolled in a staging directory (`~/.agy-crew/enroll/<random>/home`) and moved into place only after it passes the checks below; a re-login works inside the existing account directory after backing up its token (and is refused while the account is in a lease or loan).
|
|
221
|
+
|
|
222
|
+
1. The companion prints instructions, then runs `agy --log-file <dir>/agy-crew-login.log` with the terminal attached. Exit agy once its prompt appears.
|
|
223
|
+
2. The log must contain `Using file-based token storage`, and the token file must exist. Otherwise the login fails (a new account's staging directory is deleted; a re-login restores the backup).
|
|
224
|
+
3. A duplicate email of another account fails. A re-login must yield the same email as before, or it fails and restores the backup.
|
|
225
|
+
4. A new account's `settings.json` permissions are seeded from the live settings file when it exists. A successful login clears the account's `needs login` marker.
|
|
226
|
+
|
|
227
|
+
### Choosing an account for a run
|
|
228
|
+
|
|
229
|
+
`staffer`, `research`, `review`, `implement`, `ask`, `continue` and `restart` accept `--account auto|live|<name>`. The default is the `AGY_CREW_ACCOUNT` environment variable, then `auto`.
|
|
230
|
+
|
|
231
|
+
| Request | Behaviour |
|
|
232
|
+
|---|---|
|
|
233
|
+
| `live` | The user's own login |
|
|
234
|
+
| `<name>` | That account. Fails if it is unknown, disabled or needs login. If it is cooling for the model family, fails with its `retry_at` and a suggestion to use `--account auto` or another model family |
|
|
235
|
+
| `auto` | With no enabled pool account, live. Otherwise the best candidate below |
|
|
236
|
+
|
|
237
|
+
**Selection ranking for `auto`.** A candidate is an enabled account with a token file, no authentication error, no active cooldown for the model family, and no cached Cloud Code snapshot reporting zero remaining quota for the family's quota pool with a reset time in the future. Candidates are ranked by:
|
|
238
|
+
|
|
239
|
+
1. fewest active leases (an idle account beats a busy one);
|
|
240
|
+
2. highest known remaining quota fraction (the lower of the short and weekly windows; unknown ranks after any known value above zero);
|
|
241
|
+
3. oldest `last_used_at`;
|
|
242
|
+
4. insertion order.
|
|
243
|
+
|
|
244
|
+
If there is no candidate, the run fails with reason `quota_exhausted`, listing each account's earliest `retry_at` and suggesting `--account live` or another model. Concurrent runs share one account only when it is named explicitly, or when `auto` finds no idle candidate (the least-loaded account wins).
|
|
245
|
+
|
|
246
|
+
Selection and the lease that marks the account busy are taken in one locked update, and released when the agy process ends. A lease whose process died is dropped automatically.
|
|
247
|
+
|
|
248
|
+
**Conversations stay bound to their account.** The first time a conversation id appears, it is recorded against the account. `continue --job`, `--continue` and `--conversation` use the bound account; naming a different one is an error (`conversation <id> belongs to account <x>`). Conversations created before the pool existed are treated as live. `restart` creates a fresh conversation, so it selects an account again.
|
|
249
|
+
|
|
250
|
+
### Model families, quota pools and cooldowns
|
|
251
|
+
|
|
252
|
+
A **model family** is the model id without its trailing effort suffix (`minimal`, `low`, `medium`, `high`, `xhigh`, `max`): `gemini-3.8-flash-low` belongs to `gemini-3.8-flash`. Cloud Code reports quota in two **quota pools**: `gemini` (families starting with `gemini`) and `other`.
|
|
253
|
+
|
|
254
|
+
When a run fails with agy's quota error (`RESOURCE_EXHAUSTED` together with `Individual quota reached` or `Weekly quota reached`), the companion records a **cooldown keyed by account and model family**. `retry_at` is the current time plus the parsed `Resets in` text (a sequence of `<n>d`, `h`, `m`, `s` tokens such as `2h3m`, `1d 4h` or `45s`), or plus **60 minutes** when the text cannot be parsed. Cooldowns expire on their own and can be cleared with `accounts cooldown clear`. Other families on the same account stay usable.
|
|
255
|
+
|
|
256
|
+
The run then recovers, with at most three extra attempts:
|
|
257
|
+
|
|
258
|
+
- **No conversation id yet and the account was chosen by `auto`**: the lease is released, another account is chosen and the same prompt is retried (failover).
|
|
259
|
+
- **A conversation id is known and the conversation is bound to a pool account**: a credential loan is attempted (below). If a lender exists, the run continues with the prompt "Your previous turn stopped because the account hit a quota limit. Continue the same task from where you stopped; do not repeat finished steps."
|
|
260
|
+
- **Otherwise the run fails** with reason `quota_exhausted`. A background job gets status `attention` when a conversation id exists and `error` when none does; its result includes `retry_at` and recovery text (`continue --job <id> after <retry_at>`; a credential loan is used automatically once another pool account is idle). A foreground run dies with the same information, exit 5 when a conversation id exists, otherwise 1. Further continuation is the caller's decision; the companion does not loop.
|
|
261
|
+
|
|
262
|
+
An **authentication failure** on a pool account (`401`, `403` or `unauthenticated` together with auth, credential, login or token wording) sets the account's auth error. Selection skips it, `list` shows `needs login`, and `accounts login <name>` clears it. Authentication failures are never retried.
|
|
263
|
+
|
|
264
|
+
### Credential loans
|
|
265
|
+
|
|
266
|
+
A conversation's history lives in its account's HOME, but the credential that makes the request can come from another account. When a conversation is bound to pool account B and B is cooling for the model family, either at continuation start or after a quota failure mid-run, the companion borrows an idle account L's credential:
|
|
267
|
+
|
|
268
|
+
1. L is chosen like an `auto` candidate but must also hold no lease and not be in a loan. Live never lends.
|
|
269
|
+
2. In one locked update the loan is recorded, with a lender lease on L and a run lease on B.
|
|
270
|
+
3. In B's token directory, B's token is renamed to `.antigravity-oauth-token.agy-crew.loan-backup` (only when it exists; a pre-existing backup aborts the loan), and L's token is copied to B's token path.
|
|
271
|
+
4. agy runs with B's HOME, so it sees B's conversation while L's credential makes the request. A quota cooldown during a loan is recorded against L.
|
|
272
|
+
5. Afterwards, in a `finally`, B's current token (agy may have refreshed it) is copied back to L's token path, B's token is deleted, and the backup is renamed back. Then the loan and its leases are dropped.
|
|
273
|
+
|
|
274
|
+
**Crash recovery.** Every locked update first reaps dead processes: leases whose pid is gone are dropped, and a loan whose pid is gone is restored by the same steps (so the lender's token gets the refreshed content and the borrower's original token returns). `accounts remove` and `accounts login` refuse while the account is in a lease or loan.
|
|
275
|
+
|
|
276
|
+
### Quota snapshots
|
|
277
|
+
|
|
278
|
+
`accounts quota` without `--refresh` prints what is cached and the active cooldowns. With `--refresh` it asks Google's Cloud Code service, per account:
|
|
279
|
+
|
|
280
|
+
1. Read the token. If the access token is missing or expires within 120 seconds, warm up by running `agy -p "reply with one word: pong" --output-format json` with the account's environment (60 s timeout), then reread it.
|
|
281
|
+
2. Call `loadCodeAssist` to learn the project and plan type (falling back to the cached `home/.gemini/antigravity-cli/cache/default_project_id.txt`), then `retrieveUserQuotaSummary`. Each request has a 20 s timeout.
|
|
282
|
+
3. Parse the quota groups into the `gemini` and `other` pools, each with a short (5h) and a weekly window: remaining fraction and reset time.
|
|
283
|
+
4. On `401` the account is warmed up once and retried; if it still fails, the error is recorded and the account is marked `needs login`.
|
|
284
|
+
|
|
285
|
+
A refreshed snapshot with remaining quota above zero for a pool clears that account's cooldowns for the families in that pool. Tokens are never printed. **Network access happens only in `accounts quota --refresh`**, never during dispatch.
|
|
286
|
+
|
|
287
|
+
### Environment variables
|
|
288
|
+
|
|
289
|
+
| Variable | Effect |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `AGY_CREW_ACCOUNT` | Default for `--account` (`auto`, `live` or an account name) |
|
|
292
|
+
| `AGY_CREW_HOME` | Moves the global directory `~/.agy-crew/`, including the pool and its accounts |
|
|
293
|
+
| `AGY_CREW_CLOUDCODE_URL` | Replaces the default `https://cloudcode-pa.googleapis.com` base URL for `accounts quota --refresh` (tests, proxies) |
|
|
294
|
+
|
|
295
|
+
### State layout
|
|
296
|
+
|
|
297
|
+
```
|
|
298
|
+
~/.agy-crew/
|
|
299
|
+
pool.json global pool state (schema 1)
|
|
300
|
+
pool.json.lock lock for pool.json updates
|
|
301
|
+
accounts/<name>/home/ the account's private HOME
|
|
302
|
+
.gemini/antigravity-cli/antigravity-oauth-token file-backed token (never printed)
|
|
303
|
+
.gemini/antigravity-cli/settings.json permissions for this account
|
|
304
|
+
enroll/<random>/home/ staging directory during a first login
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
`pool.json` holds `accounts` (insertion order is the final tie-break), `cooldowns` (keyed `<name>|<family>`), `leases`, `conversations` (conversation id to account), `loans` and `quota` snapshots. Writes are atomic and locked. A missing file is an empty pool; a corrupt file is an error and is never reset; a file with a newer `schema` is refused (`pool.json was written by a newer agy-crew`).
|
|
308
|
+
|
|
309
|
+
### Settings and `setup --apply`
|
|
310
|
+
|
|
311
|
+
`setup --apply` writes the usual permission rules to the live `~/.gemini/antigravity-cli/settings.json` and then applies the same merge to every pool account's `home/.gemini/antigravity-cli/settings.json`, reporting each path. The dry run lists those files too. New accounts seed their permissions from the live settings file on login.
|
|
312
|
+
|
|
313
|
+
### Failure reasons and exit codes
|
|
314
|
+
|
|
315
|
+
| Situation | Reason / output | Exit |
|
|
316
|
+
|---|---|---|
|
|
317
|
+
| No `auto` candidate, or quota hit mid-run with no lender | `quota_exhausted`, with `retry_at` (per account when no candidate) | 5 when a conversation id exists, otherwise 1; a background job ends `attention` or `error` accordingly |
|
|
318
|
+
| Authentication failure on a pool account | account marked `needs login`; never retried | follows the normal error path |
|
|
319
|
+
| Explicit `--account <name>` that is unknown, disabled, cooling or needs login | error before launch naming the reason | 1 |
|
|
320
|
+
| `--account` conflicting with a bound conversation | `conversation <id> belongs to account <x>` | 1 |
|
|
321
|
+
| `accounts` subcommand failure | error on stderr | 1 |
|
|
322
|
+
| `pool.json` corrupt or from a newer agy-crew | refuses to run | 1 |
|
|
323
|
+
|
|
324
|
+
## Troubleshooting
|
|
325
|
+
|
|
326
|
+
- **"agy reported an error (status ERROR)"** — the companion relays agy's own error verbatim, and appends a cause hint only when the error text actually matches one (invalid model id → run `agy models`; expired auth → run `agy` interactively once to re-login; exhausted quota). If agy reported an error but still returned response text, the companion delivers the response anyway — exit 0, response on stdout, warning on stderr (`done_with_warnings`); a deadline with no response but a known conversation instead signals attention (exit 5).
|
|
327
|
+
- **Quota error or `needs login` on a pool account** — see [Accounts](#accounts). A quota failure records a cooldown and is recovered inside the run when another account or an idle lender exists; otherwise the job ends with `quota_exhausted` and a `retry_at`. An authentication failure is never retried: run `agy-crew accounts login <name>` in your own terminal.
|
|
328
|
+
- **`operation not permitted` on `~/.gemini/...` / `bind: operation not permitted` / sudden "authentication failed" while `agy` works in your terminal** — check whether a harness command sandbox is blocking access. AGY needs its OAuth credentials and a localhost port for its internal language server; allowing workspace writes alone may not provide that access. Where those restrictions apply, use the host's authorization mechanism to run the companion in a context that supports AGY. Use the same permission context to start and manage a job.
|
|
329
|
+
- **False crash report on `wait`/`status` ("finished with status crashed and no stored result")** — the background job was started in one permission or sandbox context (e.g. unsandboxed) and collected from another (e.g. inside a command sandbox). The collector cannot see the worker PID across the sandbox boundary and misclassifies the running job as crashed. Run management commands (`wait`, `status`, `result`) in the same unsandboxed permission context as the job start; rerunning from the unsandboxed context resumes waiting or reporting normal status.
|
|
330
|
+
- **Empty response, "status SUCCESS"** — a restricted run may report success even when its tool calls were denied. Check whether the profile came from a flag, repository policy or an earlier conversation. Use `setup` to configure allowed commands, or pass `--unrestricted` explicitly if authorized; dropping `--restricted` alone does not override an inherited profile. Some native tools remain unavailable in restricted headless runs even with allow-rules. An empty response from unrestricted mode or tool-free ask needs a separate diagnosis; retain the diagnostics and report it.
|
|
331
|
+
- **"unknown flag --X: the whole string … arrived as a single argument"** — several flags, and usually the task, are quoted into one argument. Each flag is its own argument; the task belongs in `--prompt`. See [Task text](#task-text).
|
|
332
|
+
- **"task text exceeds the 200KB inline limit"** — the companion ultimately passes the complete prompt to AGY as one command-line argument. `--prompt-file` and `--stdin` simplify input but do not remove that limit. Shorten the task text by referring to a PR, branch or file, and let AGY read the material itself.
|
|
333
|
+
- **Workspace attachment** — foreground and background calls pass `--add-dir <repoRoot>` (the launch directory outside Git), including continuation and restart. Without explicit attachment, tested AGY print-mode sessions can start in `~/.gemini/antigravity-cli/scratch` even without `--sandbox`; inherited shell cwd or trusted-workspace settings alone do not attach the repo. The companion does not pass `--sandbox`. Workspace attachment grants scoped file reads; restricted commands still need their allow-rules.
|
|
334
|
+
- **Dirty workspace on implement** — `implement` can start even when the repo already has changes. The companion adds a capped status summary to agy's prompt so it knows those paths are pre-existing user work. If the task does not clearly include them, agy should ask before overwriting, cleaning, stashing, resetting, deleting, committing, pushing, or opening a PR with those changes.
|
|
335
|
+
- **"agy modified the working tree during this review"** — an unrestricted `research`/`review` run changed files it was asked to preserve. Inspect the listed paths to identify changes from this run before deciding what to revert, preserving pre-existing user work.
|
|
336
|
+
- **Project-scoped agy permissions** — agy has project-level rules ("highest priority") tied to its `--project` system; the settings-file path for those is undocumented and unverified, so setup only edits the global file. If a rule seems ignored, check agy interactively. See [Advanced: project-scoped permissions](#advanced-project-scoped-permissions).
|
|
337
|
+
- **Rules context** — agy auto-loads `AGENTS.md`/`GEMINI.md`/`.agents/rules/*.md` from the workspace; keep those files sane in repos where you delegate.
|
|
338
|
+
|
|
339
|
+
The migration sections below are inherited agy-staff history. The `/agy:` names in them belong to the upstream plugin; in agy-crew the same personas are invoked as shown in [Modes and defaults](#modes-and-defaults).
|
|
340
|
+
|
|
341
|
+
## Migration from 0.1
|
|
342
|
+
|
|
343
|
+
0.2 renamed the permission profiles, changed which profile the modes default to, and dropped the flags that 0.1 used to steer review and execution.
|
|
344
|
+
|
|
345
|
+
| 0.1 | 0.2 | Notes |
|
|
346
|
+
|---|---|---|
|
|
347
|
+
| `research`/`review` default to the strict (restricted) profile | `research`/`review`/`implement` default to `unrestricted` | 0.1 fail-closed research and review unless you ran setup first. 0.2 works out of the box and makes `--restricted` the opt-in hardening flag; `ask` still runs restricted (tool-free). |
|
|
348
|
+
| `--strict` | `--restricted` | Old name accepted as a deprecated compatibility alias; it warns on stderr. Same semantics. |
|
|
349
|
+
| `--loose` | `--unrestricted` | Old name accepted as a deprecated compatibility alias; it warns on stderr. Same semantics. |
|
|
350
|
+
| profile names "strict"/"loose" in output | "restricted"/"unrestricted" | Cosmetic rename; the telemetry line (stderr) now prints `profile=restricted` / `profile=unrestricted`. |
|
|
351
|
+
| `--diff-file <path>` | *(removed)* | Review is prompt-based: `review --prompt "Review the patch at /tmp/change.patch"`. |
|
|
352
|
+
| `--pr <num>` | *(removed)* | `review --prompt "Review PR #730"`. |
|
|
353
|
+
| `--target <ref>` | *(removed)* | `review --prompt "Review changes against master"`. |
|
|
354
|
+
| `--background` / `--wait` | *(removed)* | Execution style is fixed per mode: `ask` is synchronous, `research`/`review`/`implement` return a job id. Manage them with `status`/`result`/`cancel`. |
|
|
355
|
+
|
|
356
|
+
Removed flags fail fast with a message naming the replacement. The deprecated profile aliases remain accepted for compatibility; use `--restricted` and `--unrestricted` in new commands and scripts.
|
|
357
|
+
|
|
358
|
+
## Migration from 0.3
|
|
359
|
+
|
|
360
|
+
0.4 consolidated the two invocation layers (commands + skills) into a single skills layer with persona names, added the `staffer` mode, and made `.agy-crew/` hygiene automatic.
|
|
361
|
+
|
|
362
|
+
| 0.3 | 0.4 | Notes |
|
|
363
|
+
|---|---|---|
|
|
364
|
+
| `/agy:research` (command) + `/agy:agy-research` (skill) | `/agy:researcher` | one skill per persona; the command layer is gone |
|
|
365
|
+
| `/agy:review` + `/agy:agy-review` | `/agy:reviewer` | now routes two flavors: code review and general (plan/decision) review |
|
|
366
|
+
| `/agy:implement` + `/agy:agy-implement` | `/agy:implementer` | |
|
|
367
|
+
| `/agy:ask` + `/agy:agy-ask` | `/agy:ask` | unchanged name, single entry |
|
|
368
|
+
| *(none)* | `/agy:staffer` | new general-purpose mode with a minimal prompt |
|
|
369
|
+
| `/agy:status`, `/agy:wait`, `/agy:result`, `/agy:cancel`, `/agy:continue`, `/agy:setup` | the `jobs` skill (model-facing) | ask in natural language ("is the agy job done?"); the companion subcommands are unchanged |
|
|
370
|
+
| manual `.git/info/exclude` step | automatic on first run | |
|
|
371
|
+
|
|
372
|
+
## Migration from 0.4.4 (breaking)
|
|
373
|
+
|
|
374
|
+
0.4.5 removes positional task text. The companion parses the shell's argv once and never re-splits an argument, which is what makes flag-like text inside a task safe (see [Task text](#task-text)). The price is that the task must arrive through an explicit source.
|
|
375
|
+
|
|
376
|
+
| 0.4.4 | 0.4.5 | Notes |
|
|
377
|
+
|---|---|---|
|
|
378
|
+
| `ask "question"`, `review "Review PR #730"` (positional task text) | `ask --prompt "question"`, `review --prompt "Review PR #730"` | Positional text is removed, not deprecated: a positional argument on a run command is an error naming the three sources. `--prompt-file` and `--stdin` are unchanged. |
|
|
379
|
+
| one big string, e.g. `review "--restricted Review PR #730"` | `review --restricted --prompt "Review PR #730"` | The companion no longer splits an argument into flags. A flag name that still contains whitespace gets an error naming this fix. |
|
|
380
|
+
|
|
381
|
+
Management commands (`status`, `wait`, `result`, `cancel`, `setup`) are untouched: their positional arguments are ids and values, and `wait <id> --timeout 30s` works exactly as before.
|
|
382
|
+
|
|
383
|
+
## Migration from 0.4.5
|
|
384
|
+
|
|
385
|
+
0.5.0 updates all persona defaults and the `flash` alias/`--effort` shorthand from Gemini 3.7 Flash to Gemini 3.8 Flash while preserving each persona effort tier (`ask`: low; `staffer` & `reviewer`: medium; `researcher` & `implementer`: high).
|
|
386
|
+
|
|
387
|
+
If the installed `agy` CLI does not support Gemini 3.8 Flash, the companion fails clearly without silent fallback: it queries `agy models` and reports available models alongside the best same-effort compatible recommendation (e.g. `--model gemini-3.7-flash-high`), advising that updating `agy` is preferred to use the latest default.
|
|
388
|
+
|
|
389
|
+
## Windows support
|
|
390
|
+
|
|
391
|
+
Windows is supported on a best-effort basis and exercised by the `Tests (Windows)` CI job; it has not yet been validated against a real Windows `agy` installation. Subprocesses are spawned with `windowsHide: true` so no console windows appear during background execution. Job cancellation and process cleanup discover descendant processes via PowerShell (`Get-CimInstance Win32_Process`, with `CreationDate` in round-trip precision) and terminate each identified member individually; the leader falls to `taskkill /PID <pid> /F`, never `/T`. A parent link is only followed when the child was created after its parent: Windows keeps a dead parent's PID in `ParentProcessId`, so once that PID is reused an unrelated orphan (typically another job's detached worker) would otherwise look like a descendant and be killed. State locking retries transient Windows errors (`EPERM`/`EBUSY`/`EACCES`) when renaming or unlinking lock directories and marker files.
|
|
392
|
+
|
|
393
|
+
## OpenCode
|
|
394
|
+
|
|
395
|
+
The dependency-free `opencode.mjs` entrypoint implements the OpenCode V1 plugin config hook (verified with 1.18.34). Install the full package with `opencode plugin 'agy-crew@git+https://github.com/pStrikeZ/agy-crew.git' --global`, then restart OpenCode and run `/agy-crew-ask reply with OK`. The companion requires Node.js and an authenticated `agy` on PATH. OpenCode V2 is not covered.
|
|
396
|
+
|
|
397
|
+
The native installer adds a package entry to the `plugin` array in the OpenCode config. The equivalent configuration is:
|
|
398
|
+
|
|
399
|
+
```json
|
|
400
|
+
{
|
|
401
|
+
"plugin": ["agy-crew@git+https://github.com/pStrikeZ/agy-crew.git"]
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
The plugin appends its absolute bundled `opencode-skills/` directory to `skills.paths`, preserving existing paths and avoiding duplicate registrations. OpenCode discovers eight branded skills and exposes them as same-named slash commands: `/agy-crew-ask`, `/agy-crew-staffer`, `/agy-crew-researcher`, `/agy-crew-reviewer`, `/agy-crew-implementer`, `/agy-crew-jobs`, `/agy-crew-accounts`, and `/agy-crew-lead`. No command wrappers are installed. Existing OpenCode skill permissions still apply.
|
|
406
|
+
|
|
407
|
+
`npm run generate:opencode` generates these entrypoints from canonical `skills/`, copying all assets, rewriting invocation syntax and sibling paths, and appending the same host compatibility context as Pi. The companion and prompt templates remain shared. Install the whole package; copying only the plugin file would lose its relative resources.
|
|
408
|
+
|
|
409
|
+
For local development, run `opencode plugin /absolute/path/to/checkout --global`, generate skills with `npm run generate:skills`, and restart OpenCode. This reads the checkout directly. For Git installs, OpenCode 1.18.34 caches by the full package spec; restart or `--force` alone does not refresh an unchanged spec. Upgrade by choosing a newer tag or commit and running `opencode plugin 'agy-crew@git+https://github.com/pStrikeZ/agy-crew.git#<tag-or-commit>' --global --force`, then restart. The selected ref must contain this adapter. `--force` replaces the configured plugin entry; changing the ref gives the new install a distinct cache key.
|
|
410
|
+
|
|
411
|
+
## Install command
|
|
412
|
+
|
|
413
|
+
`agy-crew install` is the terminal route to installing the skills. It renders them once into a shared bundle and links that bundle into every harness it finds, instead of each harness keeping its own plugin cache. Requirements: Node.js 20+ and a working `agy` on PATH (`agy --version`).
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
npm install -g agy-crew
|
|
417
|
+
agy-crew install
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
From a checkout: `git clone https://github.com/pStrikeZ/agy-crew && cd agy-crew && npm link`, then `agy-crew install`. The skills then run straight from the checkout, so a `git pull` is live immediately; re-run `agy-crew install` after pulling so the bundle is refreshed.
|
|
421
|
+
|
|
422
|
+
### Commands and flags
|
|
423
|
+
|
|
424
|
+
| Command | Effect |
|
|
425
|
+
|---|---|
|
|
426
|
+
| `agy-crew install` | Detect the harnesses present (by their config directories) and install into each |
|
|
427
|
+
| `agy-crew install --hosts claude,codex,omp,opencode,dsh` | Install into an explicit list instead of auto-detecting |
|
|
428
|
+
| `agy-crew install --all` | Install into every supported host |
|
|
429
|
+
| `agy-crew install --dry-run` | Print the plan; write nothing |
|
|
430
|
+
| `agy-crew install --status` | Show per-host link state and bundles |
|
|
431
|
+
| `agy-crew install --json` | Machine-readable output (combine with any of the above) |
|
|
432
|
+
| `agy-crew uninstall [--hosts …\|--all]` | Remove only the links the installer created |
|
|
433
|
+
|
|
434
|
+
### Hosts
|
|
435
|
+
|
|
436
|
+
| Host (`--hosts` id) | Skills directory |
|
|
437
|
+
|---|---|
|
|
438
|
+
| Claude Code (`claude`) | `~/.claude/skills` |
|
|
439
|
+
| Codex (`codex`) | `~/.agents/skills` |
|
|
440
|
+
| Oh My Pi (`omp`) | `~/.omp/agent/skills` |
|
|
441
|
+
| OpenCode (`opencode`) | `~/.config/opencode/skills` |
|
|
442
|
+
| DeepSeek Harness (`dsh`) | `~/.dsh/skills` |
|
|
443
|
+
|
|
444
|
+
Pi is not covered by `install`; use the Pi package route (`pi install git:github.com/pStrikeZ/agy-crew`).
|
|
445
|
+
|
|
446
|
+
### Mechanics
|
|
447
|
+
|
|
448
|
+
The skills are rendered once into `~/.agy-crew/bundles/<version>-<digest>/` with absolute companion paths. Each harness gets one directory link per persona (`agy-crew-<persona>`, for example `agy-crew-staffer`) pointing into that bundle; on Windows the link is a junction, which needs no elevation. The global directory `~/.agy-crew/` can be moved with the `AGY_CREW_HOME` environment variable.
|
|
449
|
+
|
|
450
|
+
User-level skills are invoked as `/agy-crew-staffer` on every harness (Codex lists them as `$agy-crew-staffer`). Restart the harness or open a new session afterwards; smoke test with `/agy-crew-ask reply with OK`. The `ask` persona runs no tools and needs no permission setup.
|
|
451
|
+
|
|
452
|
+
### Conflict policy
|
|
453
|
+
|
|
454
|
+
Anything in a skills directory that the installer did not create is user content and is never overwritten. Any conflict aborts the whole run before anything is written (all-or-nothing) and prints the offending paths together with a remedy. `uninstall` likewise removes only links it created.
|
|
455
|
+
|
|
456
|
+
### Mutual exclusion with agy-staff
|
|
457
|
+
|
|
458
|
+
agy-crew and the upstream [agy-staff](https://github.com/keli-wen/agy-staff) must not be installed on the same machine: the skills would appear twice to the agent, and both companions would write the same per-repository state. `agy-crew install` refuses to run when it finds agy-staff and says how to remove it:
|
|
459
|
+
|
|
460
|
+
- **Claude Code** — `claude plugin uninstall agy@agy-staff`
|
|
461
|
+
- **Codex** — remove the agy-staff plugin, then restart Codex
|
|
462
|
+
- **OpenCode** — remove the `agy-staff@…` entry from the `plugin` array in `opencode.json`
|
|
463
|
+
- **Pi** — uninstall the agy-staff package
|
|
464
|
+
- **Any harness** — remove upstream flat skills (`agy-ask`, `agy-jobs`, …) from the skills directory
|
|
465
|
+
|
|
466
|
+
To get upstream back later, run `agy-crew uninstall --all` first.
|
|
467
|
+
|
|
468
|
+
### Permission setup
|
|
469
|
+
|
|
470
|
+
`setup` still edits the global `~/.gemini/antigravity-cli/settings.json`; since 0.9.0, `setup --apply` also applies the same permission merge to every pool account's own `settings.json` (see [Settings and `setup --apply`](#settings-and-setup---apply)). The per-repository policy file is `.agy-crew/config.json`.
|
|
471
|
+
|
|
472
|
+
## Upgrading
|
|
473
|
+
|
|
474
|
+
Claude Code and Codex cache the plugin under a per-**version** directory (e.g. `cache/agy-crew/agy-crew/0.9.2`) and key "is it current?" on that version string, not on the commit. Bump their manifests and `package.json` together when preparing a release. Pi's Git source instead follows the configured ref; local sources read the checkout directly.
|
|
475
|
+
|
|
476
|
+
- **Terminal command (`agy-crew install`)** — for an npm install, run `npm install -g agy-crew@latest`, then `agy-crew install` to render a fresh bundle and re-link; restart the harness. For a checkout, `git pull` is live at once for the source, and `agy-crew install` refreshes the bundle. See [Install command](#install-command).
|
|
477
|
+
- **Claude Code** — `claude plugin marketplace update agy-crew` refreshes the marketplace clone, then `claude plugin update agy-crew@agy-crew` re-copies it into the cache. `install` is **not** the upgrade command: on an already-installed plugin it answers "already installed" and does nothing, whatever the version. And `update` only moves if the version string changed — on an unchanged version it answers "already at the latest version" and leaves the old commit in place. Force the current commit in with `claude plugin uninstall agy-crew@agy-crew && claude plugin install agy-crew@agy-crew`. Restart Claude Code afterwards either way — skills are registered at session start.
|
|
478
|
+
- **Codex** — bump the version, run `codex plugin marketplace upgrade` (or remove and re-add the marketplace entry), then restart the app.
|
|
479
|
+
- **OpenCode** — use a newer Git tag/commit in the native plugin installer with `--force`, then restart; see [OpenCode](#opencode).
|
|
480
|
+
- **Pi** — for an unpinned Git install, run `pi update --extension git:github.com/pStrikeZ/agy-crew`, then `/reload`. For local development, regenerate Pi skills (`npm run generate:pi`) and run `/reload`; no push is needed.
|
|
481
|
+
|
|
482
|
+
You can check which commit is actually installed: the `gitCommitSha` in `~/.claude/plugins/installed_plugins.json`, versus `git -C ~/.claude/plugins/marketplaces/agy-crew log -1` for what the marketplace clone has fetched.
|
|
483
|
+
|
|
484
|
+
## Repository layout
|
|
485
|
+
|
|
486
|
+
```
|
|
487
|
+
companion/agy-companion.mjs command entrypoint, modes, job management and setup
|
|
488
|
+
companion/identity.mjs product identity constants (names, prefixes, state directories, AGY_CREW_HOME)
|
|
489
|
+
companion/install.mjs cross-harness installer behind `agy-crew install` / `uninstall`
|
|
490
|
+
companion/accounts.mjs `accounts` subcommands
|
|
491
|
+
companion/pool/ account pool: state, selection, loans, quota, classifiers, isolated environment
|
|
492
|
+
companion/stream-worker.mjs streaming execution, process cleanup and deadlines
|
|
493
|
+
companion/observation.mjs event parsing, progress snapshots and output budgets
|
|
494
|
+
companion/state-lock.mjs state-write locking and stale-lock recovery
|
|
495
|
+
templates/ shared prompt templates (staffer/ask/research/review/implement) and harness-compatibility.md
|
|
496
|
+
.claude-plugin/ Claude Code plugin + self-hosting marketplace manifests
|
|
497
|
+
.codex-plugin/plugin.json Codex plugin manifest
|
|
498
|
+
.agents/plugins/ Codex marketplace manifest
|
|
499
|
+
pi-skills/ generated agy-* entrypoints/resources for Pi; do not hand-edit
|
|
500
|
+
opencode-skills/ generated agy-* entrypoints/resources for OpenCode; do not hand-edit
|
|
501
|
+
opencode.mjs OpenCode V1 package plugin; registers bundled skills
|
|
502
|
+
scripts/generate-skills.mjs generates Pi/OpenCode skills and checks for drift
|
|
503
|
+
package.json Pi manifest, OpenCode entrypoint, npm file allowlist, and verification commands
|
|
504
|
+
skills/ canonical personas + jobs (Claude/Codex entrypoints;
|
|
505
|
+
reviewer/ and jobs/ carry references/ for on-demand detail)
|
|
506
|
+
assets/ design diagram + logo + badges
|
|
507
|
+
tests/ offline regression tests and opt-in integration suites
|
|
508
|
+
docs/ references, installation guide and release notes
|
|
509
|
+
```
|