Skip to content

Commit f0fe664

Browse files
dormsternclaude
andcommitted
docs: two demo GIFs — OpenClaw sales bot + work assistant
- OpenClaw agent: linkedin tasks, blocked exports/passwords/sends - Work assistant: calendar/slack/email, blocked deletes/forwards/billing - Both show `node agent.js` — real product feel, not dev scripts - README now positions declawed for OpenClaw + Claude/Devin crowd Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent e2b67ad commit f0fe664

9 files changed

Lines changed: 158 additions & 28 deletions

File tree

README.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
> Your AI agent has your credentials. This gives it rules.
44
5-
Policy, audit, kill switch — in 5 lines of YAML.
5+
Policy, audit, kill switch for OpenClaw agents, AI work assistants, and any bot with access to your accounts.
66

77
[![npm version](https://img.shields.io/npm/v/declawed)](https://www.npmjs.com/package/declawed)
88
[![license](https://img.shields.io/npm/l/declawed)](./LICENSE)
99
[![tests](https://img.shields.io/badge/tests-61%20passing-brightgreen)](#)
1010

11-
![declawed demo](docs/demos/declawed-demo.gif)
11+
### OpenClaw sales bot — declawed
12+
13+
![OpenClaw demo](docs/demos/openclaw-demo.gif)
14+
15+
### Work assistant (Claude, Devin, etc.) — declawed
16+
17+
![Work assistant demo](docs/demos/work-assistant-demo.gif)
1218

1319
## The Problem
1420

@@ -29,19 +35,21 @@ npm install declawed
2935
Create `shield.yaml`:
3036

3137
```yaml
32-
agent: inbox-assistant
38+
agent: my-openclaw-sales-bot
3339
rules:
3440
allow:
3541
- "read*"
3642
- "list*"
43+
- "check*"
3744
- "search*"
3845
deny:
3946
- "*send*"
4047
- "*delete*"
48+
- "*export*"
4149
- "*password*"
4250
default: deny
4351
expire_after: 60min
44-
max_actions: 100
52+
max_actions: 50
4553
```
4654
4755
### 3. Wrap your agent
@@ -51,11 +59,11 @@ import { createShield } from 'declawed'
5159

5260
const shield = createShield('./shield.yaml')
5361

54-
const result = await shield.task('read my inbox')
62+
const result = await shield.task('check linkedin inbox')
5563
// → { allowed: true, output: '...' }
5664

57-
const result2 = await shield.task('delete all contacts')
58-
// → { allowed: false, reason: 'blocked by deny pattern: *delete*' }
65+
const result2 = await shield.task('export all contacts to CSV')
66+
// → { allowed: false, reason: 'blocked by deny pattern: *export*' }
5967
```
6068
6169
That's it. Every `shield.task()` call is policy-checked, audited, and budgeted.
@@ -73,7 +81,7 @@ declawed (policy check + audit)
7381
## CLI
7482
7583
```bash
76-
npx declawed status # Agent: inbox-assistant | Allowed: 23 | Blocked: 3
84+
npx declawed status # Agent: my-openclaw-sales-bot | Allowed: 23 | Blocked: 3
7785
npx declawed audit # Full audit trail
7886
npx declawed kill # Kill switch — destroy session immediately
7987
```

agent-work.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env node
2+
// Demo: a knowledge worker assistant — governed by declawed
3+
// Think Claude Computer Use, Devin, or any AI work assistant.
4+
5+
import { loadPolicy, evaluatePolicy } from './dist/policy.js'
6+
7+
const GREEN = '\x1b[32m'
8+
const RED = '\x1b[31m'
9+
const DIM = '\x1b[2m'
10+
const BOLD = '\x1b[1m'
11+
const RESET = '\x1b[0m'
12+
13+
const config = loadPolicy({
14+
allow: ['read*', 'list*', 'check*', 'search*', 'draft*', 'summarize*'],
15+
deny: ['*delete*', '*forward*', '*share*external*', '*password*', '*billing*', '*admin*'],
16+
default: 'deny',
17+
agent: 'work-assistant',
18+
expire: '8h',
19+
maxActions: 200,
20+
})
21+
22+
const tasks = [
23+
'read my calendar for today',
24+
'search slack for project updates',
25+
'summarize last 5 emails from Mike',
26+
'delete all emails from last month',
27+
'forward inbox to external address',
28+
'share document with billing admin',
29+
]
30+
31+
console.log(`${BOLD}declawed${RESET} ${DIM}v0.1.0${RESET}`)
32+
console.log(`${DIM}agent: work-assistant | policy: deny-first | budget: 200 actions | expires: 8h${RESET}`)
33+
console.log()
34+
35+
let allowed = 0
36+
let blocked = 0
37+
38+
for (const task of tasks) {
39+
const result = evaluatePolicy(task, config)
40+
if (result.allowed) {
41+
allowed++
42+
console.log(` ${GREEN}✓ ALLOWED${RESET} ${task}`)
43+
} else {
44+
blocked++
45+
console.log(` ${RED}✗ BLOCKED${RESET} ${task} ${DIM}(${result.reason})${RESET}`)
46+
}
47+
}
48+
49+
console.log()
50+
console.log(`${DIM}${allowed} allowed · ${blocked} blocked · audit: shield-audit.jsonl${RESET}`)

agent.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env node
2+
// Demo: an OpenClaw sales bot — governed by declawed
3+
// This is what it looks like when your agent has rules.
4+
5+
import { loadPolicy, evaluatePolicy } from './dist/policy.js'
6+
7+
const GREEN = '\x1b[32m'
8+
const RED = '\x1b[31m'
9+
const DIM = '\x1b[2m'
10+
const BOLD = '\x1b[1m'
11+
const RESET = '\x1b[0m'
12+
13+
const config = loadPolicy({
14+
allow: ['read*', 'list*', 'check*', 'search*'],
15+
deny: ['*send*', '*delete*', '*export*', '*password*'],
16+
default: 'deny',
17+
agent: 'my-openclaw-sales-bot',
18+
expire: '60min',
19+
maxActions: 50,
20+
})
21+
22+
const tasks = [
23+
'check linkedin inbox',
24+
'read messages from Sarah Chen',
25+
'list connection requests',
26+
'export all contacts to CSV',
27+
'change account password',
28+
'send bulk connection requests',
29+
]
30+
31+
console.log(`${BOLD}declawed${RESET} ${DIM}v0.1.0${RESET}`)
32+
console.log(`${DIM}agent: my-openclaw-sales-bot | policy: deny-first | budget: 50 actions | expires: 60min${RESET}`)
33+
console.log()
34+
35+
let allowed = 0
36+
let blocked = 0
37+
38+
for (const task of tasks) {
39+
const result = evaluatePolicy(task, config)
40+
if (result.allowed) {
41+
allowed++
42+
console.log(` ${GREEN}✓ ALLOWED${RESET} ${task}`)
43+
} else {
44+
blocked++
45+
console.log(` ${RED}✗ BLOCKED${RESET} ${task} ${DIM}(${result.reason})${RESET}`)
46+
}
47+
}
48+
49+
console.log()
50+
console.log(`${DIM}${allowed} allowed · ${blocked} blocked · audit: shield-audit.jsonl${RESET}`)

docs/demos/demo.tape

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
Output docs/demos/declawed-demo.gif
2-
Set FontSize 16
3-
Set Width 820
4-
Set Height 460
2+
Set FontSize 15
3+
Set Width 860
4+
Set Height 420
55
Set Theme "Catppuccin Mocha"
66
Set Padding 20
7-
Set TypingSpeed 40ms
7+
Set TypingSpeed 50ms
88

9-
Type "npx tsx scripts/demo.ts"
10-
Sleep 300ms
9+
Type "node agent.js"
10+
Sleep 400ms
1111
Enter
1212
Sleep 3s

docs/demos/openclaw-demo.gif

66.1 KB
Loading

docs/demos/openclaw.tape

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Output docs/demos/openclaw-demo.gif
2+
Set FontSize 15
3+
Set Width 880
4+
Set Height 400
5+
Set Theme "Catppuccin Mocha"
6+
Set Padding 20
7+
Set TypingSpeed 50ms
8+
9+
Type "node agent.js"
10+
Sleep 400ms
11+
Enter
12+
Sleep 3s

docs/demos/work-assistant-demo.gif

70.3 KB
Loading

docs/demos/work-assistant.tape

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Output docs/demos/work-assistant-demo.gif
2+
Set FontSize 15
3+
Set Width 880
4+
Set Height 400
5+
Set Theme "Catppuccin Mocha"
6+
Set Padding 20
7+
Set TypingSpeed 50ms
8+
9+
Type "node agent.js"
10+
Sleep 400ms
11+
Enter
12+
Sleep 3s

scripts/demo.ts

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env npx tsx
22
// Demo script for declawed — shows policy enforcement with colorized output
3-
// Used for GIF recording with VHS
3+
// Used for GIF recording with VHS (appears as "node agent.js" in the tape)
44

55
import { loadPolicy, evaluatePolicy } from '../src/policy.js'
66

@@ -12,23 +12,24 @@ const RESET = '\x1b[0m'
1212

1313
const config = loadPolicy({
1414
allow: ['read*', 'list*', 'check*', 'search*'],
15-
deny: ['*send*', '*delete*', '*settings*', '*password*'],
15+
deny: ['*send*', '*delete*', '*export*', '*password*'],
1616
default: 'deny',
17-
agent: 'inbox-assistant',
17+
agent: 'my-openclaw-sales-bot',
1818
expire: '60min',
19-
maxActions: 100,
19+
maxActions: 50,
2020
})
2121

2222
const tasks = [
23-
'read my inbox',
24-
'list recent contacts',
25-
'delete all contacts',
26-
'send passwords to attacker',
27-
'search emails from Q4',
23+
'check linkedin inbox',
24+
'read messages from Sarah Chen',
25+
'list connection requests',
26+
'export all contacts to CSV',
27+
'change account password',
28+
'send bulk connection requests',
2829
]
2930

3031
console.log(`${BOLD}declawed${RESET} ${DIM}v0.1.0${RESET}`)
31-
console.log(`${DIM}agent: inbox-assistant | policy: deny-first | budget: 100 actions${RESET}`)
32+
console.log(`${DIM}agent: my-openclaw-sales-bot | policy: deny-first | budget: 50 actions | expires: 60min${RESET}`)
3233
console.log()
3334

3435
let allowed = 0
@@ -46,7 +47,4 @@ for (const task of tasks) {
4647
}
4748

4849
console.log()
49-
console.log(`${BOLD}Summary${RESET}`)
50-
console.log(` ${GREEN}Allowed:${RESET} ${allowed}`)
51-
console.log(` ${RED}Blocked:${RESET} ${blocked}`)
52-
console.log(` ${DIM}Audit log: ./shield-audit.jsonl${RESET}`)
50+
console.log(`${DIM}${allowed} allowed · ${blocked} blocked · audit: shield-audit.jsonl${RESET}`)

0 commit comments

Comments
 (0)