UditAkhourii/adhd Architecture: Main Components and Tree-of-Thought Engine

The UditAkhourii/adhd architecture comprises seven modular TypeScript components—Engine, Frames, Types, LLM Wrapper, Renderer, CLI, and Documentation—that orchestrate a five-phase tree-of-thought loop to transform problem statements into scored, clustered, and deepened ideas.

The UditAkhourii/adhd repository implements a tree-of-thought LLM orchestration system designed to break cognitive fixation through structured divergence and convergence. Its architecture separates concerns into distinct modules that handle everything from cognitive frame selection to terminal rendering, making the codebase extensible and testable.

Core Components of the UditAkhourii/adhd Architecture

The repository organizes functionality into seven primary modules. Each component owns a specific slice of the idea-generation pipeline, communicating through strict TypeScript interfaces defined in src/types.ts.

Engine

The Engine (src/engine.ts) serves as the central orchestrator, implementing the five-phase execution loop. It exposes the main run() function that coordinates the entire workflow: problem re-framing, frame selection, divergent generation, scoring, clustering, deepening, and provocation. The engine manages concurrency and aggregates RunEvent streams for real-time progress feedback.

Frames

The Frames module (src/frames.ts) maintains a curated registry of cognitive perspectives (e.g., hardware engineer, regulator, 10-year-old) and provides the selectFrames() utility. This function randomly selects a balanced subset of frames for each run, biasing toward "code" or "design" tagged entries when codeMode is enabled while guaranteeing at least one "wild" frame to ensure unconventional thinking.

Types

Types (src/types.ts) defines the domain model—including Idea, Branch, Cluster, RunResult, Score, and RunOptions—that creates type safety across the architecture. These plain TypeScript interfaces ensure that the engine, LLM wrapper, and renderer agree on data shapes when exchanging phase results.

LLM Wrapper

The LLM Wrapper (src/llm.ts) abstracts the underlying language model SDK behind callLLM() and provides JSON parsing utilities (parseJSON). It houses the system prompt templates—DIVERGE_SYSTEM, SCORE_SYSTEM, CLUSTER_SYSTEM, DEEPEN_SYSTEM, and REFRAME_SYSTEM—that instruct the model during each phase of the pipeline.

Renderer

Renderer (src/render.ts) handles human-readable output formatting through the renderText() function. It consumes a RunResult object and produces formatted terminal output with color coding, indentation levels, and "chip" style score displays for clusters and deepened ideas.

CLI

The CLI (src/cli.ts) wraps the engine as a command-line tool, exposing the adhd run command. It parses command-line flags (--frames, --topK, --codeMode), streams RunEvents to the console for progress indication, and delegates final output generation to the renderer.

Documentation

Documentation (documentation/how-it-works.md) provides the architectural rationale and algorithmic explanation, describing the philosophy behind the diverge-then-converge pattern and the "ADHD" cognitive mode.

The Five-Phase Execution Flow

Understanding how these components interact requires examining the runtime flow implemented in src/engine.ts.

Phase 0: Problem Re-framing

When stripAnchors is enabled, the engine invokes reframeProblem(), which calls the LLM with the REFRAME_SYSTEM prompt to strip implementation-specific assumptions from the input problem. This occurs in the initialization stage of the run() function.

Phase 1: Divergent Generation

The engine calls selectFrames() to choose perspective frames, then executes divergeBranch() for each selected frame. This function stitches the frame-specific prompt into DIVERGE_SYSTEM and requests ideasPerFrame short ideas from the LLM, creating parallel branches of thought.

Phase 2: Scoring and Clustering

All generated ideas undergo two critic passes:

  • scoreIdeas(): Applies the SCORE_SYSTEM prompt and calculates a weighted total using the formula novelty × 0.35 + viability × 0.4 + fit × 0.25
  • clusterIdeas(): Uses CLUSTER_SYSTEM to group semantically similar ideas into Cluster objects

These passes filter out ideas containing "traps" and produce scored, clustered data structures.

Phase 3: Deepening and Provocation

The engine shortlists the top-K highest-scoring ideas for deepenIdea(), which invokes the DEEPEN_SYSTEM prompt to generate detailed sketches and child sub-ideas. Simultaneously, it identifies the highest novelty-plus-viability idea as the nonObviousPick and formats a provocative "What if...?" question without an additional LLM call.

Finally, the populated RunResult flows to renderText() for human consumption or stdout via the CLI.

Practical Implementation Examples

Running a Session Programmatically

Import the engine and renderer directly to embed ADHD in larger applications:

import { run, renderText } from "adhd";

const result = await run({
  problem: "How can we reduce latency in our API gateway?",
  context: "Node.js, Express, 2-region AWS deployment",
  framesPerRun: 5,
  ideasPerFrame: 6,
  topK: 3,
  concurrency: 4,
  codeMode: true,
});

console.log(renderText(result));

This executes the full five-phase loop defined in src/engine.ts and returns a typed RunResult, which renderText() (exported from src/index.ts) formats into terminal-ready output.

Using the Command-Line Interface

Invoke the architecture via the CLI entry point in src/cli.ts:

npx adhd run "Enable offline-first editing for our collaborative markdown editor" \
  --frames 7 --topK 4 --codeMode false

The CLI maps flags directly onto RunOptions interfaces, streams RunEvent progress notifications (e.g., frame:start, score:done), and prints the rendered result using the same renderText() function available programmatically.

Extending the Frame Set

Add custom cognitive perspectives by manipulating the exported FRAMES array before running the engine:

import { FRAMES } from "adhd";

FRAMES.push({
  id: "quantum",
  label: "Quantum physicist",
  prompt:
    "Treat the problem as if information is encoded in qubits. What superposition-style solutions appear?",
  tags: ["design", "wild"],
});

New frames automatically participate in future runs subject to the selection logic in src/frames.ts, allowing domain-specific extensions without modifying core engine code.

Summary

  • Modular Design: The UditAkhourii/adhd architecture separates concerns into Engine, Frames, Types, LLM Wrapper, Renderer, and CLI components.
  • Tree-of-Thought Pipeline: The run() function in src/engine.ts orchestrates a five-phase flow: Re-framing, Divergence, Scoring/Clustering, Deepening, and Provocation.
  • Frame-Driven Divergence: Cognitive frames defined in src/frames.ts force perspective shifts, with selectFrames() ensuring balanced representation of technical and "wild" viewpoints.
  • Weighted Scoring: Ideas are evaluated using novelty × 0.35 + viability × 0.4 + fit × 0.25 within the scoreIdeas() pass.
  • Dual Interface: The same core engine powers both programmatic TypeScript imports and the npx adhd CLI tool.

Frequently Asked Questions

What role does the Frame component play in the ADHD architecture?

The Frames component (src/frames.ts) provides the cognitive diversity mechanism by supplying perspective prompts (e.g., viewing a problem as a regulator versus a child). The selectFrames() function ensures each run includes a mix of domain-relevant and unconventional viewpoints, which is essential for the tree-of-thought divergence phase.

How does the Engine determine which ideas to deepen?

After the scoring phase, the engine filters out ideas containing "traps" and sorts the remainder by their weighted score (combining novelty, viability, and fit). The top-K ideas from this sorted list are passed to deepenIdea() using the DEEPEN_SYSTEM prompt, while the highest-scoring novel idea becomes the nonObviousPick for provocation.

Can I use ADHD without the CLI?

Yes. The core functionality is exported from src/index.ts as a programmatic API. You can import run and renderText directly into Node.js or Deno applications, bypassing src/cli.ts entirely while still executing the full five-phase architecture.

What is the purpose of the LLM Wrapper abstraction?

The LLM Wrapper (src/llm.ts) centralizes SDK interactions and prompt management. By isolating callLLM() and JSON parsing logic, the architecture can swap underlying providers or add retry logic without modifying the Engine or Frame components, and it keeps system prompts (DIVERGE_SYSTEM, SCORE_SYSTEM, etc.) version-controlled alongside the code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →