Files
gh-jezweb-claude-skills-ski…/templates/permission-control.ts
2025-11-30 08:23:58 +08:00

212 lines
5.7 KiB
TypeScript

import { query } from "@anthropic-ai/claude-agent-sdk";
/**
* Permission Control Template
*
* Demonstrates:
* - Permission modes (default, acceptEdits, bypassPermissions)
* - Custom canUseTool callback
* - Safety controls for dangerous operations
* - Conditional tool approval
*/
// Example 1: Accept Edits Mode (auto-approve file edits)
async function autoApproveEdits() {
const response = query({
prompt: "Refactor the user service to use async/await throughout",
options: {
model: "claude-sonnet-4-5",
workingDirectory: "/path/to/project",
permissionMode: "acceptEdits" // Auto-approve file edits
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log(message.content);
}
}
}
// Example 2: Bypass Permissions (use with caution!)
async function bypassAllPermissions() {
const response = query({
prompt: "Run comprehensive test suite and fix all failures",
options: {
model: "claude-sonnet-4-5",
permissionMode: "bypassPermissions"
// ⚠️ CAUTION: Skips ALL permission checks
// Use only in trusted, sandboxed environments
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log(message.content);
}
}
}
// Example 3: Custom Permission Logic
async function customPermissions() {
const response = query({
prompt: "Deploy the application to production",
options: {
model: "claude-sonnet-4-5",
permissionMode: "default",
canUseTool: async (toolName, input) => {
// Allow read-only operations
if (['Read', 'Grep', 'Glob'].includes(toolName)) {
return { behavior: "allow" };
}
// Deny destructive bash commands
if (toolName === 'Bash') {
const dangerous = [
'rm -rf',
'dd if=',
'mkfs',
'> /dev/',
'shutdown',
'reboot'
];
if (dangerous.some(pattern => input.command.includes(pattern))) {
return {
behavior: "deny",
message: `Destructive command blocked: ${input.command}`
};
}
}
// Require confirmation for deployments
if (input.command?.includes('deploy') ||
input.command?.includes('kubectl apply') ||
input.command?.includes('terraform apply')) {
return {
behavior: "ask",
message: `Confirm deployment: ${input.command}?`
};
}
// Require confirmation for file writes to sensitive paths
if (toolName === 'Write' || toolName === 'Edit') {
const sensitivePaths = [
'/etc/',
'/root/',
'.env',
'credentials',
'secrets',
'config/production'
];
if (sensitivePaths.some(path => input.file_path?.includes(path))) {
return {
behavior: "ask",
message: `Modify sensitive file ${input.file_path}?`
};
}
}
// Allow by default
return { behavior: "allow" };
}
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log(message.content);
}
}
}
// Example 4: Environment-Based Permissions
async function environmentBasedPermissions(environment: 'development' | 'staging' | 'production') {
const response = query({
prompt: "Deploy the latest changes",
options: {
model: "claude-sonnet-4-5",
permissionMode: "default",
canUseTool: async (toolName, input) => {
// Production requires approval for everything
if (environment === 'production') {
if (toolName === 'Bash' || toolName === 'Write' || toolName === 'Edit') {
return {
behavior: "ask",
message: `PRODUCTION: Approve ${toolName}?`
};
}
}
// Staging auto-approves edits
if (environment === 'staging') {
if (toolName === 'Write' || toolName === 'Edit') {
return { behavior: "allow" };
}
}
// Development bypasses most checks
if (environment === 'development') {
return { behavior: "allow" };
}
return { behavior: "allow" };
}
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log(message.content);
}
}
}
// Example 5: Logging & Auditing
async function loggingPermissions() {
const toolLog: Array<{ tool: string; input: any; decision: string; timestamp: Date }> = [];
const response = query({
prompt: "Implement new feature X",
options: {
model: "claude-sonnet-4-5",
permissionMode: "default",
canUseTool: async (toolName, input) => {
// Log all tool usage
console.log(`[${new Date().toISOString()}] Tool requested: ${toolName}`);
const decision = { behavior: "allow" as const };
// Audit log
toolLog.push({
tool: toolName,
input,
decision: decision.behavior,
timestamp: new Date()
});
// Could also send to external logging service
// await logToDatabase(toolName, input, decision);
return decision;
}
}
});
for await (const message of response) {
if (message.type === 'assistant') {
console.log(message.content);
}
}
// Print audit log
console.log('\n\n=== Audit Log ===');
toolLog.forEach(entry => {
console.log(`${entry.timestamp.toISOString()} - ${entry.tool} - ${entry.decision}`);
});
}
// Run
customPermissions().catch(console.error);