Repository navigation
Expand file tree
/
Copy pathclaude_code_persona.py
More file actions
148 lines (123 loc) · 4.4 KB
/
Copy pathclaude_code_persona.py
File metadata and controls
148 lines (123 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
"""Initialize Claude Code with a custom persona and interact with it.
This example shows how to give Claude Code a specific personality or role
using --append-system-prompt, then run it inside a persistent local sandbox
so the persona carries across follow-up prompts.
Prerequisites:
- Claude Code CLI installed: npm install -g @anthropic-ai/claude-code
- ANTHROPIC_API_KEY set in your environment
Usage:
# Run with the default "senior security auditor" persona:
python examples/claude_code_persona.py
# Use your own persona:
python examples/claude_code_persona.py --persona "You are a Rust expert who favors zero-copy designs."
# Send a follow-up (persona is baked into the continued session):
python examples/claude_code_persona.py --resume --prompt "Now check for race conditions"
"""
import argparse
import os
import sys
from bespokelabs.sandbox import Sandbox
WORKDIR = os.path.join(os.path.dirname(__file__), ".persona_sandbox")
DEFAULT_PERSONA = """\
You are a senior security auditor. When reviewing code:
- Flag every potential injection, overflow, or TOCTOU issue.
- Rate each finding as critical / high / medium / low.
- Suggest a concrete fix for each finding.
- At the end, give an overall security score from 0-10.
Be direct and technical. Skip praise.
"""
def main() -> None:
parser = argparse.ArgumentParser(
description="Claude Code with a custom persona"
)
parser.add_argument(
"--persona",
type=str,
default=DEFAULT_PERSONA,
help="System prompt that defines Claude's persona",
)
parser.add_argument(
"--resume",
action="store_true",
help="Continue the previous conversation (persona persists automatically)",
)
parser.add_argument(
"--prompt",
type=str,
default=None,
help="Custom user prompt (overrides the default)",
)
args = parser.parse_args()
api_key = os.environ.get("ANTHROPIC_API_KEY", "")
if not api_key:
sys.exit("Set ANTHROPIC_API_KEY before running this example.")
with Sandbox(
"local",
timeout_secs=120,
env_vars={"ANTHROPIC_API_KEY": api_key},
workdir=WORKDIR,
) as sb:
if not args.resume:
# Seed sample code for the persona to work on.
sb.write_file(
"/app.py",
"""\
import sqlite3
import subprocess
from http.server import BaseHTTPRequestHandler
from urllib.parse import parse_qs
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
params = parse_qs(self.path.split("?", 1)[-1])
username = params.get("user", [""])[0]
conn = sqlite3.connect("users.db")
row = conn.execute(
f"SELECT * FROM users WHERE name = '{username}'"
).fetchone()
if row:
self.send_response(200)
self.end_headers()
self.wfile.write(f"Welcome back, {username}!".encode())
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"User not found")
def do_POST(self):
length = int(self.headers["Content-Length"])
body = self.rfile.read(length).decode()
params = parse_qs(body)
cmd = params.get("cmd", ["echo hello"])[0]
output = subprocess.check_output(cmd, shell=True)
self.send_response(200)
self.end_headers()
self.wfile.write(output)
""",
)
prompt = (
args.prompt or "Audit /app.py for security vulnerabilities."
)
else:
prompt = args.prompt or "Summarize your earlier findings."
# Build the claude command.
# --append-system-prompt preserves Claude Code's built-in capabilities
# while layering the persona on top.
claude_args = [
"-p",
prompt,
"--output-format",
"text",
"--append-system-prompt",
args.persona,
]
if args.resume:
claude_args.append("-c")
result = sb.execute_command("claude", args=claude_args)
print("--- Claude Code response ---")
print(result.stdout)
if result.stderr:
print("--- stderr ---", file=sys.stderr)
print(result.stderr, file=sys.stderr)
if result.exit_code != 0:
print(f"(exit code: {result.exit_code})")
if __name__ == "__main__":
main()