Skip to content

Index

Functions

planSmartStructure

async function planSmartStructure(elements: APIElement[], client: LLMClient): Promise<DocStructure>
TypeScript

Use planSmartStructure to let an LLM analyze your extracted API elements and propose a logical documentation layout — grouping related concepts, ordering topics by importance, and surfacing structure that would take hours to plan manually.

Reach for this when you've scanned a codebase with skrypt and have a flat list of APIElement objects that need to be organized before writing docs. It sits between the scanning step and the generation step: scan → plan structure → generate MDX.

It first runs a topology analysis on your elements to understand relationships and dependencies between them, then passes that graph to the LLM to produce a DocStructure — a hierarchical plan of topics, sections, and which elements belong where.

Parameters

NameTypeRequiredDescription
elementsAPIElement[]YesThe API elements extracted from your source scan. An empty array will return a minimal structure with no topics.
clientLLMClientYesA configured LLM client (e.g. OpenAI, Anthropic) that skrypt uses to reason about groupings. The quality of the structure depends on the model — use GPT-4 class or better for non-trivial codebases.

Returns

Returns a DocStructure describing how your docs should be organized — topics, their display order, and which APIElement IDs belong to each. Pass this directly to your generation step (e.g. generateForElements) to produce MDX files that follow the planned layout rather than mirroring your file system.

Heads up

  • This makes LLM API calls proportional to the number of elements — for large codebases (500+ elements), expect latency and token costs to be significant. Consider batching or filtering elements before calling.
  • The returned structure is a proposal, not a contract. You can mutate it before passing it downstream if the LLM's groupings don't match your preferences.

Example:

type APIElement = {
  id: string
  name: string
  kind: "function" | "class" | "interface" | "type"
  signature: string
  description: string
  filePath: string
}

type DocTopic = {
  title: string
  slug: string
  order: number
  elementIds: string[]
}

type DocStructure = {
  topics: DocTopic[]
  ungrouped: string[]
}

type LLMClient = {
  complete: (prompt: string) => Promise<string>
}

// --- Minimal mock implementations ---

function analyzeTopology(elements: APIElement[]) {
  return { elementCount: elements.length, clusters: [] }
}

async function planStructure(
  elements: APIElement[],
  topology: ReturnType<typeof analyzeTopology>,
  client: LLMClient
): Promise<DocStructure> {
  const prompt = `Given ${topology.elementCount} API elements, propose documentation topics as JSON.`
  const raw = await client.complete(prompt)
  return JSON.parse(raw) as DocStructure
}

async function planSmartStructure(
  elements: APIElement[],
  client: LLMClient
): Promise<DocStructure> {
  const topology = analyzeTopology(elements)
  return planStructure(elements, topology, client)
}

// --- Mock LLM client (replace with real OpenAI/Anthropic client) ---
const mockLLMClient: LLMClient = {
  complete: async (_prompt: string) => {
    return JSON.stringify({
      topics: [
        {
          title: "Authentication",
          slug: "authentication",
          order: 1,
          elementIds: ["elem_001", "elem_002"],
        },
        {
          title: "Payments",
          slug: "payments",
          order: 2,
          elementIds: ["elem_003"],
        },
      ],
      ungrouped: [],
    })
  },
}

const scannedElements: APIElement[] = [
  {
    id: "elem_001",
    name: "createSession",
    kind: "function",
    signature: "function createSession(userId: string): Promise<Session>",
    description: "Creates an authenticated session for a user.",
    filePath: "src/auth/session.ts",
  },
  {
    id: "elem_002",
    name: "revokeToken",
    kind: "function",
    signature: "function revokeToken(token: string): Promise<void>",
    description: "Invalidates an existing auth token.",
    filePath: "src/auth/tokens.ts",
  },
  {
    id: "elem_003",
    name: "createCharge",
    kind: "function",
    signature: "function createCharge(amount: number, currency: string): Promise<Charge>",
    description: "Creates a new payment charge.",
    filePath: "src/payments/charge.ts",
  },
]

async function main() {
  try {
    const structure = await planSmartStructure(scannedElements, mockLLMClient)

    console.log(`Planned ${structure.topics.length} topics:`)
    for (const topic of structure.topics) {
      console.log(`  [${topic.order}] ${topic.title} (${topic.elementIds.length} elements)`)
    }
    console.log(`Ungrouped elements: ${structure.ungrouped.length}`)

    // Expected output:
    // Planned 2 topics:
    //   [1] Authentication (2 elements)
    //   [2] Payments (1 elements)
    // Ungrouped elements: 0
  } catch (err) {
    console.error("Failed to plan structure:", err)
  }
}

main()
TypeScript

generateWithStructure

async function generateWithStructure(structure: DocStructure, client: LLMClient, outputPath: string, options: GenerationOptions): Promise<{ filesWritten: number; totalDocs: number; docs: GeneratedDoc[] }>
TypeScript

Use generateWithStructure to turn a planned documentation structure into fully written MDX files on disk, with AI-generated descriptions and code examples for every API element.

Reach for this after you've built a DocStructure — typically from planDocStructure — and you're ready to produce the final output. It's the last step in the generation pipeline: it takes the blueprint and writes real files.

generateWithStructure walks the structure's topics and elements, calls the LLM to generate prose and examples for each one, then writes MDX files to outputPath organized by topic. Files are created (and directories are made) automatically.

Parameters

NameTypeRequiredDescription
structureDocStructureYesThe topic-organized plan of your API surface — produced by planDocStructure. Determines which elements get documented and how they're grouped into files.
clientLLMClientYesThe configured LLM client used to generate descriptions and code examples. Controls which model and provider handles the writing.
outputPathstringYesDirectory where MDX files are written. Subdirectories are created per topic. Use an absolute path or one relative to your working directory.
optionsGenerationOptionsYesControls generation behavior — including whether to produce multi-language examples, overwrite existing files, and which languages to target.

Returns

Returns a promise that resolves to a result object. filesWritten tells you how many MDX files landed on disk. totalDocs is the count of individual API elements documented. docs is the full array of GeneratedDoc objects — each containing the element's name, generated markdown, and code examples — useful for post-processing or logging.

Heads up

  • outputPath must be writable. If the directory doesn't exist, it's created — but if a parent directory is missing and can't be created, the call will throw.
  • Generation is LLM-bound: for large structures, this can take tens of seconds. Consider batching or running this in a background job rather than in a request handler.

Example:

// Inline types — do not import from autodocs
type APIElement = {
  name: string;
  signature: string;
  docstring: string;
  filePath: string;
  language: "typescript" | "python" | "go" | "rust";
};

type DocTopic = {
  name: string;
  slug: string;
  elements: APIElement[];
};

type DocStructure = {
  topics: DocTopic[];
  projectName: string;
};

type GeneratedDoc = {
  elementName: string;
  markdown: string;
  codeExample: string;
};

type GenerationOptions = {
  multiLang: boolean;
  overwrite: boolean;
  targetLanguages: string[];
};

type LLMClient = {
  provider: string;
  model: string;
  apiKey: string;
};

// Mock implementation of generateWithStructure
async function generateWithStructure(
  structure: DocStructure,
  client: LLMClient,
  outputPath: string,
  options: GenerationOptions
): Promise<{ filesWritten: number; totalDocs: number; docs: GeneratedDoc[] }> {
  const docs: GeneratedDoc[] = [];

  for (const topic of structure.topics) {
    for (const element of topic.elements) {
      docs.push({
        elementName: element.name,
        markdown: `## ${element.name}\n\n${element.docstring}`,
        codeExample: `// Example for ${element.name}\nconsole.log("${element.name} called");`,
      });
    }
  }

  return {
    filesWritten: structure.topics.length,
    totalDocs: docs.length,
    docs,
  };
}

// --- Usage ---

const structure: DocStructure = {
  projectName: "payments-sdk",
  topics: [
    {
      name: "Authentication",
      slug: "authentication",
      elements: [
        {
          name: "createApiKey",
          signature: "function createApiKey(userId: string): Promise<string>",
          docstring: "Creates a scoped API key for the given user.",
          filePath: "src/auth/keys.ts",
          language: "typescript",
        },
        {
          name: "revokeApiKey",
          signature: "function revokeApiKey(keyId: string): Promise<void>",
          docstring: "Permanently revokes an API key.",
          filePath: "src/auth/keys.ts",
          language: "typescript",
        },
      ],
    },
    {
      name: "Payments",
      slug: "payments",
      elements: [
        {
          name: "chargeCard",
          signature: "function chargeCard(amount: number, token: string): Promise<Charge>",
          docstring: "Charges a payment method and returns the resulting charge object.",
          filePath: "src/payments/charge.ts",
          language: "typescript",
        },
      ],
    },
  ],
};

const client: LLMClient = {
  provider: "openai",
  model: "gpt-4o",
  apiKey: "sk-proj-a1b2c3d4e5f6g7h8i9j0",
};

const options: GenerationOptions = {
  multiLang: true,
  overwrite: false,
  targetLanguages: ["typescript", "python"],
};

async function main() {
  try {
    const result = await generateWithStructure(
      structure,
      client,
      "/projects/payments-sdk/docs/content",
      options
    );

    console.log(`Files written: ${result.filesWritten}`);
    console.log(`Total docs generated: ${result.totalDocs}`);
    console.log(`First doc preview:\n${result.docs[0].markdown}`);

    // Expected output:
    // Files written: 2
    // Total docs generated: 3
    // First doc preview:
    // ## createApiKey
    //
    // Creates a scoped API key for the given user.
  } catch (err) {
    console.error("Documentation generation failed:", err);
  }
}

main();
TypeScript
Was this helpful?