clawarmor 2.0.0-alpha.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -146
- package/cli.js +3 -2
- package/demo-preview.gif +0 -0
- package/demo.cast +680 -0
- package/demo.gif +0 -0
- package/lib/fix.js +76 -14
- package/lib/harden.js +114 -13
- package/lib/prescan.js +166 -70
- package/lib/protect.js +60 -4
- package/lib/status.js +38 -15
- package/package.json +2 -2
- package/scripts/record-demo.py +125 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Generate a scripted asciinema .cast file for ClawArmor v2.0 demo.
|
|
4
|
+
Captures real command output with simulated typing for professional pacing.
|
|
5
|
+
"""
|
|
6
|
+
import json
|
|
7
|
+
import subprocess
|
|
8
|
+
import time
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
CAST_FILE = os.path.expanduser("~/clawarmor/demo.cast")
|
|
12
|
+
COLS = 110
|
|
13
|
+
ROWS = 35
|
|
14
|
+
PROMPT = "$ "
|
|
15
|
+
|
|
16
|
+
def run_cmd(cmd):
|
|
17
|
+
"""Run a command and return its output."""
|
|
18
|
+
result = subprocess.run(cmd, shell=True, capture_output=True, text=True,
|
|
19
|
+
env={**os.environ, "FORCE_COLOR": "0", "NO_COLOR": "1", "TERM": "dumb"})
|
|
20
|
+
return result.stdout + result.stderr
|
|
21
|
+
|
|
22
|
+
def write_cast(events):
|
|
23
|
+
"""Write asciicast v2 file."""
|
|
24
|
+
header = {
|
|
25
|
+
"version": 2,
|
|
26
|
+
"width": COLS,
|
|
27
|
+
"height": ROWS,
|
|
28
|
+
"timestamp": int(time.time()),
|
|
29
|
+
"title": "ClawArmor v2.0 — Security Audit Demo",
|
|
30
|
+
"env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}
|
|
31
|
+
}
|
|
32
|
+
with open(CAST_FILE, 'w') as f:
|
|
33
|
+
f.write(json.dumps(header) + '\n')
|
|
34
|
+
for ts, etype, data in events:
|
|
35
|
+
f.write(json.dumps([round(ts, 6), etype, data]) + '\n')
|
|
36
|
+
print(f"Written to {CAST_FILE}")
|
|
37
|
+
|
|
38
|
+
def type_text(events, t, text, char_delay=0.045):
|
|
39
|
+
for ch in text:
|
|
40
|
+
events.append((t, "o", ch))
|
|
41
|
+
t += char_delay
|
|
42
|
+
return t
|
|
43
|
+
|
|
44
|
+
def output_text(events, t, text, line_delay=0.008):
|
|
45
|
+
lines = text.split('\n')
|
|
46
|
+
for i, line in enumerate(lines):
|
|
47
|
+
events.append((t, "o", line + ('\n' if i < len(lines) - 1 else '')))
|
|
48
|
+
t += line_delay
|
|
49
|
+
return t
|
|
50
|
+
|
|
51
|
+
def pause(t, seconds):
|
|
52
|
+
return t + seconds
|
|
53
|
+
|
|
54
|
+
def main():
|
|
55
|
+
events = []
|
|
56
|
+
t = 0.0
|
|
57
|
+
|
|
58
|
+
# Opening
|
|
59
|
+
t = output_text(events, t, PROMPT)
|
|
60
|
+
t = pause(t, 0.8)
|
|
61
|
+
|
|
62
|
+
# 1. Audit
|
|
63
|
+
t = type_text(events, t, "# Step 1: Check your OpenClaw security posture", 0.03)
|
|
64
|
+
events.append((t, "o", "\n")); t += 0.1
|
|
65
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
66
|
+
t = type_text(events, t, "clawarmor audit")
|
|
67
|
+
events.append((t, "o", "\n")); t += 0.2
|
|
68
|
+
output = run_cmd("clawarmor audit 2>&1")
|
|
69
|
+
t = output_text(events, t, output, 0.012)
|
|
70
|
+
t = pause(t, 3.0)
|
|
71
|
+
|
|
72
|
+
# 2. Harden dry-run
|
|
73
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
74
|
+
t = type_text(events, t, "# Step 2: See what ClawArmor can fix automatically", 0.03)
|
|
75
|
+
events.append((t, "o", "\n")); t += 0.1
|
|
76
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
77
|
+
t = type_text(events, t, "clawarmor harden --dry-run")
|
|
78
|
+
events.append((t, "o", "\n")); t += 0.2
|
|
79
|
+
output = run_cmd("clawarmor harden --dry-run 2>&1")
|
|
80
|
+
t = output_text(events, t, output, 0.012)
|
|
81
|
+
t = pause(t, 3.0)
|
|
82
|
+
|
|
83
|
+
# 3. Harden auto
|
|
84
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
85
|
+
t = type_text(events, t, "# Step 3: Fix everything automatically", 0.03)
|
|
86
|
+
events.append((t, "o", "\n")); t += 0.1
|
|
87
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
88
|
+
t = type_text(events, t, "clawarmor harden --auto")
|
|
89
|
+
events.append((t, "o", "\n")); t += 0.2
|
|
90
|
+
output = run_cmd("clawarmor harden --auto 2>&1")
|
|
91
|
+
t = output_text(events, t, output, 0.012)
|
|
92
|
+
t = pause(t, 2.5)
|
|
93
|
+
|
|
94
|
+
# 4. Re-audit
|
|
95
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
96
|
+
t = type_text(events, t, "# Step 4: Verify — re-audit after hardening", 0.03)
|
|
97
|
+
events.append((t, "o", "\n")); t += 0.1
|
|
98
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
99
|
+
t = type_text(events, t, "clawarmor audit")
|
|
100
|
+
events.append((t, "o", "\n")); t += 0.2
|
|
101
|
+
output = run_cmd("clawarmor audit 2>&1")
|
|
102
|
+
t = output_text(events, t, output, 0.012)
|
|
103
|
+
t = pause(t, 3.0)
|
|
104
|
+
|
|
105
|
+
# 5. Status
|
|
106
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
107
|
+
t = type_text(events, t, "# Bonus: Full security dashboard", 0.03)
|
|
108
|
+
events.append((t, "o", "\n")); t += 0.1
|
|
109
|
+
t = output_text(events, t, PROMPT); t = pause(t, 0.5)
|
|
110
|
+
t = type_text(events, t, "clawarmor status")
|
|
111
|
+
events.append((t, "o", "\n")); t += 0.2
|
|
112
|
+
output = run_cmd("clawarmor status 2>&1")
|
|
113
|
+
t = output_text(events, t, output, 0.012)
|
|
114
|
+
t = pause(t, 3.0)
|
|
115
|
+
|
|
116
|
+
# End
|
|
117
|
+
t = output_text(events, t, PROMPT)
|
|
118
|
+
t = pause(t, 1.0)
|
|
119
|
+
|
|
120
|
+
write_cast(events)
|
|
121
|
+
print(f"Total duration: {t:.1f}s")
|
|
122
|
+
print(f"Events: {len(events)}")
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
main()
|