# priiisk

[Русская версия](./README.ru.md)

A camp of long-lived worker agents. An orchestrator hires them, assigns work,
and keeps control; a human watches through the cabin and steps in only when
needed.

A worker is a live session, not a one-shot process: it keeps a role, a model, a
thinking level, a tool set, and a transcript that survives a restart.

**Under active development.** Commands, configuration and stored state change
between releases, sometimes without a transition path: a camp started by an
older build may refuse to resume, and a config that worked yesterday may be
rejected as a whole. Expect breakage and read the release you install.

## Install

```sh
npm install -g priiisk
priiisk --version
```

No separate runtime: the camp lives inside the executable. linux and macOS, x64
and arm64.

## After install

`priiisk` with no arguments — the same as `priiisk status` — is the camp
state: whether a camp is up, the roster, pending questions and elevation
requests. `priiisk survey` is the command map and the usual order of work.
When nothing is running, start with `camp up`.

Commands that report state accept `--json`. The camp is polled by request, not
by reading a screen. `priiisk --help` lists the rest; `priiisk <command> --help`
lists the arguments of one command.

## Quick start

`camp up` starts the camp as a detached process and, when the terminal it was
typed in can draw, opens the cabin there. The camp keeps running when the cabin
closes; `camp open` brings it back. Hire needs at least one model alias in the
config; see [Configuration](#configuration).

```sh
priiisk camp up
priiisk hire "Look into the failing tests" --role prospector
priiisk status prospector-quiet-harbor
priiisk asks
priiisk answer prospector-quiet-harbor
priiisk camp down
```

Hire generates an alias (`<role>-<adjective>-<noun>`) unless you pass `--alias`.
Use the name hire printed — `prospector-quiet-harbor` above is only an example.
The first assignment is optional: omit it and the worker waits in `idle` for
`priiisk send`.

One project root is one camp, one socket, and one orchestrator.

## Access modes

Access mode is a set of operation classes the worker may receive. It is chosen
at hire and does not change on a live worker. `equip` may narrow what is
handed out, but it cannot raise this ceiling.

| mode | classes | in practice |
| --- | --- | --- |
| `read-only` | read | files, search, read-only catalog binaries; no shell |
| `execute` | read, execute | plus a shell for checks; `edit` and `write` are not handed out |
| `read-write` | read, write | file edits through tools; no shell |
| `all` | all three | the full set |

The tool itself declares its class. Built-in roles: `prospector` is
`read-only`, `assayer` is `execute`, `wright` is `all`.

`execute` does not forbid writes. A started command writes everything the
process user can write. That is role discipline, not isolation.

## Elevation

A one-off step outside the hired mode is a grant, not a question. The worker
names the class it lacks (`read`, `write`, or `execute`) and a reason. The
orchestrator answers with `priiisk grant <id>` or `priiisk grant <id> --deny`.
An allow opens a window until the worker finishes the turn by returning a
result; interrupt, error, and retry do not close it. The next need is a new
request. The hired mode does not change.

## Worker workspace

`priiisk hire --workspace worktree` creates a named workspace with its own
working tree and branch. Hire a second worker into it by name:
`priiisk hire --workspace <name>`. A reviewer can then read the writer's work
before any merge. It is not a sandbox: the object database, refs, repository
config, hooks, and the user permissions of the same repository stay shared.
Dismissal is cooperative. Take the finished work with an ordinary `git merge`.

`priiisk workspace list` shows who lives in which workspace.
`priiisk workspace forget <name>` removes an empty named workspace.
`priiisk workspace sweep` lists orphan trees left after a crash: an empty named
workspace is not an orphan. `--confirm` deletes only trees that are clean and
whose branch is already reachable from another ref. A dirty tree and a tree
with an unmerged branch stay put.

## Configuration

The camp reads one user TOML file: `$XDG_CONFIG_HOME/priiisk/config.toml`, or
`~/.config/priiisk/config.toml` when `XDG_CONFIG_HOME` is unset.

The file is checked as a whole. An unknown field is rejected. There are no
silently ignored settings.

### Before the first camp: the agent runtime comes first

priiisk runs workers on the pi agent runtime and **inherits its providers,
models and authentication**. It stores no tokens and copies no model registry,
so a model exists for the camp only if it already exists there.

That makes the order fixed, and it is easy to get wrong:

1. Sign in to pi and connect the providers you intend to use. Adding a provider
   or renewing its authentication is done with pi, not here.
2. Ask pi which `provider/model` references are actually available to you. The
   camp accepts an exact reference, not a family or a display name.
3. Map those references to short aliases in the priiisk config below, and use
   the aliases in roles and presets.
4. Run `priiisk doctor`. It confirms that every configured alias resolves in the
   pi catalog and that authentication for it is available — by reading the
   catalog, without sending a prompt or spending anything.

Skipping the first two steps is the usual first failure: the config is valid
TOML, the camp starts, and the first hire dies because the model reference
belongs to no one.

A minimal file. Replace both `id` values before `camp up`; the placeholders below are only the required `provider/model` shape:

```toml
schemaVersion = 2

[defaults]
model = "strong"
thinking = "medium"

[models.strong]
id = "provider/model"

[models.fast]
id = "provider/model"

[roles.assayer]
description = "Review worker"
model = "strong"
thinking = "high"
access = "execute"

[hirePresets.safe-review]
description = "Review without a shell"
role = "assayer"
access = "read-only"
```

Replace both `id` values with models from your agent runtime. `defaults.model`
and `defaults.thinking` are required. A hire preset may name a built-in role
(`wright`, `assayer`, `prospector`) and then tighten access.

A repository may keep `.priiisk/config.toml` and override policy from the user
file: models, roles, hire presets, skill groups, defaults, and workspace. It
does not read MCP server definitions or the external-binary catalog from the
repository: those fields name what the camp will start, so taking them from a
clone would run someone else's code on the first hire.
