@aibridge/cli 0.9.0 → 0.10.0
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/README.md +48 -28
- package/dist/cli.mjs +1 -1
- package/dist/{context-BQgclUqy.mjs → context-DeJmEXLe.mjs} +59 -5
- package/dist/index.mjs +1 -1
- package/instructions/SKILL.md +115 -0
- package/instructions/reference/image-gen.md +107 -0
- package/instructions/reference/implement.md +51 -0
- package/instructions/reference/plan.md +69 -0
- package/instructions/reference/review.md +75 -0
- package/instructions/reference/subagent.md +48 -0
- package/instructions/reference/why.md +54 -0
- package/package.json +6 -5
- package/src/app.exit-code.test.ts +10 -1
- package/src/app.ts +4 -5
- package/src/commands/skill/command.ts +28 -0
- package/src/commands/skill/impl.test.ts +59 -0
- package/src/commands/skill/impl.ts +60 -0
- package/src/package.ts +5 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# aibridge
|
|
5
5
|
|
|
6
|
-
**Let your coding agent
|
|
6
|
+
**Let your coding agent use the other AI CLIs on your machine.** Plan, implement, review, red-team, and generate images with Grok, Gemini, Codex, and Claude. No API keys.
|
|
7
7
|
|
|
8
8
|
[](https://skills.sh/ycmjason/aibridge)
|
|
9
9
|
[](https://www.npmjs.com/package/@aibridge/cli)
|
|
@@ -15,38 +15,42 @@
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
Your agent
|
|
18
|
+
Your coding agent uses one model. Your machine may already have others available
|
|
19
|
+
through `grok`, `agy` (Antigravity), `codex`, or `claude`. **aibridge** lets your
|
|
20
|
+
agent use those models as planners, implementers, reviewers, one-shot delegates,
|
|
21
|
+
and image generators. Each model runs through its existing CLI login.
|
|
19
22
|
|
|
20
23
|
## Install
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
Install the skill into your agent:
|
|
23
26
|
|
|
24
27
|
```bash
|
|
25
28
|
npx skills add ycmjason/aibridge
|
|
26
29
|
```
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
The skill runs the CLI on demand with `npx -y @aibridge/cli`. Ask your agent to
|
|
32
|
+
"use aibridge", or run a command directly:
|
|
29
33
|
|
|
30
34
|
```bash
|
|
31
35
|
npx -y @aibridge/cli subagent --model xai-grok/grok-4.6 "summarize the architecture of this repo"
|
|
32
36
|
```
|
|
33
37
|
|
|
34
|
-
<sup>
|
|
38
|
+
<sup>Optional: install `aibridge` on your PATH with `npm i -g @aibridge/cli`.</sup>
|
|
35
39
|
|
|
36
40
|
## Commands
|
|
37
41
|
|
|
38
42
|
| Command | Use when |
|
|
39
43
|
|---|---|
|
|
40
|
-
| `aibridge plan --model xai-grok/grok-4.6 --out plan.md "<task>"` |
|
|
41
|
-
| `aibridge implement --model google-antigravity/gemini-3.7-flash <plan.md>` |
|
|
42
|
-
| `aibridge review --model xai-grok/grok-4.6 --out review.md [--plan <plan.md>]` |
|
|
43
|
-
| `aibridge subagent --model xai-grok/grok-4.6 "<task>"` |
|
|
44
|
-
| `aibridge image-gen --model openai-codex/gpt-5.6-sol --out out.png "<prompt>"` |
|
|
45
|
-
| `aibridge models [--json]` |
|
|
46
|
-
| `aibridge quota` |
|
|
47
|
-
| `aibridge runs` | Inspect or watch
|
|
44
|
+
| `aibridge plan --model xai-grok/grok-4.6 --out plan.md "<task>"` | Study the repo and write a detailed plan file |
|
|
45
|
+
| `aibridge implement --model google-antigravity/gemini-3.7-flash <plan.md>` | Execute an approved plan and run the project's checks |
|
|
46
|
+
| `aibridge review --model xai-grok/grok-4.6 --out review.md [--plan <plan.md>] [--base <ref>]` | Review a diff or, on a clean tree, a plan |
|
|
47
|
+
| `aibridge subagent --model xai-grok/grok-4.6 "<task>"` | Delegate a self-contained task or request a second opinion |
|
|
48
|
+
| `aibridge image-gen --model openai-codex/gpt-5.6-sol --out out.png "<prompt>"` | Generate and verify a raster image |
|
|
49
|
+
| `aibridge models [--json]` | List registered models and their capabilities |
|
|
50
|
+
| `aibridge quota` | Show quota remaining for every backend |
|
|
51
|
+
| `aibridge runs` | Inspect or watch run logs in `~/.aibridge/runs` |
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
Use `plan`, `implement`, and `review` as one controlled workflow:
|
|
50
54
|
|
|
51
55
|
```
|
|
52
56
|
aibridge plan --model xai-grok/grok-4.6 --out plan.md "add rate limiting to the API" # delegate writes plan.md
|
|
@@ -55,21 +59,26 @@ aibridge implement --model google-antigravity/gemini-3.7-flash plan.md
|
|
|
55
59
|
aibridge review --model xai-grok/grok-4.6 --out review.md --plan plan.md # a third seat cross-checks the diff
|
|
56
60
|
```
|
|
57
61
|
|
|
58
|
-
|
|
62
|
+
Only the plan path passes between stages, which keeps the plan out of the
|
|
63
|
+
orchestrator's conversation context.
|
|
59
64
|
|
|
60
65
|
## How it works
|
|
61
66
|
|
|
62
|
-
- **The skill
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
- **
|
|
67
|
+
- **The skill decides; the CLI executes.** The skill covers routing and prompt
|
|
68
|
+
design. The CLI starts the backend, captures output, validates known failure
|
|
69
|
+
modes, and logs the run.
|
|
70
|
+
- **Review stays cross-model.** The recommended workflow uses Grok to plan and
|
|
71
|
+
review, and Gemini to implement.
|
|
72
|
+
- **Existing logins, no API keys.** Each backend uses its CLI login and quota.
|
|
73
|
+
- **Every model has a canonical slug:**
|
|
74
|
+
`<vendor>-<cli>/<model>[-<effort>]`, such as `xai-grok/grok-4.6` or
|
|
75
|
+
`openai-codex/gpt-5.6-sol-high`. There are no aliases. Run
|
|
76
|
+
`aibridge <command> --help` for the current list.
|
|
66
77
|
|
|
67
78
|
## Tell your agent when to reach for it
|
|
68
79
|
|
|
69
|
-
aibridge
|
|
70
|
-
|
|
71
|
-
your agent already reads at the start of every session (`AGENTS.md`, `CLAUDE.md`,
|
|
72
|
-
`.cursorrules`, …). Something like:
|
|
80
|
+
aibridge does not decide when to delegate. Put a routing rule in the instructions
|
|
81
|
+
file your agent reads (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`, and so on):
|
|
73
82
|
|
|
74
83
|
```markdown
|
|
75
84
|
## Delegation gate — decide before you implement
|
|
@@ -91,21 +100,32 @@ Delegated work is yours to verify: re-run the real gates before trusting a diff.
|
|
|
91
100
|
Prefer a reviewer from a different model family than whoever implemented.
|
|
92
101
|
```
|
|
93
102
|
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
Adjust the models and thresholds for your quotas. Make the routing decision before
|
|
104
|
+
implementation starts.
|
|
96
105
|
|
|
97
106
|
## Requirements
|
|
98
107
|
|
|
99
108
|
- **Node ≥ 24.11**
|
|
100
|
-
-
|
|
109
|
+
- At least one authenticated backend CLI on `PATH`:
|
|
110
|
+
[`grok`](https://github.com/superagent-ai/grok-cli), `agy` (Antigravity),
|
|
111
|
+
[`codex`](https://github.com/openai/codex), or
|
|
112
|
+
[`claude`](https://claude.com/claude-code). Missing CLIs produce install hints.
|
|
101
113
|
|
|
102
114
|
## Packages
|
|
103
115
|
|
|
104
|
-
|
|
116
|
+
Packages use the [`@aibridge`](https://www.npmjs.com/org/aibridge) scope:
|
|
117
|
+
[`@aibridge/cli`](https://www.npmjs.com/package/@aibridge/cli),
|
|
118
|
+
`@aibridge/proc`, and one reusable driver for each backend:
|
|
119
|
+
`driver-agy`, `driver-grok`, `driver-codex`, and `driver-claude`.
|
|
105
120
|
|
|
106
121
|
## Security
|
|
107
122
|
|
|
108
|
-
|
|
123
|
+
In tools mode, delegates can read files, write files, and run shell commands with
|
|
124
|
+
the same access as the invoking agent. Task content is sent to the selected
|
|
125
|
+
provider. Use `--no-tools` for untrusted input. Packages are published from this
|
|
126
|
+
public repository through OIDC with
|
|
127
|
+
[SLSA provenance](https://www.npmjs.com/package/@aibridge/cli) and no install-time
|
|
128
|
+
scripts.
|
|
109
129
|
|
|
110
130
|
## Contributing & development
|
|
111
131
|
|
package/dist/cli.mjs
CHANGED
|
@@ -1656,6 +1656,62 @@ const runs = buildCommand({
|
|
|
1656
1656
|
fullDescription: fullDescription$1
|
|
1657
1657
|
}
|
|
1658
1658
|
});
|
|
1659
|
+
const PACKAGE_VERSION = createRequire(import.meta.url)("../package.json").version;
|
|
1660
|
+
//#endregion
|
|
1661
|
+
//#region src/commands/skill/impl.ts
|
|
1662
|
+
const TOPICS = {
|
|
1663
|
+
plan: "reference/plan.md",
|
|
1664
|
+
implement: "reference/implement.md",
|
|
1665
|
+
review: "reference/review.md",
|
|
1666
|
+
subagent: "reference/subagent.md",
|
|
1667
|
+
"image-gen": "reference/image-gen.md",
|
|
1668
|
+
why: "reference/why.md"
|
|
1669
|
+
};
|
|
1670
|
+
function instructionPath(relativePath) {
|
|
1671
|
+
const found = [new URL(`../instructions/${relativePath}`, import.meta.url), new URL(`../../../instructions/${relativePath}`, import.meta.url)].find((candidate) => existsSync(candidate));
|
|
1672
|
+
if (!found) throw new Error(`bundled instruction file is missing: ${relativePath}`);
|
|
1673
|
+
return found;
|
|
1674
|
+
}
|
|
1675
|
+
function readInstruction(relativePath) {
|
|
1676
|
+
return readFileSync(instructionPath(relativePath), "utf8").trimEnd();
|
|
1677
|
+
}
|
|
1678
|
+
function skillImpl(topic) {
|
|
1679
|
+
if (topic !== void 0 && !(topic in TOPICS)) {
|
|
1680
|
+
this.process.stderr.write(`aibridge skill: unknown topic ${JSON.stringify(topic)}; expected one of: ${Object.keys(TOPICS).join(", ")}\n`);
|
|
1681
|
+
this.process.exitCode = 2;
|
|
1682
|
+
return;
|
|
1683
|
+
}
|
|
1684
|
+
try {
|
|
1685
|
+
const sections = [`Command runner for these instructions: \`${`npx -y @aibridge/cli@${PACKAGE_VERSION}`}\`\nUse that exact prefix for every aibridge command below; do not substitute a global binary.`, readInstruction("SKILL.md")];
|
|
1686
|
+
if (topic !== void 0) sections.push(readInstruction(TOPICS[topic]));
|
|
1687
|
+
this.process.stdout.write(`${sections.join("\n\n---\n\n")}\n`);
|
|
1688
|
+
} catch (error) {
|
|
1689
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1690
|
+
this.process.stderr.write(`aibridge skill: ${message}\n`);
|
|
1691
|
+
this.process.exitCode = 1;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
//#endregion
|
|
1695
|
+
//#region src/commands/skill/command.ts
|
|
1696
|
+
function skillCommand(_flags, topic) {
|
|
1697
|
+
skillImpl.call(this, topic);
|
|
1698
|
+
}
|
|
1699
|
+
const skill = buildCommand({
|
|
1700
|
+
func: skillCommand,
|
|
1701
|
+
parameters: {
|
|
1702
|
+
flags: {},
|
|
1703
|
+
positional: {
|
|
1704
|
+
kind: "tuple",
|
|
1705
|
+
parameters: [{
|
|
1706
|
+
brief: "Command-specific instructions to append to the router",
|
|
1707
|
+
parse: String,
|
|
1708
|
+
placeholder: "topic",
|
|
1709
|
+
optional: true
|
|
1710
|
+
}]
|
|
1711
|
+
}
|
|
1712
|
+
},
|
|
1713
|
+
docs: { brief: "Print the canonical agent instructions bundled with this CLI" }
|
|
1714
|
+
});
|
|
1659
1715
|
//#endregion
|
|
1660
1716
|
//#region src/commands/subagent/impl.ts
|
|
1661
1717
|
async function subagent$1(flags, prompt) {
|
|
@@ -1777,9 +1833,6 @@ function normalizeExitCode(ctx) {
|
|
|
1777
1833
|
}
|
|
1778
1834
|
if (code !== 0 && code !== 1 && code !== 2 && code !== 3) ctx.process.exitCode = 1;
|
|
1779
1835
|
}
|
|
1780
|
-
//#endregion
|
|
1781
|
-
//#region src/app.ts
|
|
1782
|
-
const { version } = createRequire(import.meta.url)("../package.json");
|
|
1783
1836
|
const app = buildApplication(buildRouteMap({
|
|
1784
1837
|
routes: {
|
|
1785
1838
|
plan,
|
|
@@ -1789,12 +1842,13 @@ const app = buildApplication(buildRouteMap({
|
|
|
1789
1842
|
"image-gen": imageGen,
|
|
1790
1843
|
runs,
|
|
1791
1844
|
quota,
|
|
1792
|
-
models
|
|
1845
|
+
models,
|
|
1846
|
+
skill
|
|
1793
1847
|
},
|
|
1794
1848
|
docs: { brief: "Bridge tasks to the other AI CLIs on this machine — a plan → implement → review workflow, task delegation, and image generation (codex / agy / grok seats)." }
|
|
1795
1849
|
}), {
|
|
1796
1850
|
name: "aibridge",
|
|
1797
|
-
versionInfo: { currentVersion:
|
|
1851
|
+
versionInfo: { currentVersion: PACKAGE_VERSION },
|
|
1798
1852
|
scanner: { caseStyle: "allow-kebab-for-camel" }
|
|
1799
1853
|
});
|
|
1800
1854
|
/** Public entry used by cli.ts and index.ts — preserves runCli(ctx, argv) surface. */
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as supportsImageGen, _ as backendModelId, a as readRunLogs, b as listModelHelpLines, c as evaluateAgyPreflight, d as preflightModel, f as renderPreflightRefusal, g as MODELS, h as positiveIntSeconds, i as listRuns, l as evaluateCodexPreflight, m as nonEmptyPrompt, n as app, o as startRun, p as getDriver, r as runCli, s as delegate, t as buildContext, u as preflightCodex, v as formatImageGenModelError, x as resolveModel, y as formatUnknownModelError } from "./context-
|
|
1
|
+
import { S as supportsImageGen, _ as backendModelId, a as readRunLogs, b as listModelHelpLines, c as evaluateAgyPreflight, d as preflightModel, f as renderPreflightRefusal, g as MODELS, h as positiveIntSeconds, i as listRuns, l as evaluateCodexPreflight, m as nonEmptyPrompt, n as app, o as startRun, p as getDriver, r as runCli, s as delegate, t as buildContext, u as preflightCodex, v as formatImageGenModelError, x as resolveModel, y as formatUnknownModelError } from "./context-DeJmEXLe.mjs";
|
|
2
2
|
export { MODELS, app, backendModelId, buildContext, delegate, evaluateAgyPreflight, evaluateCodexPreflight, formatImageGenModelError, formatUnknownModelError, getDriver, listModelHelpLines, listRuns, nonEmptyPrompt, positiveIntSeconds, preflightCodex, preflightModel, readRunLogs, renderPreflightRefusal, resolveModel, runCli, startRun, supportsImageGen };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# aibridge
|
|
2
|
+
|
|
3
|
+
Use other providers' authenticated AI CLIs as delegates. You choose the task,
|
|
4
|
+
model, and prompt; aibridge runs the backend and validates its output. Each run
|
|
5
|
+
spends the selected backend's quota.
|
|
6
|
+
|
|
7
|
+
Load the `why` topic only when a rule appears unsuitable.
|
|
8
|
+
|
|
9
|
+
## Running it
|
|
10
|
+
|
|
11
|
+
The output header defines the exact command runner for this instruction set.
|
|
12
|
+
Examples below abbreviate that runner as `aibridge`; always substitute the exact
|
|
13
|
+
runner. This keeps instructions and executable behavior on the same version.
|
|
14
|
+
|
|
15
|
+
Requires Node 24.11 or later. If Node is older, ask the user to upgrade with
|
|
16
|
+
`nvm install 24` or `mise use node@24`. Ask before any global install.
|
|
17
|
+
|
|
18
|
+
Backing CLIs must be on `PATH` and authed: `grok`, `agy` (Antigravity), `codex`,
|
|
19
|
+
`claude`. Any subset works; commands fail fast with install hints.
|
|
20
|
+
|
|
21
|
+
## Where `--out` goes
|
|
22
|
+
|
|
23
|
+
- Put permanent project assets in their final location, such as
|
|
24
|
+
`--out public/icons/settings.png`.
|
|
25
|
+
- Put plans, reviews, and drafts in `<repo root>/.aibridge/`. Outside a
|
|
26
|
+
repository, use `.aibridge/` under the current directory.
|
|
27
|
+
- Name files by topic. Promote a draft to its real path once it is the keeper.
|
|
28
|
+
- Once per session, before the first write: `git check-ignore -q .aibridge/`
|
|
29
|
+
Keep the trailing slash so a directory-only rule matches before the directory
|
|
30
|
+
exists. If the command fails, ask to add `.aibridge/` to `.gitignore`.
|
|
31
|
+
- An explicit path from the user wins over all of this.
|
|
32
|
+
|
|
33
|
+
## Subcommands
|
|
34
|
+
|
|
35
|
+
| Command | Description |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `plan` | Expand a task into a detailed implementation plan file |
|
|
38
|
+
| `implement` | Implement a plan file in place and run the real checks |
|
|
39
|
+
| `review` | Review a diff, commit range, or plan contract |
|
|
40
|
+
| `subagent` | Delegate a self-contained task to another model |
|
|
41
|
+
| `image-gen` | Generate a raster image with a Codex, Antigravity, or Grok seat |
|
|
42
|
+
| `runs` | Monitor and inspect execution runs |
|
|
43
|
+
| `quota` | Show backend quota and reset times |
|
|
44
|
+
| `models` | List registered model seats and capabilities |
|
|
45
|
+
|
|
46
|
+
`plan`, `review` and `image-gen` require `--out` and print only a verdict/path
|
|
47
|
+
line. `subagent` and `implement` have no `--out`; they print the delegate's
|
|
48
|
+
answer to stdout, and `subagent --out foo.md` exits 2 with
|
|
49
|
+
`No flag registered for --out`. Redirect if you want that answer in a file.
|
|
50
|
+
|
|
51
|
+
## Routing
|
|
52
|
+
|
|
53
|
+
1. **First word is a subcommand** → use the command-specific section appended
|
|
54
|
+
to this output. If it is missing, run `aibridge skill <subcommand>` before
|
|
55
|
+
taking action.
|
|
56
|
+
2. **No subcommand** → infer:
|
|
57
|
+
- an image, icon or graphic to make → `image-gen`;
|
|
58
|
+
- a self-contained task, cross-model second opinion, or red-team → `subagent`;
|
|
59
|
+
- sizeable or risky implementation work → `plan` → *you read, edit and
|
|
60
|
+
approve the plan file* → `implement` → `review --plan <file>`. For
|
|
61
|
+
high-risk designs only, add a gate before any code is written:
|
|
62
|
+
`review --plan` on a clean tree.
|
|
63
|
+
|
|
64
|
+
If genuinely ambiguous, show the table above and ask.
|
|
65
|
+
3. **Unsure of the current flags?** Run `aibridge <command> --help`.
|
|
66
|
+
|
|
67
|
+
## Model seats
|
|
68
|
+
|
|
69
|
+
`--model` is required on every command that spends a delegate (`plan`,
|
|
70
|
+
`implement`, `review`, `subagent`, `image-gen`); nothing is chosen for you.
|
|
71
|
+
`quota`, `models` and `runs` take no `--model`. Starting points, not
|
|
72
|
+
benchmarks:
|
|
73
|
+
|
|
74
|
+
| slug | plan | implement | review | image-gen |
|
|
75
|
+
|---|---|---|---|---|
|
|
76
|
+
| `xai-grok/grok-4.6` | ✅ small–mid, well-scoped | ○ | ✅ | ○ JPEG |
|
|
77
|
+
| `xai-grok/grok-4.5` | ○ | ✅ any fidelity | ○ | ○ JPEG |
|
|
78
|
+
| `openai-codex/gpt-5.6-sol` | ✅ mid–big, ambiguous | ○ | ✅ | ✅ PNG |
|
|
79
|
+
| `anthropic-claude/opus-5` | ✅ mid–big, ambiguous | ○ | ✅ | ✗ |
|
|
80
|
+
| `google-antigravity/gemini-3.7-flash` | ○ | ✅ needs high–xhigh detail | ○ | ○ JPEG |
|
|
81
|
+
| `anthropic-claude/sonnet-5` | ○ | ✅ needs high detail | ○ | ✗ |
|
|
82
|
+
|
|
83
|
+
✅ recommended · ○ supported · ✗ unsupported. For `plan`, the qualifier describes
|
|
84
|
+
how much ambiguity the model can resolve. For `implement`, it describes how
|
|
85
|
+
detailed the plan must be.
|
|
86
|
+
**If the task fits no row, or the user has said how they want work routed, ask
|
|
87
|
+
rather than guess.**
|
|
88
|
+
|
|
89
|
+
Also registered: `openai-codex/gpt-5.6-terra` / `-luna` (cheaper coding tiers),
|
|
90
|
+
`anthropic-claude/fable-5` (hardest, longest-running work),
|
|
91
|
+
`anthropic-claude/haiku-4-5` (quick answers),
|
|
92
|
+
`google-antigravity/gemini-3.6-flash`, `google-antigravity/gemini-3.1-pro`
|
|
93
|
+
(`-high`/`-low` only), and agy's `claude-sonnet-4-6` /
|
|
94
|
+
`claude-opus-4-6-thinking` / `gpt-oss-120b-medium`. Run `aibridge models
|
|
95
|
+
[--json]` for exact per-seat facts, or `aibridge <command> --help` for the list.
|
|
96
|
+
|
|
97
|
+
- **One grok stage at a time.** ~30 req/min, ~1k msgs/day, and both tiers share
|
|
98
|
+
that budget.
|
|
99
|
+
- **`grok-4.6` plans and reviews, `grok-4.5` implements.** They are different
|
|
100
|
+
seats, not old and new.
|
|
101
|
+
- **The reviewer must be a different model family from whoever implemented**,
|
|
102
|
+
including when that was you.
|
|
103
|
+
- **A backend that shares YOUR quota is a last resort**: `anthropic-claude/*`
|
|
104
|
+
for Claude-based agents, `google-antigravity/*` for Antigravity-based agents.
|
|
105
|
+
Say so when you reach for it.
|
|
106
|
+
- **Swap on quota**: `openai-codex/gpt-5.6-sol[-<effort>]` is the usual alternate.
|
|
107
|
+
- Preflight runs before every delegation. `aibridge quota` is the manual check
|
|
108
|
+
before you pipeline several stages.
|
|
109
|
+
|
|
110
|
+
## Trust
|
|
111
|
+
|
|
112
|
+
In tools mode, delegates can read files, write files, and run shell commands at
|
|
113
|
+
your trust level. The selected provider receives the prompt and any content the
|
|
114
|
+
delegate reads. Use `--no-tools` for untrusted input; it disables file and shell
|
|
115
|
+
access.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# image-gen — generate an image via a model seat
|
|
2
|
+
|
|
3
|
+
Part A covers the command. Part B covers prompt design, which applies even when
|
|
4
|
+
you only need to return a prompt.
|
|
5
|
+
|
|
6
|
+
## A. Calling it
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
aibridge image-gen --model <slug> --out <file.png> "<full prompt — see part B>" \
|
|
10
|
+
[--aspect-ratio 16:9] [--image ref.png] [--transparent] \
|
|
11
|
+
[--timeout 600] [--no-preflight] [--json]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| slug | renders via | format |
|
|
15
|
+
|---|---|---|
|
|
16
|
+
| `openai-codex/gpt-5.6-sol` (recommended) | Codex CLI | PNG |
|
|
17
|
+
| `google-antigravity/gemini-3.7-flash` | Antigravity CLI (`agy`) | JPEG |
|
|
18
|
+
| `xai-grok/grok-4.6` | `api.x.ai` directly, on `~/.grok/auth.json` | JPEG |
|
|
19
|
+
|
|
20
|
+
Other seats fail fast with a list of capable models. The grok seat renders
|
|
21
|
+
without `grok` on `PATH`; the CLI is spawned only to refresh the token, before a
|
|
22
|
+
request when `expires_at` is close and again as a backstop if one comes back
|
|
23
|
+
401. `grok login` is still what sets the seat up.
|
|
24
|
+
|
|
25
|
+
- `--out` is required and its extension must match the seat's format above
|
|
26
|
+
(`.png` for any `--transparent` run). A mismatch is rejected before anything
|
|
27
|
+
runs. The file holds the model's own bytes verbatim, except on a
|
|
28
|
+
chroma-keyed `--transparent` run, which writes the locally keyed PNG.
|
|
29
|
+
- **Render into the asset's real home** (`public/icons/settings.png`) when the
|
|
30
|
+
project keeps it. Drafts go to `.aibridge/`; see [SKILL.md](../SKILL.md).
|
|
31
|
+
- `--aspect-ratio N:M` sets geometry. Exact pixels are whatever the model
|
|
32
|
+
renders; resize downstream.
|
|
33
|
+
- `--image a.png,b.png` attaches references and routes to the seat's edit path.
|
|
34
|
+
- `--json` prints `{ out, bytes, width, height, aspectRatio, model, backend, transparency, real }`.
|
|
35
|
+
- Preflight is on by default: an exhausted seat exits 3 and names the
|
|
36
|
+
alternatives instead of spending a paid render. Argument checks run first, so
|
|
37
|
+
bad flags still cost no network call.
|
|
38
|
+
|
|
39
|
+
### Transparency
|
|
40
|
+
|
|
41
|
+
- `--transparent` works on every image seat and always writes PNG. Codex gives
|
|
42
|
+
native alpha; grok and gemini are chroma-keyed with binary edges. Fine for
|
|
43
|
+
flat icons, logos and stickers; not for hair, smoke or glass.
|
|
44
|
+
- **Say nothing about the background in the prompt when using it.** The CLI
|
|
45
|
+
writes the backdrop instruction per seat, and a colour of your own overrides
|
|
46
|
+
it: the key then finds nothing and the paid render comes back opaque. Writing
|
|
47
|
+
"transparent background" into the prompt without the flag is refused on
|
|
48
|
+
chroma seats.
|
|
49
|
+
- **A green subject is keyed away with the backdrop** on chroma seats. Anything
|
|
50
|
+
that must be green needs `openai-codex/*`.
|
|
51
|
+
- Both surfaces report the path taken: the result line says
|
|
52
|
+
`transparency: native` / `chroma-keyed`, `--json` carries
|
|
53
|
+
`"native" | "chroma" | null`. Quote it when the edges matter. Keying under 2%
|
|
54
|
+
of the image warns: the model likely ignored the backdrop instruction.
|
|
55
|
+
|
|
56
|
+
### Reference images
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
aibridge image-gen --model openai-codex/gpt-5.6-sol \
|
|
60
|
+
"the same woman, now in a denim shirt in a bright kitchen, waist-up" \
|
|
61
|
+
--out avatar2.png --image avatar.png --aspect-ratio 9:16
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
With a reference, write the prompt as a **diff**: say only what changes. The
|
|
65
|
+
reference carries identity, framing and style.
|
|
66
|
+
|
|
67
|
+
## B. Writing the prompt
|
|
68
|
+
|
|
69
|
+
1. **Never state the image's purpose** (no "app icon", "hero banner"). Describe
|
|
70
|
+
how it looks, not its job.
|
|
71
|
+
2. **Give the aspect ratio** via `--aspect-ratio` and/or the prompt text.
|
|
72
|
+
3. **Always specify the background**: a hex colour, or `opaque`/`auto`. Except
|
|
73
|
+
on a `--transparent` run, where you say nothing about it.
|
|
74
|
+
4. **Specify** subject, composition, palette, style/medium, mood, lighting.
|
|
75
|
+
5. **Lock the critical, free the rest.** Lock verbatim text in straight quotes,
|
|
76
|
+
brand hex, required layout, the hero subject, and every "no X". Over-specified
|
|
77
|
+
incidental detail flattens the result.
|
|
78
|
+
|
|
79
|
+
### Worked example
|
|
80
|
+
|
|
81
|
+
> `Square 1:1 aspect ratio. Solid warm cream #F7F1EA background. A single flat-design
|
|
82
|
+
> fanned stack of three rounded-corner cards in coral orange #FF5A1F, centered,
|
|
83
|
+
> ~55% of the frame, soft drop shadow. Calm, minimal, modern. No text, no border,
|
|
84
|
+
> no gradient.`
|
|
85
|
+
|
|
86
|
+
Locked: ratio, background hex, subject, brand orange, the no-text/border/gradient
|
|
87
|
+
constraints. Free: fan angle, shadow softness, spacing. On a `--transparent` run,
|
|
88
|
+
drop the background sentence and the drop shadow: a soft shadow has no flat
|
|
89
|
+
backdrop colour to key against and survives as a pale halo.
|
|
90
|
+
|
|
91
|
+
### Edits and retries
|
|
92
|
+
|
|
93
|
+
1. **Describe the desired result.** State what the finished image contains,
|
|
94
|
+
rather than only what to remove or correct.
|
|
95
|
+
2. **Name the visual criterion first.** Phrases such as "the near plane" or
|
|
96
|
+
"everyone waiting" often work better than an object inventory. Enumerate
|
|
97
|
+
objects only if the criterion fails.
|
|
98
|
+
3. **Rewrite failed prompts; do not append to them.** Simplify the request. For
|
|
99
|
+
a near-correct render, make the next instruction as short as possible.
|
|
100
|
+
4. **Change strategy after the same failure occurs twice.** Try a different
|
|
101
|
+
reference, composition, or fresh generation instead of another rewording.
|
|
102
|
+
5. **Retry from the original reference.** Chaining generated outputs causes
|
|
103
|
+
unrequested details to drift.
|
|
104
|
+
6. **Check your terminology.** A near-miss word can produce a coherent image of
|
|
105
|
+
the wrong concept.
|
|
106
|
+
7. **Verify unchanged details in context.** Inspect the asset in its final
|
|
107
|
+
placement and, when relevant, in motion.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# implement — execute a plan file
|
|
2
|
+
|
|
3
|
+
An implementer edits the working tree and runs the project's checks. This is the
|
|
4
|
+
third step in **`plan` → read and approve → `implement` → `review`**.
|
|
5
|
+
|
|
6
|
+
Run this only after reading and approving the plan. If the implementer would
|
|
7
|
+
need to make a product or architecture decision, fix the plan first.
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
aibridge implement --model <slug> <plan-file>
|
|
13
|
+
--model <slug> implementer model (required, e.g. google-antigravity/gemini-3.7-flash)
|
|
14
|
+
--timeout <secs> max seconds (default: 1800)
|
|
15
|
+
--no-preflight skip the quota preflight
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Behaviour
|
|
19
|
+
|
|
20
|
+
The delegate runs with full tools at the repository root. It must follow the
|
|
21
|
+
plan, edit only named files, run the specified checks until they pass, and avoid
|
|
22
|
+
commits, pushes, and unrelated deletions.
|
|
23
|
+
|
|
24
|
+
## Output
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
<delegate's short summary>
|
|
28
|
+
|
|
29
|
+
<git diff --stat>
|
|
30
|
+
untracked files: <count>
|
|
31
|
+
run: <run id>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Exit 0: completed with tree changes. Exit 1: delegate failed, timed out, gave no
|
|
35
|
+
usable answer, or changed nothing (a no-op implement is a failure). Exit 2: bad
|
|
36
|
+
args or missing plan file. Exit 3: quota preflight refusal.
|
|
37
|
+
|
|
38
|
+
## After it returns
|
|
39
|
+
|
|
40
|
+
1. **Re-run the checks yourself.** The summary reports the delegate's claim.
|
|
41
|
+
2. Then `aibridge review --model xai-grok/grok-4.6 --plan <plan-file> --out .aibridge/review.md`.
|
|
42
|
+
|
|
43
|
+
## Gotchas
|
|
44
|
+
|
|
45
|
+
- Keep the implementer a different model family from the reviewer. The
|
|
46
|
+
recommended seats (gemini implements, grok reviews) comply; if you override
|
|
47
|
+
one, check the other.
|
|
48
|
+
- agy quota is shared by model group. Two concurrent agy-heavy runs drain
|
|
49
|
+
the same window. Run `aibridge quota` before pipelining.
|
|
50
|
+
- The timeout covers the whole run including gate-fixing loops. Raise it for big
|
|
51
|
+
plans rather than letting a near-done run get killed.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# plan — write a detailed implementation plan file
|
|
2
|
+
|
|
3
|
+
A planner studies the codebase and writes a detailed plan to a file. This is the
|
|
4
|
+
first step in **`plan` → read and approve → `implement` → `review`**. Pass the
|
|
5
|
+
file path—not its contents—between stages.
|
|
6
|
+
|
|
7
|
+
Use it for sizeable or risky work. For small, fully-specified chunks use
|
|
8
|
+
`subagent`, or just do them.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
aibridge plan --model <slug> --out <file> "<task prompt>"
|
|
14
|
+
--model <slug> planner model (required, e.g. xai-grok/grok-4.6)
|
|
15
|
+
--out <file> where to write the plan (required)
|
|
16
|
+
--timeout <secs> max seconds (default: 1800)
|
|
17
|
+
--no-preflight skip the quota preflight
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The positional argument is the task prompt, not a file path.
|
|
21
|
+
|
|
22
|
+
## Writing the task prompt
|
|
23
|
+
|
|
24
|
+
The planner can read the code. Do not paste file contents. Provide only what it
|
|
25
|
+
cannot infer:
|
|
26
|
+
|
|
27
|
+
- the goal and the user-visible behaviour change;
|
|
28
|
+
- hard constraints (APIs to keep stable, zero-dep rules, style conventions);
|
|
29
|
+
- scope boundaries and non-goals;
|
|
30
|
+
- architectural calls you have already made, since the planner details your
|
|
31
|
+
design rather than overruling it;
|
|
32
|
+
- starting files, if the repo is large.
|
|
33
|
+
|
|
34
|
+
## Behaviour
|
|
35
|
+
|
|
36
|
+
- The planner writes exactly one file (`--out`). Any other change to the working
|
|
37
|
+
tree fails the run (exit 1, paths listed). An `--out` inside the repo is
|
|
38
|
+
exempt.
|
|
39
|
+
- The plan must end with `## Open questions` (`None.` when confident). The count
|
|
40
|
+
prints on stdout.
|
|
41
|
+
|
|
42
|
+
## Output
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
plan: /abs/path/to/plan.md
|
|
46
|
+
open questions: 2
|
|
47
|
+
run: <run id>
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Exit 0 even with open questions. Exit 1: plan missing, empty, no open-questions
|
|
51
|
+
section, tree dirtied, delegate failure or timeout. Exit 2: bad arguments.
|
|
52
|
+
Exit 3: quota preflight refusal.
|
|
53
|
+
|
|
54
|
+
## After it returns
|
|
55
|
+
|
|
56
|
+
1. **Read the plan file.** It is the implementation contract.
|
|
57
|
+
2. Resolve every open question: edit the file directly, or re-run `plan` with a
|
|
58
|
+
sharpened prompt.
|
|
59
|
+
3. High-risk design? Gate it first:
|
|
60
|
+
`aibridge review --model xai-grok/grok-4.6 --plan <file> --out .aibridge/review.md`
|
|
61
|
+
on a clean tree.
|
|
62
|
+
4. Then `aibridge implement --model google-antigravity/gemini-3.7-flash <file>`.
|
|
63
|
+
|
|
64
|
+
## Gotchas
|
|
65
|
+
|
|
66
|
+
- `--out` belongs in `.aibridge/` (see [SKILL.md](../SKILL.md)); check it is
|
|
67
|
+
gitignored once per session.
|
|
68
|
+
- grok is capped at ~30 req/min, ~1k msgs/day, one run at a time. Never run two
|
|
69
|
+
grok stages concurrently.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# review — cross-model review of a diff or a plan
|
|
2
|
+
|
|
3
|
+
A reviewer inspects a diff, optionally against a plan contract, and writes its
|
|
4
|
+
report to a file. Standard output contains only the verdict and paths.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
aibridge review --model <slug> --out <file> [options]
|
|
10
|
+
--model <slug> reviewer model (required, e.g. xai-grok/grok-4.6)
|
|
11
|
+
--plan <file> plan contract; over-reach against it is a finding
|
|
12
|
+
--base <ref> any git ref or range to diff against (default: HEAD)
|
|
13
|
+
--out <file> full report destination (required)
|
|
14
|
+
--timeout <secs> max seconds (default: 1200)
|
|
15
|
+
--no-preflight skip the quota preflight
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Picking the diff
|
|
19
|
+
|
|
20
|
+
`--base` is passed straight to `git diff`, so any ref or range git accepts
|
|
21
|
+
works: `HEAD~3`, a branch, a SHA, a tag, `v1.2.0..HEAD`.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# uncommitted work only (the default base, HEAD)
|
|
25
|
+
aibridge review --model xai-grok/grok-4.6 --out .aibridge/review.md
|
|
26
|
+
|
|
27
|
+
# the 3 commits you just made
|
|
28
|
+
aibridge review --model xai-grok/grok-4.6 --base HEAD~3 --out .aibridge/review.md
|
|
29
|
+
|
|
30
|
+
# the whole branch, against the plan contract
|
|
31
|
+
aibridge review --model xai-grok/grok-4.6 --base main \
|
|
32
|
+
--plan .aibridge/plan.md --out .aibridge/review.md
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Use `--base` to review committed work. Do not copy a diff into a file for
|
|
36
|
+
`subagent`. Uncommitted changes are included unless the range fixes both ends.
|
|
37
|
+
|
|
38
|
+
## Modes (detected before any model spend)
|
|
39
|
+
|
|
40
|
+
1. **Diff review:** changes or untracked files exist relative to `--base`. With
|
|
41
|
+
`--plan`, unrequested changes count as over-reach.
|
|
42
|
+
2. **Plan review:** nothing differs from `--base` and `--plan` is given.
|
|
43
|
+
Reviews the plan for soundness, edge cases, safety, feasibility. Use it as a
|
|
44
|
+
pre-implementation gate on high-risk designs.
|
|
45
|
+
3. **No input:** nothing differs and no `--plan` is given. Exits 2.
|
|
46
|
+
|
|
47
|
+
## Output & exit codes
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
PASS | FINDINGS: 1 critical, 0 major, 3 minor
|
|
51
|
+
review: /abs/path/to/review.md
|
|
52
|
+
run: <run id>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- `0`: PASS, or minor-only findings.
|
|
56
|
+
- `1`: critical or major findings; unparseable verdict (raw answer + paths still
|
|
57
|
+
print); missing or empty report file; delegate failure or timeout.
|
|
58
|
+
- `2`: bad flags, missing plan file, nothing to review, bad base ref.
|
|
59
|
+
- `3`: quota preflight refusal.
|
|
60
|
+
|
|
61
|
+
## After it returns
|
|
62
|
+
|
|
63
|
+
- `PASS` → proceed (commit, or report done).
|
|
64
|
+
- Findings → read the report, then judge. Over-reach findings can be scope you
|
|
65
|
+
added deliberately: the reviewer flags, you decide. Fix what is real, re-run.
|
|
66
|
+
- Never let a model review its own diff. The recommended seats (grok reviews,
|
|
67
|
+
gemini implements) already comply; if you override one, check the other.
|
|
68
|
+
|
|
69
|
+
## Gotchas
|
|
70
|
+
|
|
71
|
+
- The report file is required even for PASS. Missing or empty fails the run.
|
|
72
|
+
- Verdict parsing accepts the line first, last, or at the end of a narration
|
|
73
|
+
blob (grok concatenates progress prose). If it still fails, you get exit 1
|
|
74
|
+
with the raw answer plus the report path on stdout.
|
|
75
|
+
- A bad `--base` ref is a hard error (exit 2), not a silent dirty-tree fallback.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# subagent — delegate a task to another model
|
|
2
|
+
|
|
3
|
+
Delegate one self-contained task to another provider's model. Use this for a
|
|
4
|
+
second opinion, red-team review, long-context analysis, or a clearly specified
|
|
5
|
+
piece of work.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
aibridge subagent --model <slug> "<self-contained prompt>" [options]
|
|
11
|
+
--model <slug> required, canonical slug (no short aliases)
|
|
12
|
+
--timeout <secs> max seconds (default: 600)
|
|
13
|
+
--no-tools reasoning only: no file or shell access
|
|
14
|
+
--no-preflight skip the quota preflight
|
|
15
|
+
--json machine-readable, e.g. {"model": "grok-4.6", "slug": "xai-grok/grok-4.6", ...}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The answer prints to stdout. There is no `--out`; redirect if you want a file.
|
|
19
|
+
|
|
20
|
+
Effort suffixes work on seats that support them
|
|
21
|
+
(`xai-grok/grok-4.6-medium`, `google-antigravity/gemini-3.7-flash-low`,
|
|
22
|
+
`anthropic-claude/sonnet-5-max`). The seat table is in [SKILL.md](../SKILL.md);
|
|
23
|
+
`aibridge subagent --help` prints the live list.
|
|
24
|
+
|
|
25
|
+
**Tools are ON by default** — the delegate reads/writes files and runs shell.
|
|
26
|
+
|
|
27
|
+
## Writing the prompt
|
|
28
|
+
|
|
29
|
+
Write for a capable model with no conversation context:
|
|
30
|
+
|
|
31
|
+
1. **Self-contained.** Paste the code or spec to act on. Never reference "what
|
|
32
|
+
we discussed".
|
|
33
|
+
2. **Specify the approach.** Include design decisions, interfaces, files, and
|
|
34
|
+
constraints without prescribing every line of code.
|
|
35
|
+
3. **State the constraints.** Run the real typecheck and tests until green;
|
|
36
|
+
write code only, no commit/push/deploy/delete; reply with a short summary.
|
|
37
|
+
4. **Verify the result.** Re-run the real gates yourself.
|
|
38
|
+
|
|
39
|
+
## When to stay native instead
|
|
40
|
+
|
|
41
|
+
- The task needs session-specific tools, skills, or MCP servers.
|
|
42
|
+
- It needs conversational context or live user guidance.
|
|
43
|
+
- It needs strict schema validation or guaranteed retry orchestration.
|
|
44
|
+
|
|
45
|
+
## Scaling up
|
|
46
|
+
|
|
47
|
+
For large or multi-file work, use the three verbs instead of raw subagent calls:
|
|
48
|
+
[plan](plan.md) → you approve → [implement](implement.md) → [review](review.md).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# why — the reasoning behind the rules
|
|
2
|
+
|
|
3
|
+
This page explains rules that the command guides state without rationale. Read
|
|
4
|
+
it when a rule appears unsuitable for your case.
|
|
5
|
+
|
|
6
|
+
**Paths travel between stages, not contents.** A plan re-emitted into your
|
|
7
|
+
context costs you the tokens the split was meant to save. `plan` writes a file,
|
|
8
|
+
`implement` reads that path, `review` takes it as `--plan`. Nothing round-trips
|
|
9
|
+
through you except your judgment.
|
|
10
|
+
|
|
11
|
+
**You read the plan file.** That sign-off is the entire point of splitting plan
|
|
12
|
+
from implement. Skip it and you have an unreviewed contract that a second model
|
|
13
|
+
will now execute literally.
|
|
14
|
+
|
|
15
|
+
**The implementer is a pure do-er.** It executes a fully-designed plan and does
|
|
16
|
+
not hold the surrounding vision. When a plan turns out to need that vision, the
|
|
17
|
+
design work upstream was insufficient. Fix the plan rather than briefing the
|
|
18
|
+
implementer.
|
|
19
|
+
|
|
20
|
+
**Reviewers are cross-model on purpose.** A model reviewing its own diff shares
|
|
21
|
+
its own blind spots and will wave through the thing it just failed to see. This
|
|
22
|
+
applies to you too: prefer a reviewer outside your own model family for code you
|
|
23
|
+
wrote yourself.
|
|
24
|
+
|
|
25
|
+
**Over-reach is a finding.** A delegate that also refactors three neighbouring
|
|
26
|
+
files has left the contract, and the diff you now have to verify is bigger than
|
|
27
|
+
the one you asked for. The reviewer flags it; you decide whether it was scope
|
|
28
|
+
you wanted.
|
|
29
|
+
|
|
30
|
+
**Quota is relative to whoever runs the skill.** Every backend spends its own
|
|
31
|
+
CLI's login. A backend on the same provider as you (`anthropic-claude/*` for a
|
|
32
|
+
Claude-based agent) drains the pool you are already burning, so it buys no extra
|
|
33
|
+
capacity and no independent perspective. That is why it is a last resort rather
|
|
34
|
+
than merely a choice.
|
|
35
|
+
|
|
36
|
+
**Seats pin exact model versions.** A vendor alias like `opus` moves under you
|
|
37
|
+
when a release lands, silently changing what a documented pipeline does.
|
|
38
|
+
|
|
39
|
+
**Some commands write files, some print.** `plan`, `review` and `image-gen`
|
|
40
|
+
produce artifacts worth keeping and re-reading, so they take `--out` and keep
|
|
41
|
+
stdout to a verdict line. `subagent` returns an answer you consume immediately,
|
|
42
|
+
and `implement`'s output IS the working tree.
|
|
43
|
+
|
|
44
|
+
**The CLI catches fake successes, not bad work.** Backends fail in ways that
|
|
45
|
+
look like success: an agy model with no quota returns an empty answer and exit 0;
|
|
46
|
+
codex sometimes draws a tiny image in code instead of rendering one. So a
|
|
47
|
+
too-small render is rejected as fake, an empty answer is an error, and an
|
|
48
|
+
`implement` that changed nothing exits 1. A review with no report file fails as
|
|
49
|
+
well, because a verdict without evidence is not a review. None of that judges
|
|
50
|
+
the work itself, which is why you still re-run the real gates on a diff.
|
|
51
|
+
|
|
52
|
+
**Chroma keying is a fallback, not a feature.** Only codex renders true alpha.
|
|
53
|
+
On the JPEG seats aibridge asks for a flat backdrop and removes it locally,
|
|
54
|
+
which gives binary edges and eats any subject the same colour as the backdrop.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aibridge/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "Agent instructions and CLI for delegating work to authenticated AI CLIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"engines": {
|
|
@@ -31,16 +31,17 @@
|
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
|
+
"instructions",
|
|
34
35
|
"src"
|
|
35
36
|
],
|
|
36
37
|
"dependencies": {
|
|
37
38
|
"@stricli/core": "1.3.0",
|
|
38
39
|
"sharp": "^0.35.3",
|
|
40
|
+
"@aibridge/driver-agy": "0.9.0",
|
|
39
41
|
"@aibridge/proc": "0.9.0",
|
|
40
|
-
"@aibridge/driver-grok": "0.9.0",
|
|
41
42
|
"@aibridge/driver-codex": "0.9.0",
|
|
42
|
-
"@aibridge/driver-
|
|
43
|
-
"@aibridge/driver-
|
|
43
|
+
"@aibridge/driver-claude": "0.9.0",
|
|
44
|
+
"@aibridge/driver-grok": "0.9.0"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"tsdown": "0.22.14"
|
|
@@ -84,7 +84,16 @@ describe('stricli exit-code lock & routing', () => {
|
|
|
84
84
|
const ctx = fakeCtx();
|
|
85
85
|
await runCli(ctx, ['--help']);
|
|
86
86
|
const output = ctx._stdout.join('');
|
|
87
|
-
for (const cmd of [
|
|
87
|
+
for (const cmd of [
|
|
88
|
+
'plan',
|
|
89
|
+
'implement',
|
|
90
|
+
'review',
|
|
91
|
+
'subagent',
|
|
92
|
+
'image-gen',
|
|
93
|
+
'runs',
|
|
94
|
+
'quota',
|
|
95
|
+
'skill',
|
|
96
|
+
]) {
|
|
88
97
|
expect(output).toContain(cmd);
|
|
89
98
|
}
|
|
90
99
|
});
|
package/src/app.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createRequire } from 'node:module';
|
|
2
1
|
import { buildApplication, buildRouteMap, run } from '@stricli/core';
|
|
3
2
|
import { imageGen } from './commands/image-gen/command.ts';
|
|
4
3
|
import { implement } from './commands/implement/command.ts';
|
|
@@ -7,12 +6,11 @@ import { plan } from './commands/plan/command.ts';
|
|
|
7
6
|
import { quota } from './commands/quota/command.ts';
|
|
8
7
|
import { review } from './commands/review/command.ts';
|
|
9
8
|
import { runs } from './commands/runs/command.ts';
|
|
9
|
+
import { skill } from './commands/skill/command.ts';
|
|
10
10
|
import { subagent } from './commands/subagent/command.ts';
|
|
11
11
|
import type { LocalContext } from './context.ts';
|
|
12
12
|
import { normalizeExitCode } from './exitCode.ts';
|
|
13
|
-
|
|
14
|
-
const require = createRequire(import.meta.url);
|
|
15
|
-
const { version } = require('../package.json') as { version: string };
|
|
13
|
+
import { PACKAGE_VERSION } from './package.ts';
|
|
16
14
|
|
|
17
15
|
const BRIEF =
|
|
18
16
|
'Bridge tasks to the other AI CLIs on this machine — a plan → implement → review workflow, task delegation, and image generation (codex / agy / grok seats).';
|
|
@@ -27,6 +25,7 @@ const routes = buildRouteMap({
|
|
|
27
25
|
runs,
|
|
28
26
|
quota,
|
|
29
27
|
models,
|
|
28
|
+
skill,
|
|
30
29
|
},
|
|
31
30
|
docs: {
|
|
32
31
|
brief: BRIEF,
|
|
@@ -36,7 +35,7 @@ const routes = buildRouteMap({
|
|
|
36
35
|
export const app = buildApplication(routes, {
|
|
37
36
|
name: 'aibridge',
|
|
38
37
|
versionInfo: {
|
|
39
|
-
currentVersion:
|
|
38
|
+
currentVersion: PACKAGE_VERSION,
|
|
40
39
|
},
|
|
41
40
|
scanner: {
|
|
42
41
|
// Accept --no-preflight / --no-tools while flag keys stay camelCase in TS
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { buildCommand } from '@stricli/core';
|
|
2
|
+
import type { LocalContext } from '../../context.ts';
|
|
3
|
+
import skillImpl from './impl.ts';
|
|
4
|
+
|
|
5
|
+
function skillCommand(this: LocalContext, _flags: Record<never, never>, topic?: string): void {
|
|
6
|
+
skillImpl.call(this, topic);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const skill = buildCommand({
|
|
10
|
+
func: skillCommand,
|
|
11
|
+
parameters: {
|
|
12
|
+
flags: {},
|
|
13
|
+
positional: {
|
|
14
|
+
kind: 'tuple',
|
|
15
|
+
parameters: [
|
|
16
|
+
{
|
|
17
|
+
brief: 'Command-specific instructions to append to the router',
|
|
18
|
+
parse: String,
|
|
19
|
+
placeholder: 'topic',
|
|
20
|
+
optional: true,
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
docs: {
|
|
26
|
+
brief: 'Print the canonical agent instructions bundled with this CLI',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import type { LocalContext } from '../../context.ts';
|
|
3
|
+
import { PACKAGE_VERSION } from '../../package.ts';
|
|
4
|
+
import skillImpl from './impl.ts';
|
|
5
|
+
|
|
6
|
+
function fakeCtx(): LocalContext & { stdout: string[]; stderr: string[] } {
|
|
7
|
+
const stdout: string[] = [];
|
|
8
|
+
const stderr: string[] = [];
|
|
9
|
+
return {
|
|
10
|
+
process: {
|
|
11
|
+
stdout: {
|
|
12
|
+
write: (value: string) => {
|
|
13
|
+
stdout.push(value);
|
|
14
|
+
return true;
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
stderr: {
|
|
18
|
+
write: (value: string) => {
|
|
19
|
+
stderr.push(value);
|
|
20
|
+
return true;
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
exitCode: undefined,
|
|
24
|
+
} as unknown as NodeJS.Process,
|
|
25
|
+
stdout,
|
|
26
|
+
stderr,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('skill command', () => {
|
|
31
|
+
it('prints the router with an exact-version runner', () => {
|
|
32
|
+
const ctx = fakeCtx();
|
|
33
|
+
skillImpl.call(ctx);
|
|
34
|
+
const output = ctx.stdout.join('');
|
|
35
|
+
|
|
36
|
+
expect(output).toContain(`npx -y @aibridge/cli@${PACKAGE_VERSION}`);
|
|
37
|
+
expect(output).toContain('# aibridge');
|
|
38
|
+
expect(output).not.toContain('# plan —');
|
|
39
|
+
expect(ctx.process.exitCode).toBeUndefined();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('appends command-specific instructions', () => {
|
|
43
|
+
const ctx = fakeCtx();
|
|
44
|
+
skillImpl.call(ctx, 'plan');
|
|
45
|
+
const output = ctx.stdout.join('');
|
|
46
|
+
|
|
47
|
+
expect(output).toContain('# aibridge');
|
|
48
|
+
expect(output).toContain('# plan — write a detailed implementation plan file');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('rejects an unknown topic', () => {
|
|
52
|
+
const ctx = fakeCtx();
|
|
53
|
+
skillImpl.call(ctx, 'nope');
|
|
54
|
+
|
|
55
|
+
expect(ctx.process.exitCode).toBe(2);
|
|
56
|
+
expect(ctx.stderr.join('')).toContain('unknown topic "nope"');
|
|
57
|
+
expect(ctx.stdout).toEqual([]);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import type { LocalContext } from '../../context.ts';
|
|
3
|
+
import { PACKAGE_VERSION } from '../../package.ts';
|
|
4
|
+
|
|
5
|
+
const TOPICS = {
|
|
6
|
+
plan: 'reference/plan.md',
|
|
7
|
+
implement: 'reference/implement.md',
|
|
8
|
+
review: 'reference/review.md',
|
|
9
|
+
subagent: 'reference/subagent.md',
|
|
10
|
+
'image-gen': 'reference/image-gen.md',
|
|
11
|
+
why: 'reference/why.md',
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export type SkillTopic = keyof typeof TOPICS;
|
|
15
|
+
|
|
16
|
+
function instructionPath(relativePath: string): URL {
|
|
17
|
+
const candidates = [
|
|
18
|
+
// Built package: dist/cli.mjs -> instructions/
|
|
19
|
+
new URL(`../instructions/${relativePath}`, import.meta.url),
|
|
20
|
+
// Source tree: src/commands/skill/impl.ts -> instructions/
|
|
21
|
+
new URL(`../../../instructions/${relativePath}`, import.meta.url),
|
|
22
|
+
];
|
|
23
|
+
const found = candidates.find(candidate => existsSync(candidate));
|
|
24
|
+
if (!found) {
|
|
25
|
+
throw new Error(`bundled instruction file is missing: ${relativePath}`);
|
|
26
|
+
}
|
|
27
|
+
return found;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readInstruction(relativePath: string): string {
|
|
31
|
+
return readFileSync(instructionPath(relativePath), 'utf8').trimEnd();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default function skillImpl(this: LocalContext, topic?: string): void {
|
|
35
|
+
if (topic !== undefined && !(topic in TOPICS)) {
|
|
36
|
+
this.process.stderr.write(
|
|
37
|
+
`aibridge skill: unknown topic ${JSON.stringify(topic)}; expected one of: ${Object.keys(TOPICS).join(', ')}\n`,
|
|
38
|
+
);
|
|
39
|
+
this.process.exitCode = 2;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const runner = `npx -y @aibridge/cli@${PACKAGE_VERSION}`;
|
|
45
|
+
const sections = [
|
|
46
|
+
`Command runner for these instructions: \`${runner}\`\nUse that exact prefix for every aibridge command below; do not substitute a global binary.`,
|
|
47
|
+
readInstruction('SKILL.md'),
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
if (topic !== undefined) {
|
|
51
|
+
sections.push(readInstruction(TOPICS[topic as SkillTopic]));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.process.stdout.write(`${sections.join('\n\n---\n\n')}\n`);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57
|
+
this.process.stderr.write(`aibridge skill: ${message}\n`);
|
|
58
|
+
this.process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
}
|