As projects grow, documentation inevitably falls out of sync with the actual code. Manually updating docs is a losing battle — sooner or later, the codebase becomes the only source of truth, and onboarding new team members turns into an archaeological expedition.
Here we build a documentation generation pipeline on top of Antigravity's AI agent capabilities. It produces API references, architecture overviews, and README files straight from your codebase, then keeps them current through CI/CD automation. The material assumes you are already comfortable with TypeScript and modern development workflows.
Prerequisites
Before diving in, make sure you have the following set up:
- Antigravity IDE (latest version)
- Node.js 20+
- A TypeScript project with JSDoc/TSDoc annotations
- A GitHub repository (for CI/CD integration)
Start by installing the documentation tooling:
# Install documentation generation tools
npm install -D typedoc typedoc-plugin-markdown unified remark-parse remark-stringifyAnalyzing Your Codebase with AI Agents
Antigravity's agent system understands your entire project structure, giving it a significant edge over regex-based doc generators. It can infer intent, explain design decisions, and produce human-readable summaries that static tools simply can't match.
Defining a Doc Generator Agent in agents.md
Create an agents.md file at the project root to define a dedicated documentation agent:
# Doc Generator Agent
## Role
Analyze the codebase and generate technical documentation.
## Instructions
1. Scan all .ts files under src/
2. Extract JSDoc/TSDoc comments from exported functions, classes, and types
3. Generate Markdown documentation in the following format:
- Use function/class names as headings
- List parameters with types and descriptions in a table
- Include return type and description
- Add code examples where available
4. Place generated documentation in the docs/ directory
## Context
- TypeScript project
- Output format: Markdown
- If existing documentation exists, update only the changed sectionsPairing with TypeDoc for Structured Analysis
AI-generated prose works best when paired with TypeDoc's precise type extraction. Here's a script that handles the structured side:
// scripts/generate-docs.ts
import { Application, TSConfigReader } from "typedoc";
import * as fs from "fs";
import * as path from "path";
interface DocEntry {
name: string;
kind: string;
description: string;
parameters?: { name: string; type: string; description: string }[];
returnType?: string;
example?: string;
}
async function generateDocs(): Promise<void> {
const app = await Application.bootstrapWithPlugins({
entryPoints: ["src/index.ts"],
plugin: ["typedoc-plugin-markdown"],
tsconfig: "tsconfig.json",
});
app.options.addReader(new TSConfigReader());
const project = await app.convert();
if (!project) {
console.error("TypeDoc conversion failed");
process.exit(1);
}
// Output as Markdown
const outputDir = path.resolve("docs/api");
await app.generateDocs(project, outputDir);
console.log(`✅ API documentation generated at ${outputDir}`);
// Report generated file count
const files = fs.readdirSync(outputDir, { recursive: true });
const mdFiles = (files as string[]).filter((f) => f.endsWith(".md"));
console.log(`📄 Generated ${mdFiles.length} documentation files`);
}
generateDocs().catch(console.error);Expected output:
✅ API documentation generated at /project/docs/api
📄 Generated 24 documentation files
Generating READMEs and Architecture Docs with AI
TypeDoc excels at API reference generation, but producing readable READMEs and architecture documents requires the contextual understanding that AI provides.
Using Antigravity's Inline Chat
Press Cmd + I (inline chat) in Antigravity and use a prompt like this to generate a project-aware README:
Generate a README.md for this project with the following sections:
- Project overview (reference package.json description)
- Installation
- Usage (include examples of the main API)
- Directory structure
- Development setup
- Running tests
- License
Batch-Generating Per-Directory READMEs
For large projects, you may need a README in each module directory. Here's a script that automates this:
// scripts/generate-module-readmes.ts
import * as fs from "fs";
import * as path from "path";
interface ModuleInfo {
dirPath: string;
files: string[];
exports: string[];
dependencies: string[];
}
function analyzeModule(dirPath: string): ModuleInfo {
const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".ts"));
const exports: string[] = [];
const dependencies: string[] = [];
for (const file of files) {
const content = fs.readFileSync(path.join(dirPath, file), "utf-8");
// Extract export statements
const exportMatches = content.matchAll(
/export\s+(?:default\s+)?(?:function|class|const|type|interface)\s+(\w+)/g
);
for (const match of exportMatches) {
exports.push(match[1]);
}
// Extract dependencies from import statements
const importMatches = content.matchAll(/from\s+["']([^"']+)["']/g);
for (const match of importMatches) {
if (!match[1].startsWith(".")) {
dependencies.push(match[1]);
}
}
}
return { dirPath, files, exports, dependencies: [...new Set(dependencies)] };
}
function generateReadme(info: ModuleInfo): string {
const moduleName = path.basename(info.dirPath);
return `# ${moduleName}
## Overview
This module contains ${info.files.length} file(s) and exports ${info.exports.length} symbol(s).
## Exports
${info.exports.map((e) => `- \`${e}\``).join("\n")}
## Files
${info.files.map((f) => `- \`${f}\``).join("\n")}
## Dependencies
${info.dependencies.length > 0 ? info.dependencies.map((d) => `- \`${d}\``).join("\n") : "No external dependencies."}
`;
}
// Process each directory under src/
const srcDir = path.resolve("src");
const dirs = fs
.readdirSync(srcDir, { withFileTypes: true })
.filter((d) => d.isDirectory())
.map((d) => path.join(srcDir, d.name));
for (const dir of dirs) {
const info = analyzeModule(dir);
if (info.files.length > 0) {
const readme = generateReadme(info);
fs.writeFileSync(path.join(dir, "README.md"), readme);
console.log(`📝 Generated README for ${path.basename(dir)}`);
}
}Integrating with CI/CD
Running doc generation manually defeats the purpose. Let's wire it into GitHub Actions so documentation stays current with every code change.
GitHub Actions Workflow
# .github/workflows/docs.yml
name: Generate Documentation
on:
push:
branches: [main]
paths:
- "src/**/*.ts"
- "scripts/generate-docs.ts"
jobs:
generate-docs:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install dependencies
run: npm ci
- name: Generate API documentation
run: npx ts-node scripts/generate-docs.ts
- name: Generate module READMEs
run: npx ts-node scripts/generate-module-readmes.ts
- name: Check for changes
id: check
run: |
git diff --quiet docs/ || echo "changed=true" >> $GITHUB_OUTPUT
- name: Commit and push
if: steps.check.outputs.changed == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add docs/
git commit -m "docs: auto-update documentation"
git pushDrift Detection and Alerts
It's also useful to get notified when documentation drift exceeds a certain threshold:
// scripts/check-doc-drift.ts
import { execSync } from "child_process";
// Get the number of changed lines since the last doc generation
const diff = execSync("git diff --stat docs/").toString();
const lines = diff.split("\n");
const summaryLine = lines[lines.length - 2] || "";
// Parse "N files changed, N insertions(+), N deletions(-)"
const match = summaryLine.match(/(\d+)\s+file.*?(\d+)\s+insertion.*?(\d+)\s+deletion/);
if (match) {
const [, files, insertions, deletions] = match;
const totalChanges = parseInt(insertions) + parseInt(deletions);
console.log(`📊 Documentation drift report:`);
console.log(` Files changed: ${files}`);
console.log(` Lines added: ${insertions}`);
console.log(` Lines removed: ${deletions}`);
// Warn if changes are substantial
if (totalChanges > 100) {
console.warn(`⚠️ Large documentation drift detected (${totalChanges} lines)`);
console.warn(` Consider reviewing the generated documentation manually.`);
process.exit(1);
}
}Advanced: Custom Templates for Doc Generation
When your project has specific documentation standards, you can combine template engines with AI output for flexible, branded documentation:
// scripts/custom-template.ts
interface TemplateContext {
projectName: string;
version: string;
modules: {
name: string;
description: string;
functions: {
name: string;
signature: string;
description: string;
}[];
}[];
}
function renderTemplate(template: string, context: TemplateContext): string {
let result = template;
// Replace basic variables
result = result.replace(/\{\{projectName\}\}/g, context.projectName);
result = result.replace(/\{\{version\}\}/g, context.version);
// Render module sections
const moduleSection = context.modules
.map(
(mod) => `
### ${mod.name}
${mod.description}
| Function | Signature | Description |
|----------|-----------|-------------|
${mod.functions.map((fn) => `| \`${fn.name}\` | \`${fn.signature}\` | ${fn.description} |`).join("\n")}
`
)
.join("\n");
result = result.replace(/\{\{modules\}\}/g, moduleSection);
return result;
}
// Usage example
const context: TemplateContext = {
projectName: "MyProject",
version: "1.0.0",
modules: [
{
name: "auth",
description: "Authentication module",
functions: [
{
name: "login",
signature: "(email: string, password: string) => Promise<User>",
description: "Handles user login",
},
{
name: "logout",
signature: "() => Promise<void>",
description: "Terminates the current session",
},
],
},
],
};
const template = `# {{projectName}} v{{version}} API Reference\n\n{{modules}}`;
console.log(renderTemplate(template, context));Wrapping Up
In this guide, we built a complete documentation generation pipeline that combines Antigravity's AI agents with TypeDoc for type-safe, human-readable technical documentation.
The key takeaways are threefold. First, define a dedicated doc generation agent in agents.md to leverage Antigravity's project-wide understanding for producing natural, contextual documentation. Second, pair AI output with TypeDoc — let TypeDoc handle precise type extraction while the AI focuses on writing clear explanations and usage examples. Third, wire everything into CI/CD with GitHub Actions so documentation updates automatically with every code change, eliminating the drift that plagues most projects.
Great documentation is a force multiplier for your team. By automating the heavy lifting, you free up time to focus on what matters — writing code that's worth documenting in the first place.