jjhub 0.2.0 → 0.3.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/dist/cli/jjhub.mjs +19252 -20228
- package/package.json +1 -1
- package/skills/jjhub-cli/SKILL.md +206 -21
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jjhub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "jjhub — GitHub CLI with Jujutsu-native superpowers: stable change IDs, stacks, platform-wide undo, and conflicts that wait, layered over plain GitHub repos by a JJHub server.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"jjhub": "./dist/cli/jjhub.mjs"
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jjhub-cli
|
|
3
|
-
description: Drive a running JJHub instance from the command line with the `jjhub` CLI — create and land changes, manage stacks and bookmarks, resolve conflicts, and undo/redo via the operation log. Use when scripting or automating repository operations against a JJHub server
|
|
3
|
+
description: Drive a running JJHub instance (a Jujutsu-native change/stack/operation overlay on GitHub) from the command line with the `jjhub` CLI, or as an agent over MCP, ACP, A2A, or WebMCP — create and land changes, manage stacks and bookmarks, resolve conflicts, coordinate local jj workspaces, and undo/redo via the operation log. Use when scripting or automating repository operations against a JJHub server, or wiring an agent client (Claude Code, Zed, a Claude/ChatGPT connector, an A2A peer) up to one.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
License: MIT (see the public mirror erisera-code/jjhub-skills, LICENSE).
|
|
7
|
+
|
|
8
|
+
# jjhub — the JJHub CLI and agent surfaces
|
|
7
9
|
|
|
8
10
|
`jjhub` is a GitHub CLI (`gh`)-like wrapper with Jujutsu-native superpowers. It is a thin
|
|
9
11
|
client over JJHub's HTTP API: every command reads or mutates state on a running JJHub
|
|
@@ -11,21 +13,47 @@ server, the same server backing the web UI. Repo context is inferred from the cu
|
|
|
11
13
|
directory's git `origin` remote (override with `--repo`), and any top-level command that
|
|
12
14
|
isn't one of `jjhub`'s own nouns is passed straight through to the real `gh` binary.
|
|
13
15
|
|
|
16
|
+
The CLI is one of five interchangeable surfaces over the same server state and the same
|
|
17
|
+
op log — pick whichever fits the client:
|
|
18
|
+
|
|
19
|
+
| Surface | What it is | Entry point |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| CLI | `jjhub`, a `gh`-alike | `npx jjhub@latest <command>`, or `jjhub` once installed |
|
|
22
|
+
| MCP | 133 structured tools | remote: `<server>/mcp` (OAuth 2.1, RFC 9728 auto-discovery); local: `npx jjhub@latest mcp serve` (stdio) or `--http <port>` |
|
|
23
|
+
| ACP | Agent Client Protocol v1, slash-command style | `npx jjhub@latest acp serve` (stdio) — Zed's agent panel and friends |
|
|
24
|
+
| A2A | Agent2Agent v1.0, one skill per registry command | agent card `<server>/.well-known/agent-card.json`; JSON-RPC `POST <server>/a2a`; REST `<server>/a2a/v1` |
|
|
25
|
+
| WebMCP | 133 tools, progressively loaded | in-browser only, from an open JJHub tab — no separate connection |
|
|
26
|
+
|
|
27
|
+
This file documents the CLI in depth (it is the most complete reference for every verb,
|
|
28
|
+
since ACP/A2A commands are the same verbs under the same names) and points at each other
|
|
29
|
+
surface's own guide for its protocol-specific mechanics. See "Install this skill" below
|
|
30
|
+
for how to wire any of these into an agent client.
|
|
31
|
+
|
|
14
32
|
## Setup
|
|
15
33
|
|
|
16
34
|
See the [top-level README](../../README.md) for full project setup (`npm install`,
|
|
17
35
|
tests, requirements). This section covers just the CLI.
|
|
18
36
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
0. **No install needed**: `npx jjhub@latest <command>` fetches and runs the CLI on demand.
|
|
38
|
+
`npm i -g jjhub` gives a standalone `jjhub` binary if you'd rather not re-fetch every
|
|
39
|
+
invocation.
|
|
40
|
+
1. **Start the JJHub server** (if not already running, and you're not pointing at a
|
|
41
|
+
deployment): `npm start` from the repo root. Defaults to `http://localhost:3000`; set
|
|
42
|
+
`PORT` to change it, `JJHUB_DB` to point at a different SQLite file.
|
|
22
43
|
2. **Point the CLI at it**: `export JJHUB_URL=http://localhost:3000` (this is the default,
|
|
23
|
-
so only needed if the server is elsewhere).
|
|
24
|
-
`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
44
|
+
so only needed if the server is elsewhere). Against a real deployment, sign in first —
|
|
45
|
+
`jjhub auth login --url https://<your-jjhub>` (GitHub device flow) saves a bearer token
|
|
46
|
+
to `~/.config/jjhub/config.json`, and every subsequent command picks it up with no env
|
|
47
|
+
vars needed. For a local dev server started with `JJHUB_API_KEY` set, instead
|
|
48
|
+
`export JJHUB_API_KEY=<the same key>` — every request otherwise gets `401 unauthorized`.
|
|
49
|
+
Precedence when both a token and a key are present: `JJHUB_TOKEN` (bearer, e.g. from
|
|
50
|
+
`auth login`) beats `JJHUB_API_KEY` (operator key, sent as `x-api-key`) beats the saved
|
|
51
|
+
config file. Exporting a login token as `JJHUB_API_KEY` does NOT work — the server
|
|
52
|
+
rejects it (401). `JJHUB_CONFIG_DIR` overrides `~/.config/jjhub` for the CLI and every
|
|
53
|
+
agent surface below, if you need an isolated config (a scratch credential, a test
|
|
54
|
+
harness, a second identity).
|
|
55
|
+
3. **Invoke commands**: `npx jjhub@latest <command> [args]` or `jjhub <command>` once
|
|
56
|
+
installed; from inside this repo in development, `npm run jjhub -- <command> [args]`.
|
|
29
57
|
4. **Initialize the overlay** for a repo before using any other command:
|
|
30
58
|
`jjhub repo init [owner/name]` (infers `owner/name` from the cwd's git origin if omitted).
|
|
31
59
|
|
|
@@ -44,6 +72,9 @@ two interchangeable clients over the same state, not separate systems.
|
|
|
44
72
|
```
|
|
45
73
|
repo init [owner/name] [--github-token pat]
|
|
46
74
|
create the JJHub overlay for this repo
|
|
75
|
+
repo create owner/name --public|--private [--description text] [--default-branch name]
|
|
76
|
+
create a NEW repo on GitHub (via the GitHub App) then
|
|
77
|
+
overlay it — --public/--private is required, no default
|
|
47
78
|
repo list list repositories you can access
|
|
48
79
|
(permissions come live from GitHub)
|
|
49
80
|
repo archive | unarchive retire/reactivate (archived = read-only, sync skipped)
|
|
@@ -63,6 +94,10 @@ change amend <changeId>
|
|
|
63
94
|
change squash <changeId>
|
|
64
95
|
change abandon <changeId>
|
|
65
96
|
change restack <changeId> rebase a needs-restack change onto its rewritten ancestor
|
|
97
|
+
change request-review <changeId> move a draft change into review and mark its PR ready for review
|
|
98
|
+
change return-to-draft <changeId> return an in-review change and its PR to draft
|
|
99
|
+
change context <changeId> compact orientation snapshot: status, diff stat, landability,
|
|
100
|
+
checks, conflicts, review health, and derived nextActions in one call
|
|
66
101
|
change commit <changeId> [<file...>] [-m msg] [--delete <path>]... [--expect-head <sha>]
|
|
67
102
|
commit working-tree files onto the change's branch;
|
|
68
103
|
--delete removes a path in the same commit (repeatable);
|
|
@@ -161,6 +196,15 @@ bookmark list
|
|
|
161
196
|
bookmark delete <name> [--force] --force required for the default (trunk) bookmark
|
|
162
197
|
bookmark set <name> <tracked|view> [--target CHG-x]
|
|
163
198
|
|
|
199
|
+
workspace list live local jj workspace agents reporting into this repo
|
|
200
|
+
(see "jjhub daemon"), with their last-seen topology observation
|
|
201
|
+
workspace status agents, which is primary, and any active lease holder
|
|
202
|
+
workspace primary <workspaceId> mark a workspace as this repository's primary
|
|
203
|
+
workspace route [<workspaceId>|clear] show/set/clear the suggested local-write target — a SUGGESTION
|
|
204
|
+
only, never applied implicitly
|
|
205
|
+
workspace connect [aliasOrPath] start a local daemon for a workspace (= "daemon start")
|
|
206
|
+
workspace disconnect [aliasOrPath] stop a local daemon for a workspace (= "daemon stop")
|
|
207
|
+
|
|
164
208
|
view save <name> <revsetExpression> save a named jj revset expression for later reuse (storage
|
|
165
209
|
only — evaluate it with "jjhub revset")
|
|
166
210
|
view list list saved views in this repo
|
|
@@ -173,9 +217,11 @@ op diff <fromOpId> <toOpId> structural diff between two operations' i
|
|
|
173
217
|
undo [--force] refused when the head op is a "land" (real merge can't be unwound); --force reverts local state anyway
|
|
174
218
|
redo
|
|
175
219
|
|
|
176
|
-
conflict list
|
|
220
|
+
conflict list ACTIONS column: the states each conflict can still take;
|
|
221
|
+
"historical" = its change already landed, nothing to resolve
|
|
177
222
|
conflict resolve <conflictId> <state>
|
|
178
223
|
state: unresolved | left | right | edited | preserve_unresolved
|
|
224
|
+
("superseded" is set by JJHub itself when the change lands; it cannot be chosen)
|
|
179
225
|
|
|
180
226
|
sync push overlay state to GitHub
|
|
181
227
|
|
|
@@ -200,13 +246,19 @@ ai models --provider <p> [--api-key <key>] [--base-url <url>]
|
|
|
200
246
|
ai status where AI is coming from for you: your own saved connection,
|
|
201
247
|
the server operator's default, or not configured at all
|
|
202
248
|
|
|
203
|
-
mcp serve MCP server over stdio (
|
|
249
|
+
mcp serve MCP server over stdio (133 tools) for agent clients
|
|
204
250
|
mcp serve --http <port> the same tools over Streamable HTTP (POST /)
|
|
205
|
-
acp serve Agent Client Protocol agent over stdio (Zed's agent
|
|
206
|
-
panel, ...) —
|
|
251
|
+
acp serve Agent Client Protocol v1 agent over stdio (Zed's agent
|
|
252
|
+
panel, ...) — modes (read-only/ask/auto), a working-
|
|
253
|
+
repository + dry-run config option, persistent sessions,
|
|
254
|
+
plans and diffs — every operation as a slash command
|
|
207
255
|
agents-md print an AGENTS.md section teaching coding agents to
|
|
208
256
|
prefer jjhub over raw git/gh (jjhub agents-md >> AGENTS.md)
|
|
209
257
|
|
|
258
|
+
telemetry flows [--since <ISO8601>] [--surface webmcp|cli|browser|mcp|acp|a2a|api] [--limit N]
|
|
259
|
+
ongoing telemetry for the read -> patch -> verify -> land -> disconnect -> recover flow
|
|
260
|
+
across every client surface — per-step p50/p95 duration and error rate
|
|
261
|
+
|
|
210
262
|
daemon <localRepoPath> [--once] [--interval 5] [--engine auto|subprocess|isomorphic] [--two-way]
|
|
211
263
|
sync a local jj working copy into JJHub (inbound; --two-way mirrors JJHub edits back)
|
|
212
264
|
daemon start [alias|localRepoPath] [--interval 5] [--engine ...] [--two-way]
|
|
@@ -249,10 +301,65 @@ content receipts [--repo owner/name|repoId]
|
|
|
249
301
|
Anything else (`pr`, `issue`, ...) is passed through to `gh` — e.g. `jjhub pr view 7`. `jjhub auth`
|
|
250
302
|
is jjhub's own command (it manages the *JJHub server* connection); use `gh auth` for GitHub auth.
|
|
251
303
|
|
|
304
|
+
### The other agent surfaces: ACP and A2A
|
|
305
|
+
|
|
306
|
+
`jjhub acp serve` and the server's A2A endpoint are not CLI subcommands (A2A has no CLI
|
|
307
|
+
entry point at all — it's always part of the running server), but they run the exact same
|
|
308
|
+
verbs as the table above, through a shared command registry
|
|
309
|
+
(`src/agents/commands.ts`, 139 commands: every operation, the hand-written extras `whoami`,
|
|
310
|
+
`land_change`, `land_stack`, `get_land_job`, `delete_bookmark`, `sync_github`,
|
|
311
|
+
`raise_conflict`, plus registry-only composites `stack_status`, `get_conflict`,
|
|
312
|
+
`get_landability`, `land_when_ready`, `watch_change`, `watch_stack`, `get_skill`, `ask`) — so
|
|
313
|
+
anything documented above as a CLI command is also an ACP slash command and an A2A skill
|
|
314
|
+
under the same snake_case name.
|
|
315
|
+
|
|
316
|
+
**`ask` / `ask_jjhub` (issue #586)** — free text mapped onto ONE command from this same
|
|
317
|
+
registry (deterministic `/command args` parse first, else the caller's own AI connection,
|
|
318
|
+
resolved SERVER-SIDE via `POST /ai/interpret-command` so the process calling it needs no local
|
|
319
|
+
AI env of its own): `jjhub ask "<free text>"`, the A2A skill `ask`, and the MCP tool
|
|
320
|
+
`ask_jjhub` all wrap the exact same interpretation. Prefer it when a caller (an editor agent
|
|
321
|
+
speaking MCP, in particular) only has free text to work with and can't first call
|
|
322
|
+
`list_repositories`/`list_changes`/etc. itself to build a structured call — e.g. an end user
|
|
323
|
+
typed "land CHG-3 in the payments repo" into a chat and the agent should map that onto
|
|
324
|
+
`land_change` without hand-rolling its own NL parsing. Prefer the DIRECT command/tool instead
|
|
325
|
+
whenever the caller already knows exactly which verb and arguments it wants — `ask` adds an
|
|
326
|
+
extra round trip (interpret, then execute) and, for a command needing confirmation (e.g.
|
|
327
|
+
force-land), never bypasses it: it returns the resolved invocation unexecuted and says to call
|
|
328
|
+
the command directly, EXCEPT `ask_jjhub` itself over MCP, which carries the identical
|
|
329
|
+
SEP-2322/elicitation confirmation seam `land_change`/`land_stack`/`delete_bookmark` use, so a
|
|
330
|
+
force-land asked for in free text still asks before it runs. Without an AI provider configured
|
|
331
|
+
for the caller, only a direct `/command args` prompt resolves; the response says so
|
|
332
|
+
(`interpreted: false`, a `reason`) rather than failing.
|
|
333
|
+
|
|
334
|
+
- **ACP** (`jjhub acp serve`, stdio, Agent Client Protocol v1): sessions have modes
|
|
335
|
+
(`read-only` refuses mutations; `ask`, the default, confirms force-land/trunk-deletion/
|
|
336
|
+
force-undo through `session/request_permission` or `elicitation/create`; `auto`
|
|
337
|
+
auto-approves everything else), a `repository` config option so `/get_change CHG-3` works
|
|
338
|
+
without repeating the repository id, a `dry_run` config option, and persistent sessions
|
|
339
|
+
(`session/load`/`list`/`resume`/`close`/`delete`, stored in
|
|
340
|
+
`~/.config/jjhub/acp-sessions.json` — `JJHUB_ACP_SESSIONS_PATH` overrides the file,
|
|
341
|
+
`JJHUB_CONFIG_DIR` moves the whole config dir). A dev server with no `JJHUB_API_KEY` needs
|
|
342
|
+
`JJHUB_ACP_ALLOW_ANONYMOUS=1` on the agent process. Full Zed setup and everything the
|
|
343
|
+
session exposes: [`docs/guides/COMMON-TASKS.md`](../../docs/guides/COMMON-TASKS.md#drive-jjhub-from-an-editor-agent-panel-acp-eg-zed).
|
|
344
|
+
- **A2A** (spec v1.0 only — the v0.3 compatibility layer was removed; no v0.3 clients):
|
|
345
|
+
agent card at `/.well-known/agent-card.json` (optionally signed via
|
|
346
|
+
`JJHUB_A2A_CARD_SIGNING_JWK`, verifiable against `/.well-known/a2a-jwks.json`), JSON-RPC at
|
|
347
|
+
`POST /a2a`, REST at `/a2a/v1` — one task store shared by both bindings, so a task started
|
|
348
|
+
on one can be fetched/listed/cancelled on the other. Call a command as a text part
|
|
349
|
+
(`/list_changes <repositoryId> status=in_review`) or a data part
|
|
350
|
+
(`{"command": "commit_files", "args": {...}}`); confirmable mutations pause the task in
|
|
351
|
+
`input-required` (a `confirm` message resumes it), plans stream as `working` updates, and
|
|
352
|
+
`CancelTask` can interrupt an in-flight skill at its next safe checkpoint. Full detail and
|
|
353
|
+
the `npm run a2a:exercise` / `npm run acp:exercise` client harnesses (including the shared
|
|
354
|
+
`--mutate --stress N --land` scratch-repository stress scenario):
|
|
355
|
+
[`docs/guides/COMMON-TASKS.md`](../../docs/guides/COMMON-TASKS.md#drive-jjhub-agent-to-agent-a2a).
|
|
356
|
+
|
|
252
357
|
### Server connection: flags, env vars, or a config file
|
|
253
358
|
|
|
254
|
-
Precedence is `--
|
|
255
|
-
(
|
|
359
|
+
Precedence is `--url` > `JJHUB_URL` > `~/.config/jjhub/config.json` for the server, and
|
|
360
|
+
`JJHUB_TOKEN` (bearer token from `jjhub auth login`) > `JJHUB_API_KEY` (operator key, sent as
|
|
361
|
+
`x-api-key`) > the saved config (token, then apiKey) for the credential; the config file is
|
|
362
|
+
written by `jjhub auth login`. Run `jjhub auth login --url http://localhost:3000 --api-key <key>`
|
|
256
363
|
once and every subsequent command in that shell (any shell, any day) picks it up with no env
|
|
257
364
|
vars needed. `jjhub auth status` confirms what's currently in effect.
|
|
258
365
|
|
|
@@ -284,7 +391,14 @@ admin verification (optional mode)" section.
|
|
|
284
391
|
For exact, always-current syntax straight from the CLI binary, run `jjhub help` — this file is
|
|
285
392
|
an expanded, example-rich companion to that output, not a replacement for it.
|
|
286
393
|
|
|
287
|
-
|
|
394
|
+
## Install this skill
|
|
395
|
+
|
|
396
|
+
Three independent ways to pick this skill up — use whichever fits the agent you're
|
|
397
|
+
configuring. `GET /.well-known/skills/` on any running JJHub server (including the live
|
|
398
|
+
instance) returns all three as an `installation` object, e.g.
|
|
399
|
+
`curl https://jjhub.erisera.com/.well-known/skills/ | jq .installation`.
|
|
400
|
+
|
|
401
|
+
### (a) Teach a repo's coding agents to prefer jjhub (AGENTS.md)
|
|
288
402
|
|
|
289
403
|
[`agents-snippet.md`](./agents-snippet.md) is a short, imperative AGENTS.md
|
|
290
404
|
section — "version control in this repo goes through JJHub; prefer `jjhub
|
|
@@ -294,11 +408,82 @@ AGENTS.md so any AGENTS.md-aware coding agent (Claude Code, Copilot, Cursor,
|
|
|
294
408
|
Codex, ...) picks up the workflow automatically:
|
|
295
409
|
|
|
296
410
|
```bash
|
|
297
|
-
jjhub agents-md >> AGENTS.md
|
|
298
|
-
|
|
299
|
-
|
|
411
|
+
npx jjhub@latest agents-md >> AGENTS.md
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### (b) Fetch this skill directly (`skills.sh`, or a plain curl/`.well-known` fetch)
|
|
415
|
+
|
|
416
|
+
The skill content itself (this file plus `agents-snippet.md`) is mirrored, read-only, to the
|
|
417
|
+
public repo [`erisera-code/jjhub-skills`](https://github.com/erisera-code/jjhub-skills) on
|
|
418
|
+
every change (`.github/workflows/publish-skills.yml`, built by
|
|
419
|
+
`scripts/build-skills-dist.ts` — `npm run build:skills` reproduces it locally). Install from
|
|
420
|
+
there with the [skills.sh](https://skills.sh) installer:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
npx skills add erisera-code/jjhub-skills
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
Or mirror it by hand into a local `skills/` directory — the same shape either the live
|
|
427
|
+
server's `GET /.well-known/skills/` or the mirror's own `index.json` returns:
|
|
428
|
+
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"skills": [
|
|
432
|
+
{ "name": "jjhub-cli", "url": "/.well-known/skills/jjhub-cli/SKILL.md", "agentsSnippet": "/.well-known/skills/jjhub-cli/agents-snippet.md" }
|
|
433
|
+
],
|
|
434
|
+
"installation": {
|
|
435
|
+
"skillsCli": "npx skills add erisera-code/jjhub-skills",
|
|
436
|
+
"claudeCodeMarketplace": "/plugin marketplace add erisera-code/jjhub-skills",
|
|
437
|
+
"agentsMd": "npx jjhub@latest agents-md >> AGENTS.md",
|
|
438
|
+
"wellKnown": "https://jjhub.erisera.com/.well-known/skills/",
|
|
439
|
+
"repository": "https://github.com/erisera-code/jjhub-skills"
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
mkdir -p skills/jjhub-cli
|
|
446
|
+
curl -s https://jjhub.erisera.com/.well-known/skills/jjhub-cli/SKILL.md -o skills/jjhub-cli/SKILL.md
|
|
447
|
+
curl -s https://jjhub.erisera.com/.well-known/skills/jjhub-cli/agents-snippet.md -o skills/jjhub-cli/agents-snippet.md
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
`erisera-code/jjhub-skills` also carries a `.claude-plugin/marketplace.json`, so Claude Code
|
|
451
|
+
can add it directly as a plugin marketplace:
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
/plugin marketplace add erisera-code/jjhub-skills
|
|
455
|
+
/plugin install jjhub-cli@jjhub-skills
|
|
300
456
|
```
|
|
301
457
|
|
|
458
|
+
### (c) Wire up an MCP/ACP client, or an A2A peer
|
|
459
|
+
|
|
460
|
+
- **Claude Code** (MCP): `claude mcp add jjhub --http https://jjhub.erisera.com/mcp`
|
|
461
|
+
against a deployment (OAuth 2.1 discovered automatically via RFC 9728 — the CLI walks you
|
|
462
|
+
through sign-in), or point at a local stdio server:
|
|
463
|
+
```json
|
|
464
|
+
{ "mcpServers": { "jjhub": { "command": "npx", "args": ["jjhub@latest", "mcp", "serve"] } } }
|
|
465
|
+
```
|
|
466
|
+
- **Zed** (ACP), `~/.config/zed/settings.json`:
|
|
467
|
+
```json
|
|
468
|
+
{
|
|
469
|
+
"agent_servers": {
|
|
470
|
+
"jjhub": {
|
|
471
|
+
"command": "npx",
|
|
472
|
+
"args": ["jjhub@latest", "acp", "serve"],
|
|
473
|
+
"env": { "JJHUB_URL": "https://jjhub.erisera.com", "JJHUB_TOKEN": "<token from jjhub auth login>" }
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
```
|
|
478
|
+
(Running `jjhub auth login` on the same machine first means the `env` block can be
|
|
479
|
+
omitted entirely — the agent picks up the saved credential from `~/.config/jjhub`.)
|
|
480
|
+
- **A Claude.ai or ChatGPT connector** (remote MCP): add a custom connector pointing at
|
|
481
|
+
`https://<your-jjhub>/mcp` — both discover the OAuth 2.1 flow automatically (RFC 9728
|
|
482
|
+
protected-resource metadata); no manual token entry.
|
|
483
|
+
- **An A2A peer**: fetch `https://<your-jjhub>/.well-known/agent-card.json` for the skill
|
|
484
|
+
list and the two binding URLs (JSON-RPC `/a2a`, REST `/a2a/v1`); see "The other agent
|
|
485
|
+
surfaces: ACP and A2A" above for the auth model and confirmation flow.
|
|
486
|
+
|
|
302
487
|
## Example workflows
|
|
303
488
|
|
|
304
489
|
### Create and land a change
|