Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
"name": "bro-code",
"description": "droniu's Claude Code toolkit — the bro persona for your pair programmer, plus a multi-model council, end-to-end ship workflow, and CodeRabbit triage",
"description": "droniu's Claude Code toolkit — the bro persona for your pair programmer, plus a multi-model council, single-model consults, end-to-end ship workflow, and CodeRabbit triage",
"owner": {
"name": "Droniu",
"email": "droniu@droniu.dev"
Expand All @@ -12,6 +12,11 @@
"description": "Multi-model council: fan a question or diff out to Codex, Grok, and a sandboxed Claude seat, run an anonymized rebuttal round, synthesize with disagreements surfaced",
"source": "./plugins/council"
},
{
"name": "consult",
"description": "Consult one other model — Codex, Grok, or a Claude model — on the issue at hand, with the same access as the current session",
"source": "./plugins/consult"
},
{
"name": "ship",
"description": "Ship current work end-to-end: branch off the correct base, run the project's verify gate, commit per repo conventions, push, open a PR",
Expand Down
34 changes: 28 additions & 6 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,36 @@ jobs:
- name: Validate marketplace and plugin manifests
run: |
claude plugin validate .claude-plugin/marketplace.json --strict
for p in council ship coderabbit-triage bro-mode; do
claude plugin validate "plugins/$p" --strict
done

- name: Portability scan — no machine-specific facts in published plugins
# Validation targets come from the marketplace itself: a plugin can
# never be registered and then silently left unvalidated. Marketplace
# --strict passes over a missing source dir and never opens skills,
# so each plugin directory is validated on its own.
jq -r '.plugins[].source' .claude-plugin/marketplace.json \
| sed 's#^\./##;s#/$##' | sort > /tmp/listed.txt
while read -r src; do
if [ ! -d "$src" ]; then
echo "marketplace.json lists '$src' but that directory does not exist" >&2
exit 1
fi
claude plugin validate "$src" --strict
done < /tmp/listed.txt

# ...and the reverse: a plugin directory nobody registered.
ls -d plugins/*/ | sed 's#/$##' | sort > /tmp/present.txt
if ! diff -u /tmp/listed.txt /tmp/present.txt; then
echo "plugins/ and marketplace.json disagree (-marketplace +on disk)" >&2
exit 1
fi

- name: Portability scan — no machine-specific facts anywhere in the repo
run: |
if grep -rEn '/Users/|/home/[a-z]|[A-Za-z]:\\\\Users|linear\.app/[a-z]|atlassian\.net' plugins/; then
echo "Machine- or workspace-specific facts found in published plugin content" >&2
# Scans the whole repo, not just plugins/: README, CHANGELOG and docs
# leak machine paths just as easily. This workflow is excluded because
# it necessarily contains the patterns it searches for.
if grep -rEn '/Users/|/home/[a-z]|[A-Za-z]:\\Users|/private/tmp|claude-501|linear\.app/[a-z]|atlassian\.net' \
--exclude-dir=.git --exclude=validate.yml .; then
echo "Machine- or workspace-specific facts found in repo content" >&2
exit 1
fi

Expand Down
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,50 @@ conventions. Versions are per-plugin semver from each plugin's `plugin.json`.

## council

### 0.2.0 — 2026-09-12

#### Added

- Per-seat preflight: a one-turn smoke call decides the roster, so a broken
codex install or an exhausted grok quota is caught before three seats get
announced and two get retracted mid-run.
- Nickname resolution for seat selection ("just fable and astra"), with an
alias table mapping nicknames to provider and model.
- Seat budgets: turn caps, a codex wall-clock timeout, and a watchdog on the
Claude seat, so one runaway seat cannot swallow a run.
- Wall-clock expectations up front, plus a spend line drawn from the provider
envelopes.
- An evidence gate: a seat whose answer carries no `file:line` citation is
reported degraded instead of counted as a position.
- A pointer to `consult` for the single-model case.

#### Fixed

- Codex seats no longer use `codex exec review`, which rejects `-C`, refuses
`--base` alongside a prompt, and ignores `--output-schema` (it returns
prose). The diff target moved into the brief.
- `find-schema.json` now lists every property in `required`, as OpenAI strict
structured output demands; the old schema was rejected outright.
- Grok failures are diagnosed as quota (`429`, `free-usage-exhausted`,
`reauthable: false`) instead of advising a pointless `grok login`, and grok
is always invoked by name so a shell wrapper's API key and `GROK_HOME`
still apply.
- Dropped `--permission-mode plan` from the Grok seat: the flag only applies
`default` and `bypassPermissions`, so `plan` was accepted and silently
ignored. `--sandbox read-only` was and remains the actual enforcement.
- Corrected the Grok model and effort claims: `grok models` lists the catalog
and `-m` pins a seat model (new `--grok-model` flag), and
`--reasoning-effort` is silently ignored when the model's catalog entry says
`supports_reasoning_effort: false`, so the roster now reports "effort: n/a"
instead of a level that was never applied.
- Grok auth detection no longer probes a hardcoded `~/.grok/auth.json`, which
missed wrapper setups that relocate `GROK_HOME`.
- The Claude seat's brief is passed as literal text and asserted non-empty,
since workflow args can arrive stringified or empty; seats also write results
to disk so notification truncation is off the critical path.
- Documented that a headless Grok seat ends its whole run
(`stopReason: "Cancelled"`) at the first command needing approval.

### 0.1.0 — 2026-07-19

#### Added
Expand All @@ -15,6 +59,18 @@ conventions. Versions are per-plugin semver from each plugin's `plugin.json`.
seat separation, capability discovery, full repo read access for every
seat (enforced read-only), degraded-roster reporting.

## consult

### 0.1.0 — 2026-09-10

#### Added

- Initial release: one-on-one consultation with a single named model —
Codex, Grok, or a Claude subagent. The consultant's access mirrors the
parent session's permission mode, it gets a self-contained brief, changes
it makes to the working tree are reported, and follow-ups resume the same
consultant session.

## ship

### 0.1.0 — 2026-07-19
Expand Down
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Claude Code plugins by [Droniu](https://github.com/Droniu). The headliner is
**bro-mode** — an output style that makes your AI pair programmer talk like
your best bro. Three workflow plugins ride along, built and dogfooded daily.
your best bro. Four workflow plugins ride along, built and dogfooded daily.

> **Alpha honesty:** everything here is `0.x`. Interfaces, flags, and skill
> names may change between minor versions. Pin nothing to muscle memory yet.
Expand Down Expand Up @@ -104,6 +104,9 @@ What the side-by-side "ask three models" tools don't do, this does:
- **Refutation by default** — in review mode, findings go to a *different*
model instructed to refute them, with `refuted: true` as the default,
because AI review's dominant failure mode is confident false positives.
- **Preflighted seats** — every provider gets a one-turn smoke call before the
roster is announced, so a broken CLI or an exhausted quota is caught up
front instead of halfway through a long run.
- **Honest degradation** — no provider CLIs installed? It says "degraded
council, single model family" instead of pretending.

Expand All @@ -119,6 +122,31 @@ accounts. Every council seat has full read access to your repository and
sends what it reads to its provider — read the skill's data-exposure section
before pointing it at anything sensitive.

### consult — one model, your session's access

When you want one specific model's take instead of a whole council:

```text
/plugin install consult@bro-code
/consult gpt-6 astra (codex) on this issue
/consult grok on why the build broke — let it try fixing it
/consult sonnet on whether SSE or websockets fits here
```

The consultant — Codex, Grok, or a Claude subagent — gets a self-contained
brief (it never saw your conversation) and the **same access as your
session**: same repo, its own full config and MCP servers, network, and your
current permission mode mapped onto its CLI. Plan mode stays read-only, auto
mode auto-approves inside a workspace sandbox, bypass stays bypass. Where your
session would ask you first, a headless consultant is denied rather than
silently upgraded.

Unlike council's read-only seats, a consultant in a write-capable mode *can*
change files; its brief says not to unless you asked ("let it try fixing
it"), and anything it changes in the working tree is reported back.
Follow-ups resume the same consultant session. Same data-exposure rule as
council: Codex and Grok send what they read to their providers.

### ship

End-to-end "take my working state to an open PR": classifies your branch
Expand Down
11 changes: 11 additions & 0 deletions plugins/consult/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "consult",
"version": "0.1.0",
"description": "Consult one other model — Codex, Grok, or a Claude model — on the issue at hand, with the same access as the current session",
"author": {
"name": "Droniu",
"email": "droniu@droniu.dev"
},
"license": "MIT",
"homepage": "https://github.com/Droniu/bro-code"
}
Loading
Loading