# jig-core: the tool manager

**Status: built.** `jig-core` governs every tool call the agent makes, whoever wrote the tool.

`jig-core` governs every tool call the agent makes, whoever wrote the tool: Pi's
own tools, Jig's tools, and tools from other packages. Every other Jig plugin
needs it.

For each call it works out where the call acts and whether it reads or writes,
applies your rules, asks you when a rule says so, masks and redacts the result,
and records the call. For example, `git push` is a write to `external`, so
`jig-core` shows you the push and waits for your `y` before it runs.

![Every tool call passes through jig-core's hooks before and after it runs](../../docs/img/one-call.svg)

*One call, end to end: it is classified, decided and, when a rule says ask, put to you before it runs; what comes back is redacted, masked, capped and recorded. [Architecture](../../docs/architecture.md) shows how the hooks fit; [Permissions](../../docs/permissions.md) has the rules and the floor.*

## Tool: `watch`

Plugins start watches from their own tools, such as `jig-ops`'s `ci watch`.
This tool lists and stops the watches of every plugin.

| Action | Kind | What it does |
|---|---|---|
| `list` | read | This session's open and paused watches, and those that finished in the last 24 hours |
| `stop` | local write | Cancels an open or paused watch, given its `id`. The agent is not told |

## Commands

| Command | What it does |
|---|---|
| `/jig` | Status: tools governed, plugins loaded, environments and who defined them, open watches, configuration problems |
| `/jig setup` | Fills in the missing parts of plugin settings, in plain words, after you confirm |
| `/jig doctor` | What is wrong with this setup, with one plain fix for each finding |
| `/jig rules [tool]` | The effective decision per tool and action, and where each came from |
| `/jig records` | Where today's records are, and a one-line summary of the day |
| `/profile` | Which company's setup is active and why; `/profile <name>` chooses one for this session, `auto` and `none` too |

What each one shows in full is in the
[configuration reference](docs/configuration.md#the-jig-commands).

## Rules

- **The floor holds.** Configuration cannot lower it: [the fixed rules](../../docs/permissions.md#the-floor-what-configuration-cannot-change).
- **A plugin's gate only tightens.** A gate sees each call after the rules and can make an allow into an
  ask or a deny, never the reverse; one that fails denies the call ([Plugin contract](docs/plugin-contract.md#gates)).
- **Unknown tools ask.** A tool that nothing classifies counts as a write
  outside the machine, and asks until a rule or its own hints say otherwise.
- **Approvals happen only inside the waiting call.** There is no web endpoint
  that could approve.
- **A failure blocks the call.** Anything that fails in `jig-core` blocks the
  call with "jig-core could not decide: ...". Nothing runs because `jig-core`
  could not tell whether it may.
- **The doctor** starts the sandbox broker for real, reports a missing broker or
  built-in roles folder, and names every Jig copy Pi loads with its version.
- **Programs run without a shell,** with a timeout, an output cap and a short
  environment. Git runs with hooks off, and refuses a repository whose own
  configuration would run a command.
- **Nothing leaves this machine on its own.** Records and saved watches stay
  here. `jig-core` sends only the requests that plugins ask for
  (`http.request`), with a credential it reads for them. It never signs in; the tool that owns a login does
  ([Credential sources](docs/sign-in-and-transports.md)).

## Configure

`jig.json` in the Jig home: `~/.jig/jig.json`, unless `JIG_HOME` names another folder. With `jig`, the home is
Pi's agent folder; Jig installed into another Pi folder keeps its `jig.json` there. All fields are optional.

| Field | Default | Meaning |
|---|---|---|
| `environments` | `local`, `external`, `production` | Add test or production environments, each with a `kind` |
| `rules` | the table in [Permissions](../../docs/permissions.md) | `allow`, `ask` or `deny` per tool, action, environment or effect |
| `classify` | none | How to classify tools Jig did not write |
| `protectedPaths` | the [defaults](../../docs/permissions.md#protected-paths) | More paths for Pi's file tools to refuse |
| `secrets.backends` | `["pass"]` | Which backends may resolve secret references |
| `secrets.disabledBackends` | none | Backends to keep off, even ones a company plugin turned on |
| `secrets.commands` | none | The commands that `cmd:<name>` may run, by name |
| `secrets.pass` | none | Where `pass` looks: `storeDir` and `gnupgHome`, each absolute or `~/...` |
| `secrets.pass.unlockAtStart` | `false` | Unlock the pass store once when a session starts, so no prompt comes mid-task |
| `records.retentionDays` | 90 | Days record files are kept, from 1 to 3650 |
| `spill.retentionDays` | 7 | Days spill files and rendered previews are kept |
| `approvals.openInBrowser` | `"on-key"` | `"always"` opens a review screen's preview in the browser as soon as it appears |
| `ui.theme` | `"system"` | `"light"` or `"dark"` for every Jig browser page; a person can still choose on the page |
| `tools.deferred` | none | Jig tools whose descriptions stay out of the context until Pi's `tool_search` finds them |
| `profiles` | none | Named company profiles: `{ "plugin": "jig-acme", "when": { "folders": [...], "remotes": [...] } }`. See [Profiles](docs/profiles.md) |
| `profile` | `"auto"` | Which profile applies: `"auto"` (the first whose folder or remote matches), `"none"`, or a name |
| `startChecks` | none | Up to 16 TCP checks made when a session starts: `name`, `tcp` (`host:port`), `hint` |

[Configuration](docs/configuration.md) has every field, its limits and the two checks that run when a session starts;
[Tools and codemode](docs/tools-and-codemode.md) has deferred tools. An unknown field is an error. It names the file
and the key, and the plugin starts with the defaults rather than guessing. So is a wrong type or value.

```json
{
  "environments": { "staging": { "kind": "test" }, "dev": { "kind": "test", "mask": true } },
  "rules": [
    { "tool": "deploy", "environment": "staging", "effect": "write", "decision": "allow" }
  ],
  "classify": [
    { "tool": "other_db", "param": "target", "value": "live", "environment": "production", "effect": "read" }
  ]
}
```

It needs Pi 1.4 or later, a secret backend if a Jig tool needs secrets (`pass`
on Linux first; any store with a command line works through `cmd:`, see
[Secrets](../../docs/secrets.md#other-stores)), and a sandbox for `bash`, which
[`jig-sandbox`](../jig-sandbox/README.md) is. Without one, `/jig` and session start say plainly that `bash` is not sandboxed.

## Company part (in the company plugin)

- environments, rules and classification rules for its own tools, and which of
  its targets count as production;
- field names that hold personal data in its systems, for masking;
- sign-in services and transports for its systems, and tunnels (a forward, or a SOCKS proxy) for its
  databases;
- defaults for other plugins' sections of `jig.json` (`config.addSectionDefaults`), which your own
  section is laid over, and for `tools` (which tools are deferred);
- a registered name and its overlays (`profiles.register`), so that only the company the work belongs to applies and its rules are
  added to the generic skills ([Profiles](docs/profiles.md));
- secret commands (`config.addSecretCommands`), the secret backends its references need
  (`config.enableSecretBackends`) and protected paths (`config.addProtectedPaths`) for its own
  tools.

## Later

- **Command rules for `bash`** that split a shell string with tree-sitter.
- **Hiding a tool that the rules deny completely** from the model.
- **The form screen.** The form kind uses the selector for now.

## Layout

- `index.ts`: the entry Pi loads; it hands on to `src/index.ts`.
- `src/`: the implementation, its checks and the parts it runs on.
- `skills/`: none: the tool text is the entry.
- `test/`: the unit tests, fake hosts and real-program tests.
Every file: [Code map](docs/code-map.md).

## More detail

**Use it**
- [Setup and doctor](../../docs/setup-and-doctor.md): Read about Setup and doctor.
- [Watches](docs/watches.md): Read before you wait for a watch.
- [Credential sources](docs/sign-in-and-transports.md): Read about Credential sources.
- [What asks](docs/approval-screens.md): Read before a call asks.
- [Results](docs/results.md): Read when a result surprises you.
- [Masking](docs/masking.md): Read when a value is masked.
- [Records](docs/records.md): Read when you need the record.
- [Running programs](docs/running-programs.md): Read before a program runs.
- [Plugin contract](docs/plugin-contract.md): Read before you add a plugin.
- [Reuse](../../docs/reuse.md#tool-manager): Read about Reuse.

**Set it up**
- [Configuration](docs/configuration.md): Read before you add settings.
- [Profiles](docs/profiles.md): Read before you switch a profile.

**Change it**
- [Code map](docs/code-map.md): Read before you change the code.
