Terminal as the Execution Substrate for AI Agents: Building Reliable Command-Line and File-System-Based Agents

    This article explains why terminals and file systems are well suited as the execution environment for AI agents. It covers a minimal agent loop, tool design, context management, skill packs, Markdown versus HTML output, rollout and operations, security, reliability, observability, and a staged implementation checklist. It draws on engineering practice and argues that mature, reusable interfaces can provide stronger foundations than bespoke integrations.

    I. Introduction: From Interaction Research to Agent Engineering

    Around 2014, researchers published work on smartphone unlock interactions, exploring how the familiar slide-to-unlock gesture could support additional uses. In 2015, another study used a deformable rod-like hardware device to transmit remote haptic experiences into the user’s hand. Both efforts shared a common focus: existing, widely used interaction carriers. One was the swipe people performed every day; the other was the simplest elongated shape.

    Years later, practitioners working on AI agent engineering applied the same thinking to AI agents. They asked what models already “know.” The answer is that models understand command-line arguments, directory hierarchies, text diffs, and exit codes because these are among the most common tool-use patterns in training corpora. Rather than building a proprietary plugin for every new capability, agents can reuse an environment that has existed for decades and been tested extensively in engineering practice. This approach is often summarized as “the terminal as the agent”: use the command line as the unified interface between agents and the external world, and use the file system as shared memory for state.

    Based on engineering practice, this article breaks down how to build reliable AI agents around terminals and file systems across seven dimensions: execution substrate, tool design, context management, skill packs, output formats, rollout and operations, and security and engineering maturity. The code in this article is illustrative and intended to explain design thinking rather than provide production-ready code.

    II. Why Terminals and File Systems

    2.1 The command line is the most universal programming interface

    The software ecosystem contains many API styles and dependency management approaches, but almost every deployable service and mainstream toolchain has a command-line entry point: environment variables can be configured, arguments can be passed, standard output can be read, and success or failure can be inferred from exit codes. If every API were wrapped as a tool for an agent, maintenance costs would grow linearly with the number of tools, and the model would have to repeatedly choose among a large set of tool descriptions. The command line provides a unified adaptation surface. An agent only needs two basic capabilities—“how to run a command” and “how to interpret output”—to cover much of the software ecosystem.

    2.2 The file system is the most stable shared state

    Agent work often spans multiple steps and even multiple sessions. If all intermediate results remain in conversation history, context is quickly filled with logs, source code, and error messages. The file system provides stable, persistent, and naturally versionable storage:

    • Large content can be written to files first, then only the paths and summaries are brought back into context.
    • Code changes can be expressed precisely through diffs, making human review and rollback easier.
    • Multiple agents can collaborate through shared directories or distributed file systems, each handling subtasks and merging results into the same workspace.

    2.3 Real feedback is more reliable than “self-assessment”

    A common agent failure mode is believing that a change has been completed when it has not. Compilers, type checkers, static scanners, unit tests, and code review tools can provide objective conclusions. Agents can use this feedback to form a loop of “execute, observe, correct,” closely mirroring programmers’ daily debugging process. It is important to emphasize that whether feedback turns into improvement depends on three points: whether tools can be invoked automatically; whether output is stable and parseable; and whether failure information is sufficient to locate the problem. These points are central to the tool design discussed below.

    2.4 The workspace is the site of action; cloud and local environments share the same runtime

    An agent’s runtime can be a development machine, a cloud container instance, or a batch job with mounted shared storage. As long as the command, file, and permission models are consistent, the same agent logic can run in different environments without environment-specific adaptation. At scale, container platforms can standardize execution environments, object storage or file storage can hold workspaces and artifacts, and log services and monitoring alerts can provide a unified operational view and capacity governance.

    III. Agent Runtime Model: A Minimal Loop

    A typical terminal-based agent is essentially a loop of “model decision, tool execution, and result feedback.” The following pseudocode shows the key structure:

    1. def run_agent(goal: str, workspace: str, tools: dict, max_steps: int = 40) -> dict:
    2. # tools: tool name -> validated executable command template
    3. history = [system_prompt(goal, workspace)]
    4. for step in range(max_steps):
    5. decision = model.plan(goal, history, tool_schema(tools)) # Decide which tool to call and what arguments to pass
    6. if decision.kind == "finish":
    7. return {"status": "done", "result": decision.result}
    8. # Pre-execution confirmation: high-risk operations require user approval
    9. if decision.risk_level == "high" and not user_approved(decision):
    10. history.append({"role": "tool", "content": "The user rejected the operation. Try a safer alternative."})
    11. continue
    12. result = execute(decision, tools, cwd=workspace, timeout=120)
    13. history.append(observation(decision, result)) # Trim tool output before adding it back to avoid context bloat
    14. return {"status": "exhausted", "result": None} # Explicitly fail when steps are exhausted instead of “pretending to finish”

    Several easily overlooked details matter:

    • Step limit: An unbounded loop can consume compute endlessly when a task is unsolvable. Use observable failure instead of infinite retries.
    • Pre-execution confirmation: Operations such as deleting data, modifying production configuration, or installing dependencies should receive human confirmation before execution.
    • Timeout control: Every command should have a timeout to prevent hung processes from occupying execution resources for a long time.
    • Output trimming: Raw output is often long and should be trimmed and distilled before being fed back into context.

    IV. Tool Design Principles: Make Tools Understandable and Usable by Agents

    Tool quality directly determines the upper limit of agent capability. A well-designed tool should have the following characteristics.

    4.1 Single responsibility and self-explanatory naming

    A tool should do one thing, and its name should describe that thing. Tools named search_symbol, run_tests, or list_open_files are easier for models to select correctly than vague verbs such as analyze_project. Parameters should have clear types and enum constraints: if values can be expressed as options, do not leave them as free text.

    4.2 Stable machine-oriented output

    Human-oriented output often has loose formatting, and wording may change across versions. Agent tools need stable, parseable structures. A practical pattern is “write structured results to files and send short summaries to standard output”:

    1. # Scan project dependencies and output a report
    2. $ scan-deps --format json --out reports/deps.json
    3. Scanned 128 modules, 3 issues found. Details: reports/deps.json

    The model can obtain the conclusion from standard output and decide the next step. When details are needed, it can read the complete file using the path. If a summary needs to be viewed directly on the command line, output plain text with stable prefixes, such as line records beginning with ISSUE: <severity> <file> <line> <description>.

    4.3 Idempotent, retryable, and recoverable

    Network jitter and interrupted execution are unavoidable. Tools should ensure that repeated execution does not create extra side effects. When writing files, write to a temporary file first, then atomically replace the target file:

    1. import json, os, tempfile
    2. def write_json_atomic(path: str, data: dict) -> None:
    3. directory = os.path.dirname(os.path.abspath(path))
    4. fd, tmp_path = tempfile.mkstemp(dir=directory, prefix=".tmp-", suffix=".json")
    5. try:
    6. with os.fdopen(fd, "w", encoding="utf-8") as f:
    7. json.dump(data, f, ensure_ascii=False, indent=2)
    8. f.flush()
    9. os.fsync(f.fileno())
    10. os.replace(tmp_path, path) # Atomic replacement within the same file system
    11. except BaseException:
    12. os.unlink(tmp_path) # Clean up the temporary file on failure to avoid leaving partial output
    13. raise

    Even if execution fails midway, the agent will not read incomplete content and can retry from a deterministic state. For tasks that span multiple steps, maintain task-state files in a dedicated directory such as .agent/, recording completed steps and intermediate results so that the agent can resume from a checkpoint.

    4.4 Semantic exit codes and error messages

    Agree on clear exit codes—for example, 0 for success, 1 for business validation failure, 2 for parameter errors, and 3 for missing dependencies—and write actionable remediation suggestions to standard error. Agents can then decide whether to retry, switch approaches, or ask the user for help, rather than repeatedly guessing at expressions designed for human readers.

    V. Context Management: The Agent’s “Working Memory” Strategy

    The context window is one of the scarcest resources for an agent. The advantage of terminal-based agents is that they can retrieve information on demand rather than preloading everything. Common management strategies include:

    1. Summary first, expand on demand: Start with the directory structure and key entry files, then read specific files as needed, avoiding loading the entire codebase at once.
    2. Retrieval instead of full reading: Use symbol search to locate definitions and references instead of scanning line by line. In large repositories, retrieval can run against an independent index and only bring matching snippets into context.
    3. Persist large results: Save test logs and build outputs as files first, then let the agent extract key lines before adding them to context.
    4. Isolate subtasks: Delegate independent research or modification work to sub-agents and report only conclusions to the main agent, preventing intermediate processes from occupying main context.
    5. Compress and archive: When conversation approaches the context limit, compress history into key points such as “goal, completed actions, current state, and remaining tasks,” and write them to a summary file.

    VI. Skill Packs: Telling the Model What It Does Not Know

    6.1 What problem do skill packs solve?

    General-purpose models possess substantial public knowledge but do not know team-specific details: coding standards, directory conventions, release processes, common failure troubleshooting patterns, and historical reasons why certain logic was written in a particular way. Skill packs are structured carriers for this knowledge. Their core idea is to tell the model what it does not know. The design value of skill packs is similar to the two interaction-research efforts mentioned in the introduction: instead of introducing entirely new carriers, they organize underused information from existing carriers.

    6.2 Key elements of a high-quality skill pack

    • Applicable conditions: Explain when the skill should be used to avoid model misuse.
    • Key steps: Provide the operation order as a checklist to avoid long narrative descriptions.
    • Cautions and counterexamples: List common pitfalls and explicitly prohibited practices.
    • Executable scripts or command templates: Turn instructions directly into actions.
    • Validation criteria: Explain how to judge whether the task was completed correctly.

    A typical directory organization is as follows:

    1. .agent/skills/
    2. ├── release-checklist.md # Pre-release checks: version number, changelog, rollback plan
    3. ├── db-migration.md # Migration process: backup, staged execution, failure rollback
    4. ├── perf-troubleshooting.md # Performance troubleshooting: from monitoring metrics to call-chain localization
    5. └── scripts/
    6. └── verify-release.sh # Executable pre-release verification script

    6.3 From “a few” to “hundreds”: scaling practices

    When an organization accumulates hundreds or thousands of skill packs, the real challenge shifts from “writing” to “management”:

    • Retrieval and matching: Use description fields in file headers to indicate applicable scenarios so the agent can first judge whether to load a skill, avoiding full injection.
    • Deduplication and merging: Periodically review overlapping topics to prevent conflicting recommendations from taking effect at the same time.
    • Versioning and maintenance: Put skill packs under version control and update them as code evolves.
    • Effectiveness measurement: Build evaluation sets from typical tasks and compare completion rates and step counts with and without skill packs, using data to decide what to keep or retire.

    VII. Output Format: Markdown or HTML

    7.1 Positioning differences between the two formats

    Agent outputs are not limited to code. They also include plans, reports, review comments, and even small interactive tools. The choice of output format directly affects whether these results can be consumed efficiently.

    Dimension Markdown HTML
    Read/write cost Plain text; model generation and diffs are simple Tag structure is more complex; unclosed tags are common
    Expressiveness Headings, lists, tables, and code blocks are sufficient Supports styles, scripts, forms, and arbitrary interactions
    Portability Rendered by almost all viewers Requires a browser or compatible rendering environment
    Collaborative review Managed alongside code with clear diffs Larger size; changes are harder to review
    Security surface Smaller Requires protection against script injection and rendering of untrusted content

    Markdown itself allows embedded HTML, so the two are not mutually exclusive. A reasonable strategy is:

    • Use Markdown for static content such as plans, documentation, and changelogs.
    • Use HTML to generate a one-off tool page for interactive content, such as filterable risk lists, clickable command previews, and reports with charts.

    An example is as follows:

    1. <section class="report" id="risk-report">
    2. <h2>Dependency Risk Report</h2>
    3. <input type="search" id="filter" placeholder="Filter by module name" aria-label="Filter by module name">
    4. <ul id="risk-list">
    5. <li data-module="billing">Billing module: lockfile version differs from actual version</li>
    6. <li data-module="gateway">Gateway module: two major versions pending upgrade</li>
    7. <li data-module="search">Search module: low risk; documentation is behind</li>
    8. </ul>
    9. <pre id="cmd-preview" hidden></pre>
    10. <script>
    11. const filter = document.getElementById('filter');
    12. const items = [...document.querySelectorAll('#risk-list li')];
    13. filter.addEventListener('input', () => {
    14. const keyword = filter.value.trim().toLowerCase();
    15. items.forEach(li => {
    16. li.hidden = keyword && !li.dataset.module.includes(keyword);
    17. });
    18. });
    19. items.forEach(li => li.addEventListener('click', () => {
    20. const pre = document.getElementById('cmd-preview');
    21. pre.textContent = `$ report-detail --module ${li.dataset.module}`;
    22. pre.hidden = false;
    23. }));
    24. </script>
    25. </section>

    7.2 Security boundaries when using HTML

    • Isolated rendering: Pages should be rendered in a controlled environment, and scripts should not directly access sensitive local data.
    • Content escaping: Dynamically inserted content must be escaped to prevent external text from being treated as executable script.
    • Minimize unnecessary scripts: If functionality can be completed with static markup, avoid introducing script logic; this significantly reduces the attack surface.
    • Accessibility: Form controls should provide labels, color contrast should meet readability requirements, and interactive elements should support keyboard operation.
    • Prohibit credential exposure: Pages must not embed sensitive information such as keys or tokens.

    VIII. From Internal Tools to Product Capabilities: Release and Operations

    Once terminal-based agents serve more users, engineering problems become product and operations problems. Several key practices from engineering work are worth noting.

    8.1 Multi-platform capabilities and staged rollout

    For example, desktop voice capabilities involve microphone permissions, audio codecs, and system differences, making one-time availability to all users difficult. A common approach is “platform batches and user-group gray release”:

    1. Complete feature testing on a single operating system to validate recognition pipelines and wake-up flows.
    2. Use a feature flag to roll out to a small percentage of users, allowing immediate shutdown if anomalies occur.
    3. Expand gradually by device type, region, or activity level, while monitoring startup success rate, recognition latency, crash rate, and other metrics.
    4. Complete regression testing before full rollout and prepare a clear rollback plan.

    For platforms not yet covered, clearly state the status in the interface to reduce user expectation gaps.

    8.2 Communicating and explaining rate-limiting policies

    When resources are strained during peak periods, rate limiting is almost inevitable. More important than “whether to limit” is “how to make users understand.” Good practices include:

    • Explain quota rules and possible queuing during peak periods in advance.
    • When limits are triggered, provide clear messages and suggested alternatives, such as off-peak use or switching to a lighter-weight model.
    • Show current load on a service status page to reduce anxiety caused by uncertainty.

    8.3 Admission mechanisms for third-party extensions

    If third-party tools or plugins are allowed into the agent execution environment, permission boundaries are the prerequisite: apply the principle of least privilege to file-system and network access, maintain an audit checklist for high-risk commands, and keep complete operation audit records. For requests beyond authorized scope, the platform has the right to refuse them and explain the reason to users. This mechanism is consistent with internal management of skill packs: openness brings ecosystem vitality, while boundaries keep the system controllable.

    8.4 Asking users and confirming task boundaries

    When information is insufficient, agents should ask questions rather than guess. For example, confirming target scope, impact area, and acceptance criteria before modifications can turn “make a mistake and roll back” into “do it right before acting.” This requires structured question interfaces at the tool layer, presenting candidate options to users and bringing answers back into the task context.

    IX. Security, Reliability, and Observability

    9.1 Security: Managing risks of terminal command execution in advance

    Terminal access means agents can read and write files, install dependencies, and even call external services, which carries much higher risk than ordinary question answering. Recommended measures include:

    • Sandbox isolation: Execute in independent containers or restricted user environments and limit access to system directories.
    • Tiered authorization: Automatically execute read-only operations, require confirmation for write operations, and require explicit approval for high-risk operations.
    • Parameter validation: Normalize and whitelist-validate paths and command parameters to prevent path traversal and command injection.
    • Assume untrusted content: Treat repository, webpage, and log content as data rather than instructions to prevent prompt injection through file content from influencing agent behavior.
    • Credential protection: Distribute secrets through controlled environment injection or key management services; do not write them into workspace files or expose them in conversation history.

    9.2 Reliability: Making failures visible and reproducible

    Record the start time, exit code, duration, and output summary of every command; record the chosen tool, parameters, and observations for every model decision. With these records, production issues can be reconstructed and evaluations can be continuously iterated.

    9.3 Observability: Integrating with common cloud product categories

    In large-scale deployment, the agent runtime can be built on a container platform, workspaces and artifacts can be stored in object storage or file storage, execution logs can be aggregated into a log service, and monitoring alerts can set thresholds for metrics such as failure rate, average steps, and timeout rate. This allows teams to detect anomalies before users are affected and plan resource usage reasonably.

    X. Implementation Roadmap and Checklist

    10.1 Phased advancement

    1. Phase 1: Read-only assistant: Expose only search, reading, and explanation capabilities to validate output quality and permission models.
    2. Phase 2: Controlled writing: Allow local file modification and test execution, with all write operations reviewable and rollbackable.
    3. Phase 3: Multi-step tasks: Introduce task-state files, sub-agents, and skill packs to handle complex changes across files.
    4. Phase 4: Scale and multi-platform: Improve gray release, rate-limiting communication, audit, and metering, and expand to more terminal forms.

    10.2 Pre-launch checklist

    • Do tools have stable structured output and semantic exit codes?
    • Are write operations idempotent and using atomic writes?
    • Are step limits, timeouts, and failure fallbacks in place?
    • Do high-risk operations have confirmation and approval steps?
    • Do skill packs have applicable conditions, validation criteria, and maintenance owners?
    • Does context have summary, compression, and archival strategies?
    • Are logs and metrics sufficient to reconstruct a complete execution process?
    • Are the gray-release plan and rollback plan clear?

    XI. Conclusion

    Returning to the opening metaphor: unlocking a phone is not complex, and a deformable rod-like hardware device is not expensive. What truly creates value is deep exploration of an existing interaction carrier. The same applies to AI agents. Command lines and file systems are not new, but they provide an execution substrate that models naturally understand, with a mature tool ecosystem and objective, trustworthy feedback. Doing tool design, context management, skill accumulation, and format selection well around them often determines product success more than pursuing a single “more advanced” technical route.

    An engineer who has spent many years on terminal-based coding agents moves into frontier research after an important experience. This may also suggest that agent capabilities are still evolving rapidly, but basic judgments about interface universality, state persistence, and feedback loops remain valuable starting points to repeatedly validate when building reliable agent systems.