> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pinework.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Rule

> A rule is either an instruction rule that agents read, at workspace, project or agent scope, or a tool permission rule on the workspace floor.

"Rule" names two different things in Pinework. For why rules work this way, see [Rules and instructions](/concepts/rules-and-instructions).

| Kind | What it does | Scopes | Id |
| - | - | - | - |
| Instruction rule | Text that agents read at the start of each run | Workspace, project, agent | A UUID for workspace and project rules. Agent rules use their name. |
| Permission rule | A deny, ask or allow line on the workspace permission floor that limits tool calls | Workspace only | `rule_` plus 10 hex characters, derived from the rule's content |

`pinework rules instructions` and `pinework agent rule` edit instruction rules. `pinework rules list|add|update|delete` edit the permission floor.

## States

Rules have no lifecycle. An agent's edit to AGENT.md, an agent rule or a project rule can need a person's approval. That edit becomes an instruction proposal, and the proposal has states.

| State | Meaning | Ends here |
| - | - | - |
| `proposed` | The edit waits on an open approval. Nothing has changed yet. | No |
| `applied` | A person approved, and the edit was written. | Yes |
| `rejected` | The approval closed without the edit being applied. | Yes |

| From | To | Trigger |
| - | - | - |
| `proposed` | `applied` | A person approves. |
| `proposed` | `rejected` | A person rejects it, or the approval closes another way. |

Who needs approval for which edit:

| Edit | A person | The agent itself | Another agent |
| - | - | - | - |
| Workspace instruction rule | Writes it | Refused with 403 | Refused with 403 |
| Turn a workspace rule off for one agent | Writes it | Refused with 403 | Refused with 403 |
| Project rule | Writes it | Approval | Approval |
| Agent rule or AGENT.md | Writes it | Writes it | Approval |
| Permission floor | Writes it if a workspace admin | Approval | Approval |

A request that needs approval returns HTTP 202 with `object: "platform_change"`, an `approvalId` and `status: "pending"`. The agent must be in a live run to raise it.

Two values are flags, not states. A permission rule's `enabled` parks it off the floor without deleting it. A workspace rule's per-agent `enabled` is `null` when the agent inherits it, `false` when turned off, and `true` when turned back on.

## Fields

### Workspace instruction rule

<ResponseField name="id" type="string" required>UUID of the rule.</ResponseField>
<ResponseField name="workspaceId" type="string" required>Workspace the rule belongs to.</ResponseField>
<ResponseField name="name" type="string" required>Unique name in the workspace. You manage the rule by it.</ResponseField>
<ResponseField name="content" type="string" required>The text agents read.</ResponseField>
<ResponseField name="scope" type="string" required>Origin scope tier.</ResponseField>
<ResponseField name="provenance" type="string" required>Origin. A rule written in Pinework has `native`.</ResponseField>
<ResponseField name="contentHash" type="string" required>SHA-256 of the normalized content.</ResponseField>
<ResponseField name="tokenCount" type="integer">Approximate token cost per run. Null when not counted yet.</ResponseField>
<ResponseField name="createdAt" type="string">Creation time.</ResponseField>
<ResponseField name="updatedAt" type="string">Last change time.</ResponseField>

A project rule has the same fields minus `scope`, `provenance` and `contentHash`, plus `projectId`.

### Agent rule

<ResponseField name="name" type="string" required>Rule name. Lowercase letters, digits and hyphens, starting with a letter or digit.</ResponseField>
<ResponseField name="content" type="string" required>The text this agent reads.</ResponseField>
<ResponseField name="tokenCount" type="integer">Approximate token cost per run. Null when not counted yet.</ResponseField>

### Instruction proposal

<ResponseField name="object" type="string" required>Always `instruction_proposal_target`.</ResponseField>
<ResponseField name="approvalId" type="string" required>The `apr_…` approval that decides the edit.</ResponseField>
<ResponseField name="proposalId" type="string">The `iprop_…` id of an older stored proposal. Null for edits raised as an approval request.</ResponseField>
<ResponseField name="targetKind" type="string" required>`agent_md`, `agent_rule` or `project_rule`.</ResponseField>
<ResponseField name="state" type="string" required>`proposed`, `applied` or `rejected`.</ResponseField>
<ResponseField name="targetLabel" type="string" required>Readable name of what the edit changes.</ResponseField>
<ResponseField name="name" type="string">Rule name. Null for an AGENT.md edit.</ResponseField>
<ResponseField name="proposedContent" type="string">New text. Null when the edit deletes a rule.</ResponseField>
<ResponseField name="currentContent" type="string">Text the edit replaces. Null when nothing exists yet.</ResponseField>
<ResponseField name="proposedByAgentId" type="string">Agent that asked for the edit.</ResponseField>
<ResponseField name="createdAt" type="string" required>When the edit was proposed.</ResponseField>

### Permission rule

<ResponseField name="id" type="string" required>`rule_` plus 10 hex characters. It changes when the content changes.</ResponseField>
<ResponseField name="action" type="string" required>`deny`, `ask` or `allow`.</ResponseField>
<ResponseField name="summary" type="string" required>One readable line for the rule.</ResponseField>
<ResponseField name="enabled" type="boolean" required>`false` when the rule is parked off the floor.</ResponseField>

You write a permission rule in one of two shapes:

<ResponseField name="kind" type="string" required>`builtin` for a built-in tool, `mcp` for an MCP tool.</ResponseField>
<ResponseField name="tool" type="string" required>For `builtin`: `read`, `edit`, `write`, `bash`, `glob`, `grep`, `agent`, `web_fetch`, `tool_search`, `multi_edit` or `notebook_edit`. For `mcp`: a tool name or `*`.</ResponseField>
<ResponseField name="server" type="string">MCP server name. Required when `kind` is `mcp`.</ResponseField>

<ResponseField name="match" type="object">
  Narrows a `builtin` rule. Leave it out to match every call.

  <Expandable title="match">
    <ResponseField name="paths" type="string[]">Path globs.</ResponseField>
    <ResponseField name="domains" type="string[]">Host names, for `web_fetch`.</ResponseField>
    <ResponseField name="commandPrefixes" type="string[]">Command prefixes, for `bash`.</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="action" type="string" required>`deny`, `ask` or `allow`.</ResponseField>

When rules target the same tool and argument, `deny` beats `ask` and `ask` beats `allow`.

## CLI

| Command | Does |
| - | - |
| `pinework rules list` | Show the permission floor, grouped deny, ask, allow. Filter with `--action`. |
| `pinework rules add` | Add one permission rule. Takes `--tool`, `--action`, and repeatable `--prefix`, `--path` or `--domain`. |
| `pinework rules update <ruleId>` | Replace one permission rule. Restate every flag. Prints the new id. |
| `pinework rules delete <ruleId>` | Remove one permission rule. Deleting a deny weakens the floor. |
| `pinework rules history` | Show who changed the floor or an instruction rule, newest first. |
| `pinework rules instructions list` | List workspace instruction rules with size and last change. |
| `pinework rules instructions get <name>` | Print one workspace instruction rule's content. |
| `pinework rules instructions set` | Create or edit a workspace instruction rule by `--name`. It never renames. |
| `pinework rules instructions delete <name>` | Delete a workspace instruction rule. |
| `pinework agent rule list` | List an agent's own rules, then each workspace rule marked on or off. |
| `pinework agent rule set <name>` | Create or replace an agent rule from `--content` or `--content-file`. |
| `pinework agent rule delete <name>` | Delete an agent rule. |
| `pinework agent rule disable <name>` | Turn a workspace instruction rule off for one agent. |
| `pinework agent rule enable <name>` | Turn it back on. |
| `pinework agent identity` | Print an agent's AGENT.md and agent rules. The hash goes to stderr. |

The `agent rule` verbs default to the calling agent. `--tool` takes runtime names such as `Bash` or `Read`, or `mcp__server__tool`.

```bash theme={null}
pinework rules add --tool Bash --prefix "git push --force" --action deny
pinework rules instructions set --name no-secrets-in-logs --content "Never print a secret value."
pinework agent rule set @builder tests-first --content "Write the failing test before the fix."
pinework agent rule disable no-secrets-in-logs --agent @builder
```

## API

Workspace routes also answer under `/api/v1/workspaces/{workspaceId}` in place of `/api/v1/companies/{workspaceId}`, except the permission routes.

| Method | Path | Does |
| - | - | - |
| GET | `/api/v1/companies/{workspaceId}/rules` | List workspace instruction rules. |
| POST | `/api/v1/companies/{workspaceId}/rules` | Create one. Body `{name, content}`. People only. |
| PUT | `/api/v1/companies/{workspaceId}/rules/{ruleId}` | Rename or rewrite one. People only. |
| DELETE | `/api/v1/companies/{workspaceId}/rules/{ruleId}` | Delete one. People only. |
| GET | `/api/v1/companies/{workspaceId}/rules/agents/{agentId}` | List workspace rules with one agent's on or off override. |
| PUT | `/api/v1/companies/{workspaceId}/rules/{ruleId}/agents/{agentId}` | Set `enabled` for one agent. People only. |
| GET | `/api/v1/companies/{workspaceId}/projects/{projectId}/rules` | List project rules. |
| POST | `/api/v1/companies/{workspaceId}/projects/{projectId}/rules` | Create a project rule, or replace the one with that name. |
| PUT | `/api/v1/companies/{workspaceId}/projects/{projectId}/rules/{ruleId}` | Rename or rewrite a project rule. |
| DELETE | `/api/v1/companies/{workspaceId}/projects/{projectId}/rules/{ruleId}` | Delete a project rule. |
| GET | `/api/v1/companies/{workspaceId}/pine-config` | Read the workspace context. |
| PUT | `/api/v1/companies/{workspaceId}/pine-config` | Set or clear the workspace context. Workspace admins only. |
| GET | `/api/v1/agents/{agentId}/identity` | Read AGENT.md, its hash and the agent rules. |
| PUT | `/api/v1/agents/{agentId}/identity/agent-md` | Replace AGENT.md. An agent must send `agentMdBaseHash`. |
| GET | `/api/v1/agents/{agentId}/identity/rules` | List agent rules. |
| PUT | `/api/v1/agents/{agentId}/identity/rules/{name}` | Create or replace an agent rule. Body `{content}`. |
| DELETE | `/api/v1/agents/{agentId}/identity/rules/{name}` | Delete an agent rule. |
| GET | `/api/v1/instruction-proposals/{approvalId}` | Show a proposed edit next to the text it replaces. People only. |
| GET | `/api/v1/companies/{workspaceId}/company-config/permissions` | List permission rules in stored order. |
| POST | `/api/v1/companies/{workspaceId}/company-config/permissions` | Add a permission rule. |
| PUT | `/api/v1/companies/{workspaceId}/company-config/permissions/{ruleId}` | Replace a permission rule. It keeps its position and `enabled`. |
| PATCH | `/api/v1/companies/{workspaceId}/company-config/permissions/{ruleId}` | Turn a permission rule on or off. Body `{enabled}`. |
| DELETE | `/api/v1/companies/{workspaceId}/company-config/permissions/{ruleId}` | Delete a permission rule. |
| GET | `/api/v1/companies/{workspaceId}/history` | List workspace changes. Filter with `kind=workspace.permissions` or `workspace.instructions`. |

## Errors

| Code | HTTP | When | What to do |
| - | - | - | - |
| `permission_rule_exists` | 409 | The floor already holds this rule. | Edit the rule id in the message. |
| `permission_rule_not_found` | 404 | No permission rule has that id. | Run `pinework rules list`. Ids change when content changes. |
| `agent_md_stale` | 409 | An agent saved AGENT.md without a hash, or with an old one. | Re-apply the edit to `details.agentMd`. Send `details.agentMdHash` as `agentMdBaseHash`. |
| `project_not_found` | 404 | The project is not in this workspace. | Check the project id. |
| `instruction_proposal_not_found` | 404 | No instruction edit is linked to that approval. | Check the approval id. |
| `platform_change_requires_run` | 403 | An agent outside a live run asked for a change that needs approval. | Ask from inside a run, or ask a person. |
| `http_exception` | 403 | An agent called a people-only route, or a non-admin edited the floor. | Ask a workspace admin. |

Two errors carry only an `error` string. A duplicate workspace rule name returns 409 "A rule with this name already exists". A bad agent rule name returns 400 "Invalid rule name". Shared codes are in [API errors](/reference/api#errors).

## Limits

* An instruction rule name holds up to 255 characters.
* `rules history` returns up to 100 entries per page.

<CardGroup cols={2}>
  <Card title="Rules and instructions" href="/concepts/rules-and-instructions">
    How rules at each scope reach a run.
  </Card>

  <Card title="Agent" href="/reference/agent">
    AGENT.md, config and history.
  </Card>

  <Card title="Approval" href="/reference/approval">
    How a proposed edit gets decided.
  </Card>

  <Card title="Import" href="/guides/import">
    Bring CLAUDE.md and AGENTS.md in as workspace rules.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.