Skip to content

Releases: juscribe/jus-dispatch

jus-dispatch v0.8.28

Choose a tag to compare

@caleon caleon released this 08 Oct 23:26
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.27

Choose a tag to compare

@caleon caleon released this 08 Oct 06:03
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.26

Choose a tag to compare

@caleon caleon released this 06 Oct 04:45
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.25

Choose a tag to compare

@caleon caleon released this 04 Oct 19:33
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.24

Choose a tag to compare

@caleon caleon released this 01 Oct 21:39
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.23

Choose a tag to compare

@caleon caleon released this 30 Sep 23:22
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.22

Choose a tag to compare

@caleon caleon released this 29 Sep 05:19
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.21

Choose a tag to compare

@caleon caleon released this 28 Sep 18:53
b30bc0c

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.20

Choose a tag to compare

@caleon caleon released this 25 Sep 21:20

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more

jus-dispatch v0.8.19

Choose a tag to compare

@caleon caleon released this 24 Sep 05:35
aad8f79

Installing jus-dispatch

jus-dispatch is the remote dispatch agent for Juscribe. It connects to the Juscribe server over a WebSocket, runs a coding-agent CLI against your project when a dispatch arrives, and reports the result back to the board.

Platform support: macOS and Linux, amd64 and arm64. Requires the CLI you dispatch to — Claude Code by default.

Install

brew install juscribe/tap/jus

That installs the jus CLI and jus-dispatch together, and brew upgrade jus moves both. Binaries for macOS and Linux, amd64 and arm64, are attached to every release at github.com/juscribe/jus-dispatch/releases and download without authentication.

A container image ships on the same cut, for the docker placement:

docker pull ghcr.io/juscribe/jus-dispatch:latest

linux/amd64 and linux/arm64. ⚠️ This page said there was no image, and that was true between #3912 and #4219. The station published one for a --sandbox docker mode that left with it; p188 restored the placement layer and the image came back with it.

To build from a checkout instead:

cd dispatch && make build

That writes dispatch/bin/jus-dispatch. make build-all cross-compiles all four platforms into the same directory, and make install copies the host build into $GOPATH/bin.

What it does NOT do

The station created a git worktree per dispatch, ran the CLI inside it, and then merged, pushed or left the branch. jus-dispatch leaves the branch and stops there (#4223).

  • It creates a worktree, runs the CLI in it, removes the worktree and keeps the branch. The board is told the branch name and how many commits are on it.
  • No merge, no push, no pull request, on any path. A person reviews and lands it. A run that committed nothing gets its branch deleted and the board says so rather than naming an empty one.
  • ⚠️ .jus/hooks/worktree-setup runs inside the new worktree first, if your project has one — a git checkout is missing everything you gitignore. A hook that fails or is not executable fails the dispatch rather than handing an agent a broken tree.
  • branch_strategy no longer arrives on the wire at all (#3902), and nothing here reads it. There is one behaviour, so there is nothing to select.

⚠️ The sandbox modes ARE back, and this section said they were gone until #4254. raw / orbstack / docker and the setup-sandbox, setup-orb, setup-docker and auth commands were restored across #4222, #4221, #4220, #4243 and #4245. jus-dispatch init is what chooses between them — the Setup section below records the choice; it does not make it, and this sentence said otherwise until #4292.

What a dispatch is allowed to do

It runs under --permission-mode auto — it can edit files (#4254).

⚠️ The placement is what makes that safe, and on raw there is nothing. Under orbstack and docker only the project directory is mounted, so a write outside it is refused by the kernel; raw is your real machine with an autonomous agent on it. jus-dispatch init prints that difference and takes a typed agree before it will select raw.

⚠️ The history matters if you are reading an older note. Between #3900 and #4254 a dispatch was read-only, enforced by the agent's own flags — first dontAsk, then plan after #3970 found that a project's own .claude/settings.json outranked the narrower mode in a trusted checkout. That approach is retired: the boundary is the container now, not the model's own restraint.

One rule still binds under auto, and it is the project's own. permissions.deny in .claude/settings.json is honoured and recorded. Measured on claude 2.1.273: asked for a deny-listed file, the CLI reached for it through cat — not the Read tool — and the rule stopped it anyway. --setting-sources is deliberately never passed, because it would discard exactly that.

⚠️ --dangerously-skip-permissions is never passed and must not be. An autonomous mode answers the permission system; that flag switches it off, and takes the deny rules with it.

⚠️ Project hooks still run — they are shell commands the harness executes, outside the permission system entirely.

Setup

jus-dispatch init

Press Enter to accept a default (shown in brackets):

Prompt Default What it means
API token (none — required) Your Juscribe API token, from Settings → API Tokens. It authenticates the agent with the server.
Server URL wss://app.juscribe.ai/cable The WebSocket endpoint for your Juscribe instance. Accept the default unless you have a designated subdomain.
Project path Current directory Absolute path to the git repository the agent runs in.
Sandbox (none — you are asked) Where the CLI runs: raw, orbstack or docker. raw is your real machine and requires a typed agree.
CLI provider claude Only shown when multi-LLM is enabled for your workspace.
Thinking effort medium low, medium, high or max. Claude only.
Log level info debug, info, warn or error. Use debug when troubleshooting a connection.
Log file ~/.local/share/jus-dispatch/logs/jus-dispatch.log Where the structured log is written, in addition to stderr.

Config is saved to ~/.config/jus-dispatch/config.toml, or to <project>/.jus/dispatch.toml when the directory has been through jus init.

⚠️ ~/.config/jus-station/ is not read, at any precedence. A frozen station and a new agent can sit on one machine, and sharing a config would have each writing over the other's scope. The station cannot connect either way — the server's protocol floor is past it — but the file is left alone rather than migrated. See Upgrading from jus-station.

Every value can be overridden at runtime by a flag (--token, --server, --project, --log-level, --log-file) or an environment variable (JUSCRIBE_API_TOKEN, JUS_SERVER_URL, JUS_PROJECT_PATH, JUS_LOG_LEVEL, JUS_LOG_FILE, JUS_EFFORT_LEVEL).

Your project's toolchain is yours to install

jus-dispatch init offers to file this as a chore on your board, with the commands below already filled in for your sandbox — you can decline, and nothing is written to your tracker unless you say yes.

A sandbox gets git, the AI CLI and the jus toolset, and nothing else. It does not get your language runtime, your package manager or your database client — jus-dispatch has no way to know what those are.

Put an executable .jus/hooks/sandbox-setup in your repository. Both setup-orb and setup-docker run it, with your project as the working directory:

#!/usr/bin/env bash
set -euo pipefail

sudo apt-get update
sudo apt-get install -y nodejs npm postgresql-client
  • No hook is not an error. Most projects need no provisioning and none is invented for them.
  • A hook that fails, or exists without an executable bit, fails setup — a sandbox missing the tools it was meant to install is one every dispatch dies in, somewhere that names neither the hook nor its permissions.
  • It is not bounded by a timeout. A toolchain install can legitimately run for half an hour; the output streams to your terminal and Ctrl-C works.
  • .jus/hooks/orb-setup still works. That was the name before the hook reached docker. Both are found, on both placements, and sandbox-setup wins if you have written both.

⚠️ This is not .jus/hooks/worktree-setup, and the two are not interchangeable. That one runs per dispatch, in a fresh worktree, and restores what you gitignore — typically starting with a dependency install. This one runs once per sandbox and installs the thing that dependency install invokes.

Placement What the hook becomes
orbstack A provisioning step inside the orb, run once by setup-orb after git, the CLI and the jus toolset are installed.
docker A build layer. setup-docker builds an image from ghcr.io/juscribe/jus-dispatch with your hook in it, tags it jus-dispatch-<project>-<hash>:latest and points [sandbox] target at that. Every container is `docker run -...
Read more