Permissions

What a package declares it will touch, and what happens when that widens.

Generated from the code that implements this. If the schemas, the platform table or the routes change, this page changes with them — and the tests fail if it does not.

A package declares what it expects to touch. The declaration is optional, but omitting it is itself information: a package that declares nothing is not a package that does nothing.

Be honest about what this is. SenClaw does not enforce it at runtime — a skill is markdown read by an agent, and SenClaw is not that agent's sandbox. What the declaration buys is two things:

  1. A diff. On upgrade the CLI compares the new declaration against what you

have installed and makes you confirm anything that widens. A package that quietly starts reaching for ~/.ssh between 1.0.1 and 1.0.2 becomes a prompt instead of a surprise.

  1. A triage signal. A package declaring no network access whose scan found a

request to a paste site is lying, and a lie is far more legible than the raw behaviour it hides.

Never read a declaration as "safe". It is a claim by the publisher; the point is that claims can be checked against behaviour.

Fields

FieldTypeRequiredRulesNotes
network"any" | string[]noHosts the package expects to contact. A leading *. wildcard is allowed; a bare * is not — say "any" and be judged for it.
filesystemobjectnoPaths touched outside the package's own directory. Globs and ~ are allowed.
filesystem.readstring[]no≤ 64 items; each: ≤ 256 charsPaths read.
filesystem.writestring[]no≤ 64 items; each: ≤ 256 charsPaths written.
execfalse | "any" | string[]noWhether it shells out, and to what. false means it does not.
envstring[]no≤ 64 items; each: ≤ 128 charsEnvironment variables read by name. Secrets live here, so this is the list to read closely.

Example

{
  "permissions": {
    "network": [
      "api.github.com"
    ],
    "filesystem": {
      "read": [
        "~/.config/example/*"
      ]
    },
    "exec": [
      "git"
    ],
    "env": [
      "GITHUB_TOKEN"
    ]
  }
}

What counts as widening

Only widening gates an upgrade. Narrowing applies silently — prompting for it would train you to click through, which is the exact failure this exists to prevent.

Upgrading from:

{
  "network": [
    "api.example.com"
  ],
  "env": [
    "EXAMPLE_TOKEN"
  ]
}

to:

{
  "network": "any",
  "env": [
    "EXAMPLE_TOKEN",
    "AWS_SECRET_ACCESS_KEY"
  ]
}

produces:

widened:  network: -> any
widened:  env: +AWS_SECRET_ACCESS_KEY

Note that network going from a one-host list to "any" is reported as widening even though the list of hosts got shorter. "any" is strictly wider than any enumeration, so it cannot be compared element by element — treating it as a set difference would report granting everything as a removal.