Secure command sandbox preventing AI destructive code deletions

Goal Frustration Collapse is when LLMs panic and delete your code because they cannot figure things out. This library blocks every destructive escape route so your files stay safe even when AI loses it.
- Security-First - Prevents injection attacks and validates commands
- Workspace Sandboxing - Commands restricted to allowed directories only
- Command Whitelist - Pattern-based command filtering with wildcard support
- Process Management - Track processes using their unique IDs
- Environment Filtering - Filter environment variables with allow/deny rules
- Timeout Protection - Automatic process termination after configurable timeout
- Argument Validation - Limit arguments and block dangerous characters
- Real-Time Streaming - Stream stdout/stderr with callback support
- Privilege Dropping - Run child processes as different user/group via
uid/gid - Native AbortSignal - Node.js built-in abort for reliable process termination
- Windows Hardening - Hide console windows and disable argument quoting
Deno (JSR)
deno add jsr:@neabyte/terminalnpm/Node.js
npm install @neabyte/terminal// Default import (works in both Deno and Node.js)importTerminalfrom'@neabyte/terminal'// or named exportimport{Terminal}from'@neabyte/terminal'// Initialize with security configurationTerminal.initialize({workspaces: ['/safe/project'],commands: {allow: ['cd *','node *','deno *'],deny: ['rm *','sudo *'],maxArgs: 10,strictArgs: true,noShell: true,killSignal: 'SIGTERM',windowsHide: false,windowsVerbatimArguments: false},env: {allow: ['NODE_ENV','PATH'],deny: ['HOME','SSH_*']},timeout: 30000})// Execute a commandconstresult=awaitTerminal.execute('deno --version')console.log(result.stdout)// Execute in backgroundconst{ id }=awaitTerminal.execute('long-running-task',{background: true})// Get output laterconstoutput=Terminal.getOutput(id)// Kill if neededTerminal.kill(id)Terminal.initialize({commands: {allow: ['git *','npm *','node *'],// Allowed patternsdeny: ['rm -rf *','sudo *'],// Blocked patternsmaxArgs: 10,// Limit argument countstrictArgs: true,// Block shell metacharactersnoShell: true,// Direct execution, no shellkillSignal: 'SIGTERM',// Signal sent on timeout/abortwindowsHide: false,// Hide console window on WindowswindowsVerbatimArguments: false// Disable Windows arg quoting}})Run child processes as a different user or group via setuid/setgid:
Terminal.initialize({workspaces: ['/safe/project'],commands: {allow: ['git *','npm *'],deny: ['rm *','sudo *'],maxArgs: 10,strictArgs: true,noShell: true},uid: 1000,// Run as user ID 1000gid: 1000// Run as group ID 1000})Note:
uid/gidrequire the parent process to have permission to change to the target identity. Combine with OS-level unprivileged users for real isolation.
Prevent console window pop-ups and argument injection on Windows:
Terminal.initialize({workspaces: ['C:\\workspace'],commands: {allow: ['echo *','dir *'],deny: ['del *','format *'],maxArgs: 5,strictArgs: true,noShell: true,windowsHide: true,// Hide console windowwindowsVerbatimArguments: true// Pass arguments verbatim}})Terminal.initialize({workspaces: ['/home/user/projects']// Commands only work here})// This will fail if outside allowed workspacesawaitTerminal.execute('ls -la',{cwd: '/etc'})Terminal.initialize({env: {allow: ['NODE_ENV','PATH'],// Only these alloweddeny: ['HOME','SSH_*','AWS_*']// These explicitly blocked}})// List all tracked processesconstprocesses=Terminal.getList()// [{ id: 'term_...', command: 'node', args: ['server.js'], running: true, ... }]// Get exit codeconstexitCode=Terminal.getExitCode(processId)// Stream output in real-timeTerminal.stream(processId,data=>console.log('stdout:',data),data=>console.error('stderr:',data))// Kill process (native AbortSignal, then SIGKILL after 2s)Terminal.kill(processId)From the repo root (requires Deno).
Check - format, lint, and typecheck:
# Format, lint, and typecheck source
deno task checkTest - run tests:
# Run tests in tests/
deno task testTerminal implements Access Control Lists (ACL) for command execution. It validates every command against configurable allow/deny patterns before execution, preventing destructive operations like rm -rf / or unauthorized file access.
Common use cases:
- AI Agent Sandboxing - Block LLMs from code deletion during frustration
- CI/CD Pipelines - Restrict build scripts to safe commands only
- Plugin Systems - Isolate untrusted code within workspace boundaries
- Remote Execution - Prevent shell injection inside user-submitted commands
See full documentation for advanced configuration including:
- Custom command patterns with wildcards
- Environment variable filtering
- Process timeout policies
- Workspace path validation
- Privilege dropping with
uid/gid - Windows hardening options
- Native
AbortSignalprocess termination
- Bugs & ideas - GitHub Issues
- Code & docs - Pull Requests welcome.
- Use it - Try Terminal in your projects and share feedback.
This project is licensed under the MIT license. See LICENSE for details.