
Permissions
- 13 installs
- 610 repo stars
- Updated June 26, 2026
- alsk1992/cloddsbot
Permissions (in cloddsbot) is a skill that manages command-execution approvals, allow/block rules, and tool policies to secure a bot's shell access.
About
This skill controls which shell commands a bot may execute, using approvals, allow/block rules, and per-agent tool policies. A developer uses it to require approval for risky commands, define allowlist or blocklist modes, and always block dangerous patterns like rm -rf / or fork bombs. It also restricts which tools each agent can call.
- Manages command-execution approvals, allow/block rules, and tool policies
- Four security modes: deny, allowlist, blocklist, full
- Built-in safety rules always block rm -rf /, sudo, fork bombs, and injection
Permissions by the numbers
- 13 all-time installs (skills.sh)
- Ranked #1,634 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
permissions capabilities & compatibility
- Use cases
- security audit
- Pricing
- Free
What permissions says it does
Command approvals, tool policies, and exec security
Manage command execution approvals, tool access policies, and security controls.
npx skills add https://github.com/alsk1992/cloddsbot --skill permissionsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 13 |
|---|---|
| repo stars | ★ 610 |
| Last updated | June 26, 2026 |
| Repository | alsk1992/cloddsbot ↗ |
What it does
Gate and approve command execution so a bot cannot run dangerous shell commands.
When should I use this skill?
You need to approve or block shell commands and restrict agent tool access.
What you get
A policy-gated command runner with approvals, allow/block rules, and per-agent tool limits.
By the numbers
- 4 security modes
- 5 always-blocked patterns
Files
Permissions - Complete API Reference
Manage command execution approvals, tool access policies, and security controls.
---
Chat Commands
View Permissions
/permissions View current permissions
/permissions list List all rules
/permissions pending View pending approvals
/permissions history View approval historyApprove/Reject
/approve Approve pending command
/approve <id> Approve specific request
/reject Reject pending command
/reject <id> "reason" Reject with reasonAllow/Block Rules
/permissions allow "npm install" Allow pattern
/permissions allow "git *" Allow with wildcard
/permissions block "rm -rf" Block dangerous command
/permissions remove <rule-id> Remove ruleSecurity Mode
/permissions mode Check current mode
/permissions mode allowlist Only allowed commands
/permissions mode blocklist Block specific commands
/permissions mode full Allow all (dangerous)---
TypeScript API Reference
Create Permissions Manager
import { createPermissionsManager } from 'clodds/permissions';
const perms = createPermissionsManager({
// Security mode
mode: 'allowlist', // 'deny' | 'allowlist' | 'blocklist' | 'full'
// Default rules
defaultAllow: [
'ls *',
'cat *',
'git status',
'git diff',
'npm run *',
],
defaultBlock: [
'rm -rf *',
'sudo *',
'chmod 777 *',
],
// Approval settings
requireApproval: true,
approvalTimeoutMs: 60000,
// Storage
storage: 'sqlite',
dbPath: './permissions.db',
});Check Permission
// Check if command is allowed
const result = await perms.check({
command: 'npm install lodash',
userId: 'user-123',
context: 'Installing dependency',
});
if (result.allowed) {
console.log('Command allowed');
} else if (result.needsApproval) {
console.log(`Waiting for approval: ${result.requestId}`);
} else {
console.log(`Blocked: ${result.reason}`);
}Request Approval
// Request approval for command
const request = await perms.requestApproval({
command: 'docker build -t myapp .',
userId: 'user-123',
reason: 'Building application container',
});
console.log(`Request ID: ${request.id}`);
console.log(`Status: ${request.status}`);
// Wait for approval
const approved = await perms.waitForApproval(request.id, {
timeoutMs: 60000,
});
if (approved) {
console.log('Approved! Executing...');
}Approve/Reject
// Approve request
await perms.approve({
requestId: 'req-123',
approvedBy: 'admin-user',
note: 'Looks safe',
});
// Reject request
await perms.reject({
requestId: 'req-123',
rejectedBy: 'admin-user',
reason: 'Command too broad',
});List Pending
// Get pending approvals
const pending = await perms.listPending();
for (const req of pending) {
console.log(`[${req.id}] ${req.command}`);
console.log(` User: ${req.userId}`);
console.log(` Reason: ${req.reason}`);
console.log(` Requested: ${req.createdAt}`);
}Add Rules
// Add allow rule
await perms.addRule({
type: 'allow',
pattern: 'npm run *',
description: 'Allow npm scripts',
createdBy: 'admin',
});
// Add block rule
await perms.addRule({
type: 'block',
pattern: 'rm -rf /',
description: 'Prevent root deletion',
createdBy: 'admin',
});
// List rules
const rules = await perms.listRules();
for (const rule of rules) {
console.log(`${rule.type}: ${rule.pattern}`);
}
// Remove rule
await perms.removeRule('rule-id');Tool Policies
// Set tool policy for agent
await perms.setToolPolicy({
agentId: 'trading',
allow: ['execute', 'portfolio', 'markets'],
deny: ['browser', 'docker', 'exec'],
});
// Check tool access
const canUse = perms.isToolAllowed('trading', 'execute');
// Get agent's allowed tools
const tools = perms.getAllowedTools('trading');---
Security Modes
| Mode | Behavior |
|---|---|
| deny | Block all exec commands |
| allowlist | Only explicitly allowed commands |
| blocklist | Block specific patterns, allow rest |
| full | Allow all (dangerous!) |
---
Pattern Syntax
| Pattern | Matches |
|---|---|
npm install | Exact command |
npm * | npm with any args |
git status | Exact command |
* --version | Any command with --version |
---
Built-in Safety Rules
Always blocked regardless of mode:
rm -rf /sudo rm -rfchmod 777 /:(){ :|:& };:(fork bomb)- Commands with shell injection patterns
---
CLI Commands
# List permission rules
clodds permissions list
# Add allow pattern
clodds permissions allow "npm run *"
# View pending approvals
clodds permissions pending
# Approve request
clodds permissions approve req-123---
Best Practices
1. Use allowlist mode — Most secure, explicit permissions 2. Review pending regularly — Don't let requests pile up 3. Specific patterns — npm install lodash over npm * 4. Audit history — Review what was approved 5. Tool policies — Restrict agent tool access
/**
* Permissions CLI Skill
*
* Commands:
* /perms list - List allowlist entries for an agent
* /perms check <command> - Check if a command is allowed
* /perms mode [deny|allowlist|full] - Get or set exec security mode
* /perms allow <pattern> - Add pattern to allowlist
* /perms remove <id> - Remove allowlist entry
* /perms policy - View current security policy
* /perms profiles - List available tool profiles
* /perms pending - Show pending approval requests
*/
async function execute(args: string): Promise<string> {
const parts = args.trim().split(/\s+/);
const cmd = parts[0]?.toLowerCase() || 'help';
try {
const mod = await import('../../../permissions/index');
const { execApprovals, toolPolicies, TOOL_PROFILES, SAFE_BINS } = mod;
const agentId = parts[1] === '--agent' ? parts[2] || 'default' : 'default';
// If --agent was used, shift parts so subcommand args still work
const cmdParts = parts[1] === '--agent' ? parts.slice(3) : parts.slice(1);
switch (cmd) {
case 'list':
case 'ls': {
const allowlist = execApprovals.getAllowlist(agentId);
if (allowlist.length === 0) {
return `**Allowlist for "${agentId}"**\n\nNo entries. Use \`/perms allow <pattern>\` to add one.\n\nSafe bins (always allowed): ${Array.from(SAFE_BINS).slice(0, 10).join(', ')}...`;
}
let output = `**Allowlist for "${agentId}"** (${allowlist.length} entries)\n\n`;
output += '| ID | Pattern | Type | Added |\n|-----|---------|------|-------|\n';
for (const entry of allowlist) {
const added = new Date(entry.addedAt).toLocaleDateString();
const shortId = entry.id.slice(0, 8);
output += `| ${shortId} | \`${entry.pattern}\` | ${entry.type} | ${added} |\n`;
}
return output;
}
case 'check': {
const command = cmdParts.join(' ');
if (!command) return 'Usage: /perms check <command>\n\nExample: `/perms check npm install`';
const result = await execApprovals.checkCommand(agentId, command, {
skipApproval: true,
waitForApproval: false,
});
const status = result.allowed ? 'ALLOWED' : 'DENIED';
let output = `**Command Check:** \`${command}\`\n\n`;
output += `Status: **${status}**\n`;
output += `Reason: ${result.reason}\n`;
if (result.entry) {
output += `Matched: \`${result.entry.pattern}\` (${result.entry.type})`;
}
return output;
}
case 'mode': {
const newMode = cmdParts[0]?.toLowerCase();
if (!newMode) {
const config = execApprovals.getSecurityConfig(agentId);
return `**Exec Security Mode** (agent: ${agentId})\n\n` +
`Mode: **${config.mode}**\n` +
`Ask: **${config.ask}**\n` +
`Approval Timeout: ${config.approvalTimeout || 60000}ms\n` +
`Fallback: ${config.fallbackMode || 'deny'}`;
}
if (!['deny', 'allowlist', 'full'].includes(newMode)) {
return 'Invalid mode. Use: `deny`, `allowlist`, or `full`';
}
const askMode = cmdParts[1]?.toLowerCase();
const update: Record<string, string> = { mode: newMode };
if (askMode && ['off', 'on-miss', 'always'].includes(askMode)) {
(update as any).ask = askMode;
}
execApprovals.setSecurityConfig(agentId, update as any);
return `Security mode set to **${newMode}**${askMode ? ` (ask: ${askMode})` : ''} for agent "${agentId}".`;
}
case 'allow':
case 'grant': {
const pattern = cmdParts[0];
if (!pattern) return 'Usage: /perms allow <pattern> [prefix|glob|regex]\n\nExample: `/perms allow npm prefix`';
const type = (cmdParts[1] as 'prefix' | 'glob' | 'regex') || 'prefix';
if (!['prefix', 'glob', 'regex'].includes(type)) {
return 'Invalid pattern type. Use: `prefix`, `glob`, or `regex`';
}
const description = cmdParts.slice(2).join(' ') || undefined;
const entry = execApprovals.addToAllowlist(agentId, pattern, type, { description });
return `Added to allowlist for "${agentId}":\n\n` +
`Pattern: \`${pattern}\`\n` +
`Type: ${type}\n` +
`ID: \`${entry.id.slice(0, 8)}\``;
}
case 'revoke':
case 'remove': {
const entryId = cmdParts[0];
if (!entryId) return 'Usage: /perms remove <id>\n\nUse `/perms list` to see entry IDs.';
// Try to find full ID from prefix
const allowlist = execApprovals.getAllowlist(agentId);
const match = allowlist.find(e => e.id.startsWith(entryId));
if (!match) {
return `No allowlist entry found matching ID \`${entryId}\` for agent "${agentId}".`;
}
const removed = execApprovals.removeFromAllowlist(agentId, match.id);
if (removed) {
return `Removed allowlist entry \`${match.pattern}\` (${match.type}) from agent "${agentId}".`;
}
return `Failed to remove entry.`;
}
case 'policy': {
const config = execApprovals.getSecurityConfig(agentId);
const allowlist = execApprovals.getAllowlist(agentId);
return `**Security Policy** (agent: ${agentId})\n\n` +
`Exec Mode: **${config.mode}**\n` +
`Ask Mode: **${config.ask}**\n` +
`Approval Timeout: ${config.approvalTimeout || 60000}ms\n` +
`Fallback Mode: ${config.fallbackMode || 'deny'}\n` +
`Allowlist Entries: ${allowlist.length}\n` +
`Safe Bins: ${SAFE_BINS.size} pre-approved utilities`;
}
case 'profiles': {
let output = '**Tool Profiles**\n\n';
for (const [name, tools] of Object.entries(TOOL_PROFILES)) {
const expanded = toolPolicies.expandGroups(tools);
output += `**${name}:** ${expanded.length === 1 && expanded[0] === '*' ? 'all tools' : expanded.join(', ')}\n`;
}
return output;
}
case 'pending': {
const pending = execApprovals.getPendingApprovals();
if (pending.length === 0) {
return '**Pending Approvals**\n\nNo pending approval requests.';
}
let output = `**Pending Approvals** (${pending.length})\n\n`;
for (const req of pending) {
const age = Math.round((Date.now() - req.timestamp.getTime()) / 1000);
output += `- \`${req.fullCommand}\` (agent: ${req.agentId}, ${age}s ago)\n ID: \`${req.id.slice(0, 8)}\`\n`;
}
return output;
}
default:
return helpText();
}
} catch (error) {
return `Error: ${error instanceof Error ? error.message : String(error)}`;
}
}
function helpText(): string {
return `**Permissions Commands**
/perms list - List allowlist entries
/perms check <command> - Check if command is allowed
/perms mode [deny|allowlist|full] - Get or set exec security mode
/perms allow <pattern> [type] - Add to allowlist (prefix|glob|regex)
/perms remove <id> - Remove allowlist entry
/perms policy - View security policy
/perms profiles - List tool profiles
/perms pending - Show pending approvals
Add \`--agent <id>\` after subcommand to target a specific agent.`;
}
export default {
name: 'permissions',
description: 'Command approvals, tool policies, and exec security',
commands: ['/perms', '/permissions'],
handle: execute,
};
Related skills
FAQ
What security modes are available?
deny (block all), allowlist (only allowed), blocklist (block patterns), and full (allow all, dangerous).
What is always blocked?
rm -rf /, sudo rm -rf, chmod 777 /, fork bombs, and shell-injection patterns regardless of mode.