Skip to main content

Quick start

This walks you from nothing to a sensible perimeter for a typical project.

1. Create a config

fencepost reads config from your project's .claude/ directory. The simplest form is a single file:

.claude/fencepost.yaml
# Pull in curated rule sets as a base.
import:
- claude # allow Claude's built-in tools + enable the /tmp sandbox
- git # sensible git porcelain rules
- secrets # deny secret-bearing inputs, redact secrets from output

# What to do when nothing matches.
default: ask

# What to do when fencepost can't reach a decision (e.g. an unparseable command).
onError: ask

That's enough to be useful. claude allows routine file tools and turns on the scratch sandbox; git allows everyday porcelain, asks before history rewrites, and denies force-pushes; secrets scans tool calls with your installed secret scanner (gitleaks recommended). Everything else falls through to ask.

2. Start a session

Open Claude Code in the project, running it in bypassPermissions mode so fencepost is the sole gate (see permission modes for why):

claude --permission-mode bypassPermissions

On SessionStart, fencepost injects a short guidance message so Claude knows it's behind a gate, and creates /tmp/claude.

Now watch the decisions:

$ git status          # → allow  (silent)
$ git push origin main # → ask (you approve)
$ git push --force # → deny (steered to --force-with-lease)

3. Layer your own rules on top

Imports are the base; your own rules always win. Add project-specific rules under tools:

.claude/fencepost.yaml
import:
- claude
- git

default: ask
onError: ask

tools:
# Non-Bash tools, matched by glob.
allow:
- "mcp__plugin_context7_*" # let the docs MCP through
deny:
- tool: "mcp__dangerous_*"
description: "Blocked by policy"
alternative: "Use the safe equivalent"

bash:
allow:
- bun test
- bun run
ask:
- bun publish
deny:
- curl

See Tool rules and Bash rules for the full schema.

4. Split rules by domain (optional)

As your config grows, switch from one file to a conf.d directory. fencepost loads every *.yaml in it, alphabetically, and merges them:

.claude/
fencepost/
00-base.yaml # imports + default + onError
10-tools.yaml # general tool rules
20-bash.yaml # bash rules
50-project.yaml # project-specific overrides

See Config files for merge semantics.

5. Tune from real usage

After a while, let fencepost tell you what to change:

/audit

The audit skill reads the decision log and suggests promotions (commands you keep approving → move to allow), flags dead rules, and prints the effective config with provenance.

To gate a tool that has no bundled preset, run /preset <tool> — it reads the tool's real command surface and builds the rules into your config. See generating rules for a new tool.

What's next