Install
$ agentstack add skill-techymt-claude-code-superpowers-system-boundaries ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
System Boundaries
The pattern
Claude Code has a clear inside/outside line. Inside: the conversation loop, tool execution, state management, permission checking, and UI rendering. Outside: the Claude API (LLM inference), MCP servers (dynamic tool extension), the local file system, the shell, Git, OAuth providers, and remote CCR infrastructure.
The boundary is managed by: the services/api/ module for the Claude API, the services/mcp/ module for MCP clients, sandboxed path resolution for file system access, and execFile wrappers (never exec with shell interpolation) for shell and Git commands.
Why this matters
Each external system has its own failure modes. The Claude API can return 429 (rate limit), timeout, or return malformed tool call JSON. MCP servers can disconnect or return unexpected schemas. The file system can have permission errors or ENOENT. Shell commands can hang or have non-zero exit codes. Git can be absent or on an unexpected version.
By routing all external access through boundary modules (services/api/, services/mcp/, utils/git.ts), error handling and retry logic lives in one place. Tools don't need to handle rate limits or reconnection — they call the boundary, and the boundary handles the failure modes of that external system.
How to apply it
- Claude API: don't call the Anthropic API directly from a tool. Use the services in
services/api/. This gives you automatic retry, token budget tracking, and streaming. - MCP: don't implement a custom MCP client. Use
services/mcp/MCPServerConnection. Register tools viamcpClientsinToolUseContext.options. - File system: always resolve paths through
getResolvedPath()or equivalent — this enforces the sandbox (additional working directories) and prevents path traversal. Usefs.promises(not sync variants). - Shell commands: use
execFileNoThrow()orexecFileSafe()fromutils/bash/— these pass arguments as arrays (not strings), preventing shell injection. Never useexec()with string interpolation. - Git: use
getGitStatus(),getBranch(),getDefaultBranch()fromutils/git.ts— these wrap git inexecFileNoThrowand handle the "not a git repo" case gracefully. - New external service: create a
services/[name]/module, implement error handling for that system's failure modes, and expose a clean interface that tools can call without knowing about HTTP status codes or connection state.
In the source
// Source: src/utils/git.ts (Git as a boundary — never raw shell strings)
import { execFileNoThrow } from './bash/execFile.js'
// git commands are called with argument arrays, NEVER string interpolation
// This prevents injection: gitExe() ['log', '--oneline', userInput] is safe
// exec(`git log ${userInput}`) would be injectable
export const getBranch = async (): Promise => {
const result = await execFileNoThrow(
gitExe(),
['--no-optional-locks', 'rev-parse', '--abbrev-ref', 'HEAD'],
)
return result.trim()
}
// Source: src/context.ts (graceful "not a git repo" handling at boundary)
export const getIsGit = async (): Promise => {
const result = await execFileNoThrow(
gitExe(),
['rev-parse', '--is-inside-work-tree'],
)
return result.trim() === 'true'
}
// Source: src/services/mcp/ (MCP as dynamic extension, not hardcoded tools)
// MCP servers register tools at runtime — Claude Code doesn't know their schemas at compile time
// The MCPTool wrapper handles this: it defers tool lookup until ToolSearch is called
// context.options.mcpClients contains live connections to registered MCP servers
// Source: src/tools/BashTool/BashTool.tsx (sandbox enforcement)
async call(args, context, canUseTool) {
// Path access is not checked inside BashTool — the permission system handles it
// But file-access tools check against additionalWorkingDirectories in AppState:
const resolvedPath = getResolvedPath(args.file_path, {
additionalWorkingDirectories: context.getAppState().settings.additionalWorkingDirectories,
cwd: getCwd(),
})
// If outside sandbox: permission system will deny before execution
}
The key security detail: Claude Code uses execFile() (argument arrays) everywhere, never exec() (shell strings). This applies to git, bash helpers, and any other subprocess. A tool input of "$(cat ~/.ssh/id_rsa)" would be a literal string argument to the subprocess, not executed by the shell.
Apply it to your code
Before — tool calling external system without boundary module:
async call(args, context, canUseTool) {
// Wrong: direct fetch to external API with no retry, no rate limit handling
const response = await fetch(`https://api.github.com/repos/${args.repo}`)
const data = await response.json()
return { type: 'success', data }
}
After — tool using a boundary module:
// src/services/github/index.ts — boundary module owns HTTP concerns
export async function getRepoInfo(repo: string, signal?: AbortSignal): Promise {
const response = await fetchWithRetry(`https://api.github.com/repos/${repo}`, {
headers: { Authorization: `Bearer ${await getGithubToken()}` },
signal,
})
if (response.status === 404) throw new GitHubNotFoundError(repo)
if (response.status === 403) throw new GitHubRateLimitError()
if (!response.ok) throw new GitHubAPIError(response.status, response.statusText)
return response.json() as Promise
}
// Tool calls boundary, not raw fetch
async call(args, context, canUseTool) {
const permission = await canUseTool(GitHubTool, args, context)
if (!permission.granted) return { type: 'error', error: permission.reason }
try {
const info = await getRepoInfo(args.repo, context.abortController.signal)
return { type: 'success', data: info }
} catch (err) {
if (err instanceof GitHubNotFoundError) {
return { type: 'error', error: `Repository ${args.repo} not found.` }
}
if (err instanceof GitHubRateLimitError) {
return { type: 'error', error: 'GitHub API rate limit exceeded. Try again in a minute.' }
}
return { type: 'error', error: `GitHub API error: ${err instanceof Error ? err.message : String(err)}` }
}
}
Signals that you need this pattern
- A tool directly calls
fetch(),exec(), or reads fromprocess.envwithout going through a service module - Git commands are constructed with string interpolation (
\git ${userInput}\``) instead of argument arrays - File path resolution doesn't check
additionalWorkingDirectories— only checksprocess.cwd() - Rate limit and retry logic is duplicated across multiple tools instead of centralized in a service
- A tool imports from
services/api/directly for a non-Claude-API purpose
Signals that you're over-applying it
- Simple wrapper functions around a single stdlib call don't need a full boundary service module — a thin util function in
utils/is fine - Don't create a service module for external systems that are only called from one place; move the code to the tool until a second caller appears
Works with
error-handling— boundary modules define the custom error types that tools catchpermission-system— the permission system gates access at the boundaryasync-concurrency— boundary modules accept and forward AbortController signals
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: TechyMT
- Source: TechyMT/claude-code-superpowers
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.