Skip to main content
Devansh Singh
Case Study

AI Bot

Agentic LLM Workspace Controller & Background Worker

Node.jsTypeScriptGemini APIShellJSZsh Hooks
The Problem

Engineering Context & Problem Statement

Software developers spend hours daily executing repetitive terminal rituals—switching branches, staging specific diff chunks, organizing scratch directories, and checking background build outputs. Existing assistant UIs require copy-pasting terminal output back and forth.

The Solution

System Architecture & Implementation Strategy

Built AI Bot, a lightweight background assistant that connects directly to the developer's shell environment. Using strict function-calling schemas, the model can inspect repository statuses, execute sandboxed terminal commands, and perform file operations autonomously with human approval safeguards.

System Pipeline & Data Flow
Pipeline Flow
Developer Shell Prompt -> Context Collector -> LLM Agent Engine -> Function Call Parser -> Sandbox Safety Filter -> Subprocess Execution -> Shell Feedback

A daemon monitors terminal events and user prompts. When triggered, it constructs a prompt incorporating current working directory context, queries the LLM with declared tool signatures, validates proposed operations, and executes vetted commands via a controlled process runner.

Overview

AI Bot bridges the gap between natural language developer intent and command-line execution. It operates directly within your terminal workspace, translating high-level workflows like "organize my downloads into date-based project folders and commit changed markdown documents" into structured, verifiable tool executions.

// Autonomous agentic execution loop with tool call validation
export async function runAgentLoop(prompt: string, tools: FunctionDeclaration[]) {
  const model = genAI.getGenerativeModel({ model: "gemini-1.5-pro" });
  let chat = model.startChat({ tools: [{ functionDeclarations: tools }] });
  
  let result = await chat.sendMessage(prompt);
  const call = result.response.functionCalls?.[0];
  
  if (call) {
    // Validate safety constraint before executing shell command
    verifyCommandSafety(call.name, call.args);
    const toolResult = await executeTool(call.name, call.args);
    result = await chat.sendMessage([
      { functionResponse: { name: call.name, response: toolResult } }
    ]);
  }
  
  return result.response.text;
}
Architectural Trade-offs

Key Architectural Decisions

  • 01Enforced strict tool schemas with mandatory confirmation prompts for irreversible git or filesystem operations.
  • 02Implemented chunked diff summarization to preserve prompt tokens when inspecting large Git working trees.
  • 03Built hooks into Zsh environment rather than requiring a dedicated heavy Electron UI application.

Technical Challenges Overcome

  • !1Preventing destructive command execution (e.g., unintended deletions or force pushes) through strict permission gating.
  • !2Handling long-running asynchronous subprocess outputs without hanging the agent loop.
  • !3Minimizing token usage when reading large terminal logs and file diffs.

What I Learned

  • Agentic loops require robust retry logic and deterministic tool schemas; open-ended free text commands fail on edge cases.
  • Developers strongly prefer fast, non-blocking background daemons over intrusive GUI overlays.

Related Writing & Technical Essays