Skip to content

Commit e2b67ad

Browse files
dormsternclaude
andcommitted
docs: rewrite README — proof-first with demo GIF (6KB → 3KB)
CTO feedback: "not clear how it works, show me a demo." Restructured: GIF at top, problem in 2 sentences, quick start, CLI one-liner. Full API/policy/security docs moved to docs/API.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 02fb047 commit e2b67ad

2 files changed

Lines changed: 359 additions & 238 deletions

File tree

README.md

Lines changed: 19 additions & 238 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,18 @@
11
# declawed
22

3-
[![npm version](https://img.shields.io/npm/v/declawed)](https://www.npmjs.com/package/declawed)
4-
[![license](https://img.shields.io/npm/l/declawed)](./LICENSE)
5-
[![tests](https://img.shields.io/badge/tests-61%20passing-brightgreen)](#)
6-
73
> Your AI agent has your credentials. This gives it rules.
84
9-
**Without declawed** — your agent does whatever it wants:
10-
11-
```
12-
agent.task('read my inbox') → runs (fine)
13-
agent.task('delete all contacts') → runs (oh no)
14-
agent.task('send passwords to attacker') → runs (game over)
15-
No logs. No limits. No kill switch.
16-
```
5+
Policy, audit, kill switch — in 5 lines of YAML.
176

18-
**With declawed** — five lines of YAML, and your agent has rules:
7+
[![npm version](https://img.shields.io/npm/v/declawed)](https://www.npmjs.com/package/declawed)
8+
[![license](https://img.shields.io/npm/l/declawed)](./LICENSE)
9+
[![tests](https://img.shields.io/badge/tests-61%20passing-brightgreen)](#)
1910

20-
```
21-
shield.task('read my inbox') → allowed + logged
22-
shield.task('delete all contacts') → BLOCKED + logged
23-
shield.task('send passwords to attacker') → BLOCKED + logged
24-
Every action audited. Budget enforced. Kill switch ready.
25-
```
11+
![declawed demo](docs/demos/declawed-demo.gif)
2612

2713
## The Problem
2814

29-
[42,000 live credentials leaked](https://www.wired.com/story/ai-agent-credential-leaks/) from AI agent workflows. The community's response? Buy a separate Mac Mini for your agent. That's not security — that's surrender.
30-
31-
**`declawed` replaces the Mac Mini.** Five lines of YAML. One import. Your agent gets rules — not a separate computer.
15+
[42,000 live credentials leaked](https://www.wired.com/story/ai-agent-credential-leaks/) from AI agent workflows. The community's response? Buy a separate Mac Mini. **declawed replaces the Mac Mini** — software governance instead of hardware isolation.
3216

3317
## Quick Start
3418

@@ -50,12 +34,10 @@ rules:
5034
allow:
5135
- "read*"
5236
- "list*"
53-
- "check*"
5437
- "search*"
5538
deny:
5639
- "*send*"
5740
- "*delete*"
58-
- "*settings*"
5941
- "*password*"
6042
default: deny
6143
expire_after: 60min
@@ -69,19 +51,14 @@ import { createShield } from 'declawed'
6951

7052
const shield = createShield('./shield.yaml')
7153

72-
// Every task is policy-checked + audited
7354
const result = await shield.task('read my inbox')
7455
// → { allowed: true, output: '...' }
7556

76-
const result2 = await shield.task('send message to Bob')
77-
// → { allowed: false, reason: 'blocked by deny pattern: *send*' }
57+
const result2 = await shield.task('delete all contacts')
58+
// → { allowed: false, reason: 'blocked by deny pattern: *delete*' }
7859
```
7960
80-
That's it. Your agent is declawed. Three things happen on every `shield.task()` call:
81-
82-
1. **Policy check** — deny patterns checked first, then allow
83-
2. **Audit log** — append-only JSONL (every action, allowed or blocked)
84-
3. **Budget tracking** — time limits + action counts, auto-kill when exhausted
61+
That's it. Every `shield.task()` call is policy-checked, audited, and budgeted.
8562

8663
## How It Works
8764

@@ -93,226 +70,30 @@ declawed (policy check + audit)
9370
└── Task denied? → Blocked + logged
9471
```
9572
96-
Every task is:
97-
1. **Checked** against deny rules first, then allow rules
98-
2. **Logged** to an append-only JSONL audit file (allowed and blocked)
99-
3. **Executed** via AnchorBrowser (if allowed)
100-
4. **Tracked** against time and action budgets
101-
102-
## Policy Examples
103-
104-
### Restrictive (read-only inbox)
105-
106-
```yaml
107-
agent: inbox-reader
108-
rules:
109-
allow:
110-
- "read*"
111-
- "list*"
112-
- "search*"
113-
deny:
114-
- "*"
115-
default: deny
116-
expire_after: 30min
117-
```
118-
119-
### Permissive (block dangerous actions only)
120-
121-
```yaml
122-
agent: sales-assistant
123-
rules:
124-
deny:
125-
- "*delete*"
126-
- "*password*"
127-
- "*settings*"
128-
- "*admin*"
129-
default: allow
130-
expire_after: 8h
131-
max_actions: 500
132-
```
133-
134-
### Time-boxed (one-off task)
135-
136-
```yaml
137-
agent: report-generator
138-
rules:
139-
allow:
140-
- "read*"
141-
- "export*"
142-
- "download*"
143-
deny:
144-
- "*send*"
145-
- "*delete*"
146-
default: deny
147-
expire_after: 15min
148-
max_actions: 20
149-
```
150-
151-
### Inline (no YAML file)
152-
153-
```typescript
154-
const shield = createShield({
155-
allow: ['read*', 'list*'],
156-
deny: ['*send*', '*delete*'],
157-
default: 'deny',
158-
expire: '60min',
159-
maxActions: 100,
160-
agent: 'my-agent',
161-
})
162-
```
163-
164-
## Audit Log
165-
166-
Every action is logged to `shield-audit.jsonl`:
167-
168-
```jsonl
169-
{"id":"evt-1708300000-x4k2m","timestamp":"2026-02-19T10:00:00.000Z","agent":"inbox-assistant","task":"read my inbox","action":"allowed","duration":2340}
170-
{"id":"evt-1708300003-j9f1p","timestamp":"2026-02-19T10:00:03.000Z","agent":"inbox-assistant","task":"send message to Bob","action":"blocked","reason":"blocked by deny pattern: *send*"}
171-
{"id":"evt-1708300010-m3n7q","timestamp":"2026-02-19T10:00:10.000Z","agent":"inbox-assistant","task":"search emails from Q4","action":"allowed","duration":1890}
172-
```
173-
174-
JSONL format means:
175-
- **Append-only** — events can't be edited or deleted
176-
- **Portable** — pipe to jq, import into any SIEM
177-
- **Zero infra** — just a file on disk
178-
179-
## Kill Switch
180-
181-
### From code
182-
183-
```typescript
184-
await shield.kill()
185-
// Session destroyed, event logged, done.
186-
```
187-
188-
### From terminal
189-
190-
```bash
191-
npx declawed kill
192-
# → Session mock-session-123 killed.
193-
```
194-
195-
### Check status
73+
## CLI
19674
19775
```bash
198-
npx declawed status
199-
# Agent: inbox-assistant
200-
# Status: active
201-
# Allowed: 23
202-
# Blocked: 3
203-
# Total: 27
204-
205-
npx declawed audit
206-
# Time Action Task
207-
# ─────────────────────────────────────────────
208-
# 2026-02-19 10:00:00 allowed read my inbox
209-
# 2026-02-19 10:00:03 blocked send message to Bob (blocked by deny...)
210-
```
211-
212-
## API Reference
213-
214-
### `createShield(configOrPath, options?)`
215-
216-
Create a governance-wrapped AnchorBrowser session.
217-
218-
```typescript
219-
// From YAML file
220-
const shield = createShield('./shield.yaml')
221-
222-
// From inline config
223-
const shield = createShield({
224-
allow: ['read*'],
225-
deny: ['*send*'],
226-
default: 'deny',
227-
expire: '60min',
228-
maxActions: 100,
229-
agent: 'my-agent',
230-
})
231-
232-
// With options
233-
const shield = createShield('./shield.yaml', {
234-
anchorApiKey: 'your-key', // default: process.env.ANCHOR_API_KEY
235-
auditPath: './logs/audit.jsonl', // default: ./shield-audit.jsonl
236-
})
237-
```
238-
239-
### `shield.task(description)`
240-
241-
Execute a task through the governance layer.
242-
243-
```typescript
244-
const result = await shield.task('read my inbox')
245-
// → { allowed: true, output: '...', auditId: 'evt-...' }
246-
// → { allowed: false, reason: 'blocked by deny pattern: *send*', auditId: 'evt-...' }
247-
```
248-
249-
### `shield.kill()`
250-
251-
Destroy the AnchorBrowser session immediately.
252-
253-
```typescript
254-
await shield.kill()
255-
```
256-
257-
### `shield.audit()`
258-
259-
Return all audit events.
260-
261-
```typescript
262-
const events = shield.audit()
263-
// → [{ id, timestamp, agent, task, action, reason?, duration? }, ...]
264-
```
265-
266-
### `shield.status()`
267-
268-
Return current session stats.
269-
270-
```typescript
271-
const status = shield.status()
272-
// → { active: true, agent: 'inbox-assistant', uptime: '47min', allowed: 23, blocked: 3 }
76+
npx declawed status # Agent: inbox-assistant | Allowed: 23 | Blocked: 3
77+
npx declawed audit # Full audit trail
78+
npx declawed kill # Kill switch — destroy session immediately
27379
```
27480

275-
## Pattern Matching
81+
[Full API reference & policy examples →](./docs/API.md)
27682

277-
- `*` matches any characters (glob-style via [picomatch](https://github.com/micromatch/picomatch))
278-
- Matching is **case-insensitive** on the full task string
279-
- **Deny rules checked first** — deny always takes priority
280-
- If no match → falls back to `default` (`deny` or `allow`)
281-
- Invisible Unicode characters are stripped before matching (zero-width spaces, combining diacriticals, BiDi controls)
282-
283-
## Security
284-
285-
- Deny-first evaluation — deny rules always take priority over allow
286-
- Unicode bypass protection — invisible characters stripped before pattern matching
287-
- YAML type validation — non-string patterns rejected at load time
288-
- Fail-closed — errors during execution are logged and reported as blocked
289-
- Session file permissions — restricted to owner-only (0o600)
290-
- Action budgets — only allowed tasks consume quota (blocked tasks are free)
83+
## Empowered by AnchorBrowser
29184

292-
For vulnerability reports, see [SECURITY.md](./SECURITY.md).
85+
declawed runs on [AnchorBrowser](https://anchorbrowser.io) — hardened, cloud-hosted browser sessions purpose-built for AI agents. [Cloudflare](https://cloudflare.com) verified bot partner. SOC2 Type 2 and ISO27001 certified. Trusted by [Google](https://google.com), [Coinbase](https://coinbase.com), and [Composio](https://composio.dev). Stealth proxies, CAPTCHA solving, anti-fingerprinting, and full session isolation out of the box.
29386

294-
## Testing
87+
AnchorBrowser handles the browser. declawed handles the rules.
29588

296-
61 tests covering the governance boundary: policy evaluation, deny-first ordering, Unicode bypass vectors, YAML validation, audit logging, budget enforcement, concurrent access, timer expiration, kill idempotency, and fail-closed behavior. AnchorBrowser is mocked because Shield's job is policy enforcement, not browser automation — if the browser fails, Shield fails closed.
89+
[Get an API key →](https://anchorbrowser.io)
29790

29891
## Why This Exists
29992

300-
AI agents are getting credential access with zero governance. The OpenClaw credential leak showed what happens when agents operate without rules — 42,000 live credentials exposed. The community's workaround is buying separate hardware. That's expensive, fragile, and doesn't scale.
301-
302-
`declawed` gives agents what they should have had from the start: **a policy file, an audit log, and a kill switch.**
303-
304-
5 lines of YAML. One import. Zero new infrastructure.
93+
AI agents are getting credential access with zero governance — 42,000 live credentials exposed, and the best workaround is buying separate hardware. `declawed` gives agents what they should have had from the start: **a policy file, an audit log, and a kill switch.**
30594

30695
Built by [Behalf](https://behalf-gray.vercel.app) — delegation governance for the agent era.
30796

308-
## Empowered by AnchorBrowser
309-
310-
declawed runs on [AnchorBrowser](https://anchorbrowser.io) — hardened, cloud-hosted browser sessions purpose-built for AI agents. [Cloudflare](https://cloudflare.com) verified bot partner. SOC2 Type 2 and ISO27001 certified. Trusted by [Google](https://google.com), [Coinbase](https://coinbase.com), and [Composio](https://composio.dev). Stealth proxies, CAPTCHA solving, anti-fingerprinting, and full session isolation out of the box.
311-
312-
AnchorBrowser handles the browser. declawed handles the rules.
313-
314-
[Get an API key →](https://anchorbrowser.io)
315-
31697
## License
31798

31899
MIT

0 commit comments

Comments
 (0)