← Back to Blog
AI/ML2026-05-13Β·85 min read

How I Documented an Entire Product in 4 Days with an AI Agent

By Debbie O'Brien

Automating Technical Documentation with Persistent AI Skills and OS-Level Capture

Current Situation Analysis

Documentation debt is rarely a writing problem. It is a synchronization problem. As engineering teams ship features at velocity, user-facing documentation inevitably drifts from the actual product state. Screenshots become stale, voice tone fractures across multiple contributors, and internal implementation details leak into user guides. The industry treats documentation as a static deliverable rather than a living artifact, which is why most teams resort to manual updates that cannot keep pace with continuous deployment cycles.

This gap is frequently misunderstood. Many engineering leaders assume that introducing large language models into the documentation workflow will automatically solve the problem. In practice, unstructured prompting leads to inconsistent formatting, hallucinated UI states, and asset rot. The real bottleneck is not content generation; it is maintaining deterministic style rules, automating visual asset capture, and enforcing validation gates without halting development velocity.

Data from recent desktop application releases demonstrates the scale of the challenge. A typical mid-sized product requires approximately 50–60 documentation pages and 50–70 contextual screenshots before launch. Manually producing this volume takes three to four weeks of dedicated technical writing time, plus additional cycles for UI changes, image optimization, and cross-linking. When the product is built on frameworks like Tauri or Electron, the complexity increases further: native webviews do not expose standard browser DevTools, making traditional browser automation ineffective. Teams that attempt to force browser-based tools into desktop workflows spend disproportionate time fighting window chrome, IPC routing, and authentication boundaries.

The solution requires shifting from ad-hoc prompting to persistent instruction architectures, paired with OS-level automation for asset management. By codifying style rules into machine-readable skill files and routing screenshot capture through accessibility APIs rather than browser protocols, teams can compress a multi-week documentation cycle into a tightly controlled, four-day execution window with over 80 commits tracking incremental validation.

WOW Moment: Key Findings

The most significant insight from production documentation automation is that the choice of capture layer dictates the entire maintenance strategy. Browser automation fails for desktop applications, while OS-level automation introduces screen takeover constraints. The trade-off matrix below compares the three primary approaches used in modern documentation pipelines.

Approach Desktop Compatibility Asset Maintenance Review Overhead Execution Risk
Manual Capture High High (manual crop/optimize) High Low
Browser Automation (Playwright/Puppeteer) Low (Tauri/Electron webviews) Medium Medium Medium (IPC/DevTools conflicts)
OS-Level AI-Assisted (Peekaboo + Vision + Pillow) High Low (automated OCR/highlight/compress) Low Medium (screen takeover during batch)

This finding matters because it redefines how documentation pipelines should be architected. Browser automation is optimized for stateless web routing, but desktop applications manage state through native bridges and window managers. OS-level capture bypasses the webview entirely, interacting with the application as an end-user would. When combined with persistent AI instruction files, this approach eliminates voice drift, automates image optimization, and reduces manual review to structural validation rather than line-by-line editing. The result is a documentation system that updates alongside the product, not after it.

Core Solution

Building a production-ready documentation automation pipeline requires three architectural layers: persistent instruction files, OS-level asset capture, and phased execution gates. Each layer addresses a specific failure mode in traditional documentation workflows.

Step 1: Codify Style Rules into Persistent Skill Files

Large language models lack inherent consistency across sessions. Prompting the same style rules repeatedly introduces drift, especially when multiple engineers or agents contribute to the same repository. The solution is to externalize style guidelines into markdown-based instruction files that the agent loads before every generation cycle.

These files function as deterministic contracts. They define voice parameters, formatting conventions, structural templates, and explicit exclusion rules. Instead of embedding instructions in prompts, they are version-controlled alongside the documentation source. When a convention changes, updating the skill file propagates the rule to all future sessions without requiring prompt engineering.

// skill-loader.ts
import { readFileSync } from 'fs';
import { join } from 'path';

interface StyleContract {
  voice: string[];
  formatting: Record<string, string>;
  structure: string[];
  exclusions: string[];
  validation: string[];
}

export function loadDocumentationSkill(skillPath: string): StyleContract {
  const raw = readFileSync(join(process.cwd(), skillPath), 'utf-8');
  
  const contract: StyleContract = {
    voice: [],
    formatting: {},
    structure: [],
    exclusions: [],
    validation: []
  };

  const sections = raw.split(/^## /m).filter(Boolean);
  
  for (const section of sections) {
    const [header, ...content] = section.split('\n');
    const key = header.trim().toLowerCase().replace(/\s+/g, '_');
    
    if (key === 'voice_and_tone') {
      contract.voice = content.filter(l => l.startsWith('- ')).map(l => l.slice(2));
    } else if (key === 'formatting_rules') {
      content.filter(l => l.includes(':')).forEach(l => {
        const [k, v] = l.split(':').map(s => s.trim());
        contract.formatting[k] = v;
      });
    } else if (key === 'page_structure') {
      contract.structure = content.filter(l => l.startsWith('- ')).map(l => l.slice(2));
    } else if (key === 'exclusions') {
      contract.exclusions = content.filter(l => l.startsWith('- ')).map(l => l.slice(2));
    } else if (key === 'validation_checklist') {
      contract.validation = content.filter(l => l.startsWith('- ')).map(l => l.slice(2));
    }
  }

  return contract;
}

Architecture Rationale: Markdown is chosen over JSON or YAML because it remains human-readable, diff-friendly, and compatible with existing documentation toolchains. The loader parses sections into a typed contract that the agent references during generation. This eliminates prompt drift and ensures every page adheres to the same structural baseline.

Step 2: Build an OS-Level Capture Pipeline

Desktop applications built on Tauri or Electron render UI inside native webviews. Browser automation tools cannot reliably interact with these environments because routing, state management, and window chrome are handled by the host OS, not the browser engine. The correct approach is to interact with the application at the operating system level using accessibility APIs and screen coordinate mapping.

The pipeline follows a deterministic sequence: window focus, retina capture, OCR text extraction, visual annotation, and lossless compression. Each step is isolated into a dedicated module to prevent cross-contamination of state.

// capture-engine.ts
import { execSync } from 'child_process';
import { writeFileSync, existsSync } from 'fs';

interface CaptureConfig {
  appName: string;
  targetText: string;
  outputDir: string;
  compressionLevel: number;
}

export async function executeCaptureCycle(config: CaptureConfig): Promise<string> {
  const { appName, targetText, outputDir, compressionLevel } = config;
  const timestamp = Date.now();
  const rawPath = `${outputDir}/raw_${timestamp}.png`;
  const annotatedPath = `${outputDir}/annotated_${timestamp}.png`;
  const finalPath = `${outputDir}/final_${timestamp}.png`;

  // 1. Focus application window via OS accessibility layer
  execSync(`peekaboo focus --app "${appName}"`);
  
  // 2. Navigate to target state using visible text matching
  execSync(`peekaboo click --text "${targetText}"`);
  
  // 3. Capture retina resolution without window shadows
  execSync(`peekaboo capture --retina --output "${rawPath}"`);
  
  // 4. Run Vision OCR to extract bounding boxes
  const ocrResult = execSync(`swift run vision-ocr --input "${rawPath}" --json`).toString();
  const boxes = JSON.parse(ocrResult);
  
  // 5. Generate highlight overlay using Pillow
  execSync(`python3 highlight-renderer.py --input "${rawPath}" --boxes "${JSON.stringify(boxes)}" --output "${annotatedPath}"`);
  
  // 6. Compress with pngquant + optipng
  execSync(`pngquant --force --speed 1 --output "${finalPath}" "${annotatedPath}"`);
  execSync(`optipng -o2 "${finalPath}"`);

  return finalPath;
}

Architecture Rationale: The pipeline avoids hardcoded coordinates by relying on OCR-driven text detection. This makes the capture process resilient to UI layout changes. Compression is applied in two stages: pngquant reduces color depth perceptually, while optipng performs lossless deflation. This combination typically reduces file size by 50–60% without visible degradation. The entire sequence is wrapped in a TypeScript orchestrator to maintain type safety and enable integration with existing build systems.

Step 3: Implement Phased Execution Gates

Fully autonomous documentation generation introduces unacceptable risk. UI changes, feature flags, and incomplete workflows can cause the agent to document non-existent states or expose internal implementation details. The solution is a phased execution model with explicit commit gates.

Each phase targets a specific documentation tier: onboarding, daily workflows, advanced features, configuration panels, and final polish. After each phase completes, the agent pauses for human review. Reviewers validate structural consistency, verify screenshot accuracy, and confirm that exclusion rules were respected. Only after approval does the pipeline advance to the next phase.

This approach transforms documentation from a monolithic deliverable into a continuous integration artifact. Commits are atomic, rollbacks are trivial, and voice consistency is enforced through the persistent skill file rather than manual editing.

Pitfall Guide

1. Full Autonomy Without Checkpoints

Explanation: Allowing the agent to generate all documentation in a single unattended session leads to compounding errors. Early mistakes propagate through later phases, requiring complete rewrites. Fix: Enforce phase boundaries with explicit commit gates. Review output after each tier before advancing.

2. Browser Automation for Desktop Applications

Explanation: Tools like Playwright or Puppeteer expect standard DOM routing and browser DevTools. Desktop webviews manage state through native IPC bridges, causing automation scripts to fail or capture incomplete UI states. Fix: Use OS-level accessibility APIs (Peekaboo, AppleScript, or Windows UI Automation) to interact with the application as an end-user would.

3. Hardcoded UI Coordinates

Explanation: Capturing screenshots using fixed pixel coordinates breaks immediately when layouts shift, responsive breakpoints change, or localization alters text length. Fix: Implement OCR-driven bounding box detection. Let the pipeline locate elements by visible text rather than position.

4. Unoptimized Image Assets

Explanation: Raw retina screenshots average 2–4 MB each. Shipping 50+ unoptimized images bloats documentation bundles, increases build times, and degrades reader load performance. Fix: Integrate a two-stage compression pipeline (pngquant + optipng) that reduces file size by 50–60% while preserving visual fidelity.

5. Voice and Formatting Drift

Explanation: Repeating style instructions in every prompt introduces subtle variations. Over time, documentation fragments into multiple tones, inconsistent heading hierarchies, and mixed formatting conventions. Fix: Externalize style rules into version-controlled skill files. Load the contract before every generation cycle to enforce deterministic output.

6. Screen Takeover During Batch Execution

Explanation: OS-level capture requires the target window to remain in focus. Running batch captures on a primary workstation interrupts workflow and risks input collisions that break the pipeline. Fix: Schedule captures during off-hours, use dedicated CI runners with virtual displays, or isolate the process in a lightweight VM.

7. Over-Documenting Internal State

Explanation: Agents trained on source code frequently leak implementation details, API schemas, or feature flags into user-facing guides. This confuses end-users and exposes internal architecture. Fix: Define explicit exclusion rules in the skill file. Validate output against a "user vs developer" boundary checklist before committing.

Production Bundle

Action Checklist

  • Initialize persistent skill file: Create a markdown contract defining voice, formatting, structure, and exclusions. Version control it alongside documentation source.
  • Configure OS-level capture pipeline: Install Peekaboo, Vision OCR bindings, Pillow, and compression tools. Verify window focus and text-click routing.
  • Establish phased execution gates: Divide documentation into onboarding, daily use, advanced features, settings, and polish. Commit after each phase.
  • Implement validation checklist: Add automated checks for dead links, image registration, formatting compliance, and exclusion rule adherence.
  • Optimize asset pipeline: Integrate pngquant and optipng into the capture workflow. Verify compression ratios and visual fidelity.
  • Schedule batch captures: Run full recaptures during off-hours or on isolated runners to prevent screen takeover conflicts.
  • Audit for undocumented surfaces: Perform a screen-by-screen sweep post-launch to identify missing panels, embedded browsers, or configuration pages.

Decision Matrix

Scenario Recommended Approach Why Cost Impact
Web-only SaaS Browser automation (Playwright) Standard DOM routing, DevTools access, stateless sessions Low infrastructure, moderate maintenance
Tauri/Electron Desktop OS-level capture (Peekaboo + Vision) Native webviews bypass browser protocols, IPC state management Medium setup, low long-term maintenance
CLI/Headless Tools Log parsing + terminal recording No GUI to capture, output is text-based Low cost, high accuracy
Multi-platform (macOS/Windows/Linux) Hybrid pipeline with OS dispatch Accessibility APIs differ per platform; requires conditional routing High initial cost, scalable long-term

Configuration Template

# doc-standards.md
## Voice and Tone
- Direct and confident. Use imperative mood for actions.
- Avoid hedging language ("you may want to", "consider clicking").
- Maintain consistent terminology across all sections.

## Formatting Rules
- Bold for interactive UI elements.
- Italics for static text or labels.
- Code backticks for commands, paths, or typed input.
- No emojis, em dashes, or decorative punctuation.

## Page Structure
- Frontmatter with title, description, and tags.
- Single H1 matching page title.
- One concept per paragraph. Lead with the action.
- Include screenshot callouts immediately after relevant steps.
- Cross-link to related configuration or troubleshooting pages.

## Exclusions
- Internal API schemas, CRDT structures, or adapter formats.
- Feature flags, experimental toggles, or developer-only workflows.
- Implementation details, error stack traces, or debug logs.

## Validation Checklist
- [ ] All UI elements bolded correctly.
- [ ] Screenshots registered in manifest and compressed.
- [ ] No internal implementation details present.
- [ ] Build passes with zero dead links.
- [ ] Voice matches contract parameters.

Quick Start Guide

  1. Install dependencies: brew install peekaboo pngquant optipng and install Python Pillow + Swift Vision bindings.
  2. Initialize skill contract: Copy the configuration template into docs/skills/doc-standards.md and adjust voice/formatting rules to match your product.
  3. Run first capture: Execute ts-node capture-engine.ts --app "YourApp" --text "Settings" --output ./docs/assets. Verify OCR bounding boxes and compression output.
  4. Generate documentation: Load the skill file into your AI agent, specify the target phase (e.g., "Phase 1: Getting Started"), and execute. Review output against the validation checklist before committing.