JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 82
  • Score
    100M100P100Q86428F
  • License MIT

TS Knowledge Base. A TypeScript-native DSL for expressing architectural intent as typed declarations. Produces renderable docs/diagrams and a queryable knowledge graph, supporting type-checked snippet references, semantic relations, and constraints.

Package Exports

  • tskb
  • tskb/jsx-runtime

Readme

tskb

Build architecture docs as code. Declaratively define architectural intent in large TypeScript codebases and monorepos, and turn that intent into a compiler-verified artifact.

Documentation physically bound to your code, so you can trust it.

npm version License: MIT


⚠️ Status

Experimental / early concept.

  • APIs and output may evolve
  • Not production-ready
  • Best viewed as a proof-of-concept and research tool

What is tskb?

tskb is a TypeScript-native DSL for expressing architectural intent as code.

You write documentation in .tskb.tsx files that:

  • are type-checked by the TypeScript compiler
  • reference real folders, files, and exports
  • fail the build when documentation and code drift apart

The result is a structured knowledge graph that can be:

  • visualized (Graphviz, diagrams)
  • queried programmatically
  • consumed efficiently by AI assistants

Refactor your code → stale documentation breaks at compile time.


Why tskb exists

Large TypeScript codebases eventually suffer from:

  • Tribal knowledge - architecture lives in senior developers’ heads
  • Compound complexity - the mental model becomes fragile and expensive to communicate
  • Documentation decay - Markdown and diagrams drift silently

tskb addresses this by making architecture documentation:

  • typed
  • validated
  • enforced at build time

Core features

  • Architecture as code using TSX
  • Compiler-verified references via typeof import()
  • Type-checked code snippets (not copied text)
  • Doc priority (essential, constraint, supplementary) to control AI guidance and enforce architectural rules
  • Flows — named, ordered sequences through the system (<Flow> + <Step>), surfaced in queries and AI skill files
  • Native IDE support (autocomplete, refactoring, go-to-definition)
  • Zero runtime impact (pure build-time tooling)
  • CLI for querying (ls, pick, search, docs, flows, context commands)
  • JSON knowledge graph output
  • Graphviz visualization
  • Monorepo-friendly by design
  • Optimized for AI assistants & programmatic consumption

0) Install and setup

Install tskb:

npm install --save-dev tskb

Run the interactive scaffolder:

npx tskb init

This will ask you:

  1. Where to put the docs folder (default: docs/)
  2. The glob pattern and tsconfig path
  3. Whether to enable Claude Code (.claude/skills/) and/or GitHub Copilot (.github/instructions/) integrations

It creates everything you need:

your-repo/
├── docs/
│   ├── tsconfig.json          # TypeScript config for docs (jsxImportSource: "tskb")
│   └── architecture.tskb.tsx  # Starter doc — edit this first
├── package.json               # "docs" script added automatically
├── .claude/skills/            # Created if Claude Code was selected
└── .github/                   # Created if Copilot was selected

Build the knowledge graph:

npm run docs

Verify:

npx tskb ls --plain       # Should show your folder structure
npx tskb docs --plain     # Should list your starter doc

For monorepos: create docs/ at workspace root, and ensure tsconfig.json can resolve all packages you want to document.


Define your vocabulary

Declare architecture primitives using TypeScript declaration merging. All primitives are declared inside the global tskb namespace.

// docs/vocabulary.tskb.tsx
import type { Folder, File, Export, Term } from "tskb";

declare global {
  namespace tskb {
    interface Folders {
      DataLayer: Folder<{
        desc: "Data access layer with repositories and database logic";
        path: "src/server/database";
      }>;
      ServiceLayer: Folder<{
        desc: "Business logic and application services";
        path: "src/server/services";
      }>;
      APILayer: Folder<{
        desc: "HTTP controllers and route handlers";
        path: "src/server/controllers";
      }>;
    }

    interface Modules {
      AuthServiceModule: Module<{
        desc: "Authentication service module";
        type: typeof import("../src/server/services/auth.service.js");
      }>;
    }

    interface Exports {
      UserRepository: Export<{
        desc: "User data access using repository pattern";
        type: typeof import("../src/server/database/repositories/user.repository.js").UserRepository;
      }>;
      AuthService: Export<{
        desc: "Authentication and authorization business logic";
        type: typeof import("../src/server/services/auth.service.js").AuthService;
      }>;
    }

    interface Files {
      "api-spec": File<{
        desc: "OpenAPI specification for the REST API";
        path: "docs/openapi.yml";
      }>;
    }

    interface Terms {
      "repository-pattern": Term<"Repository Pattern for data access abstraction">;
      jwt: Term<"JSON Web Tokens for stateless authentication">;
      "layered-architecture": Term<"Layered architecture pattern (API → Service → Data)">;
    }

    interface Externals {
      postgres: External<{
        desc: "Primary relational database";
        kind: "database";
        url: "https://www.postgresql.org";
      }>;
      redis: External<{
        desc: "Session cache and pub/sub messaging";
        kind: "cache";
        url: "https://redis.io";
      }>;
    }
  }
}

Write documentation

Reference your global vocabulary to document architecture. Multiple teams can author docs that all use the same shared architectural terms.

// docs/authentication.tskb.tsx
import { Doc, H1, H2, P, Snippet, ref } from "tskb";
import type { AuthService } from "../src/server/services/auth.service.js";
import type { UserRepository } from "../src/server/database/repositories/user.repository.js";
import type { LoginCredentials, AuthResponse } from "../src/shared/types/auth.types.js";

// Reference the global vocabulary
const ServiceLayer = ref as tskb.Folders["ServiceLayer"];
const DataLayer = ref as tskb.Folders["DataLayer"];
const AuthServiceExport = ref as tskb.Exports["AuthService"];
const UserRepositoryExport = ref as tskb.Exports["UserRepository"];
const Jwt = ref as tskb.Terms["jwt"];
const RepositoryPattern = ref as tskb.Terms["repository-pattern"];

export default (
  <Doc
    explains="Authentication architecture: login flow, JWT tokens, and service-repository interaction"
    priority="essential"
  >
    <H1>Authentication Architecture</H1>

    <P>
      The {AuthServiceExport} in the {ServiceLayer} handles authentication using {Jwt}. It depends
      on {UserRepositoryExport} in the {DataLayer} following the {RepositoryPattern}.
    </P>

    <H2>Example: Login Flow</H2>

    <Snippet
      code={async () => {
        const authService: AuthService = new AuthService();
        const credentials: LoginCredentials = {
          email: "user@example.com",
          password: "hashedPassword",
        };
        const response: AuthResponse = await authService.login(credentials);
        return response.tokens.accessToken;
      }}
    />
  </Doc>
);

Snippet type checking

<Snippet> is not a string literal.

  • Snippet bodies are fully type-checked
  • Real types and APIs can be imported
  • Broken examples fail the documentation build
// docs/repository-pattern.tskb.tsx
import { Doc, H1, P, Snippet } from "tskb";
import type { UserRepository } from "../src/server/database/repositories/user.repository.js";
import type { User } from "../src/shared/types/user.types.js";
import type { Database } from "../src/server/database/connection.js";

export default (
  <Doc explains="Repository pattern implementation for data access abstraction">
    <H1>Repository Pattern Example</H1>

    <P>The UserRepository demonstrates the repository pattern for data access abstraction.</P>

    <Snippet
      code={async () => {
        const db: Database = new Database(config);
        const userRepository: UserRepository = new UserRepository(db);
        const user: User | null = await userRepository.findByEmail("test@example.com");
        return user?.id;
      }}
    />
  </Doc>
);

If the API changes:

❌ Property 'findByEmail' does not exist on type 'UserRepository'.

The snippet is never executed - it is parsed, validated, and stringified.


What tskb produces: a semantic architecture graph

tskb builds a typed, semantic knowledge graph describing your system.

The graph captures:

  • Nodes - folders, modules, exports, files, terms, docs
  • Edges - explicit and inferred relationships
  • Hierarchy - nested architectural contexts
  • Semantics - intent expressed through JSX

This graph is the primary output. Everything else (diagrams, markdown, AI context) is derived from it.


Output schema (high level)

{
  nodes: {
    folders: Record<string, FolderNode>;   // id, desc, path
    modules: Record<string, ModuleNode>;   // id, desc, resolvedPath, typeSignature, imports
    exports: Record<string, ExportNode>;   // id, desc, resolvedPath, typeSignature
    files:   Record<string, FileNode>;     // id, desc, path
    terms:   Record<string, TermNode>;     // id, desc
    flows:   Record<string, FlowNode>;     // id, desc, priority, steps[]
    docs:    Record<string, DocNode>;       // id, explains, priority, filePath, content
  },
  edges: Array<{
    from: string;
    to: string;
    type: "references" | "contains" | "belongs-to" | "imports" | "related-to" | "flow-step";
    label?: string;
  }>,
  metadata: {
    generatedAt: string;
    version: string;
    stats: { folderCount, moduleCount, exportCount, fileCount, termCount, flowCount, docCount, edgeCount };
  }
}

DocNode.priority controls visibility:

  • "essential" — included in generated skill/instructions files and ls output
  • "constraint" — architectural rule shown in pick and search results, must be followed when working on referenced areas
  • "supplementary" — graph-only (default), queryable via search/pick

The schema is intentionally graph-first and machine-oriented.


Nested contexts

Folders define architectural contexts, not just paths.

From folder paths, tskb infers:

  • hierarchical containment (contains)
  • ownership of modules and exports (belongs-to)
  • the most specific enclosing context

Your architecture becomes a tree of nested contexts, not a flat list.


Relations

Relations in the graph come from two sources:

Explicit intent

When you reference entities in JSX:

<P>Authentication is handled by {AuthService}.</P>

tskb records a semantic edge:

Doc → AuthService (references)

Semantic Relations with <Relation />

To express a semantic relationship between two nodes, use the <Relation /> JSX tag:

<Relation from={AuthService} to={UserRepository} label="depends on" />

This creates a related-to edge in the graph, optionally labeled for richer semantics:

AuthService → UserRepository (related-to, label: "depends on")
  • from and to must be node constants (extracted from the registry)
  • label is optional and can be any string describing the relationship

These relations are visible in CLI output (e.g., pick), and the label is included if present.

Inferred structure

From filesystem paths and imports:

  • Folder → Folder (contains)
  • Module → Folder (belongs-to)
  • Module → Module (imports) — from resolved import statements
  • Export → Module (belongs-to)
  • File → Folder (belongs-to)

The graph combines authored intent with structural truth.


Flows

Flows model named, ordered sequences through the system — login pipelines, build processes, request handling chains.

import { Doc, H1, Flow, Step, ref } from "tskb";

const AuthMiddleware = ref as tskb.Exports["AuthMiddleware"];
const AuthService = ref as tskb.Modules["AuthServiceModule"];
const UserRepository = ref as tskb.Exports["UserRepository"];

export default (
  <Doc explains="Authentication flows">
    <H1>Auth Flows</H1>

    <Flow name="login" desc="User login from HTTP request to session token" priority="essential">
      <Step node={AuthMiddleware} label="Validates request format" />
      <Step node={AuthService} label="Checks credentials, generates JWT" />
      <Step node={UserRepository} label="Queries user record" />
    </Flow>
  </Doc>
);

Each <Flow> becomes a first-class node in the graph with flow-step edges connecting it to its participants. Only <Step> children are allowed (validated at build time).

Priority controls visibility:

  • priority="essential" — included in generated skill/instructions files and tskb flows output
  • priority="supplementary" (default) — graph-only, queryable via tskb flows and search

Why JSX: semantics, not rendering

JSX in tskb is not about UI.

It is a semantic DSL that allows you to declare meaning in a structured, type-safe way. Each JSX element becomes semantic data — not HTML.

JSX provides composability, static analysis, and extensibility without inventing a new syntax.


Querying the graph

Once built, query the knowledge graph using the CLI:

List folder structure

npx tskb ls              # List top-level folders (depth=1)
npx tskb ls --depth 4    # List folders up to depth 4
npx tskb ls --depth -1   # List all folders (unlimited depth)

Returns essential docs first, then folders ordered by depth.

Pick a node

npx tskb pick "ServiceLayer"              # Pick a folder by ID
npx tskb pick "src/server/services"       # Pick by filesystem path
npx tskb pick "auth.AuthService"          # Pick a module by ID

Returns type-specific data: parent, children, modules, exports, files, and referencing docs with their priority. When picking a doc node, the full content is included inline. Constraint docs in the results indicate rules that must be followed.

Search the graph

npx tskb search "auth"                    # Single keyword
npx tskb search "build command"           # Multi-word fuzzy search

Returns ranked results with scores across all node types. Doc results include priority so constraint and essential docs are immediately visible.

List and search docs

npx tskb docs                            # List all docs sorted by priority
npx tskb docs "auth"                     # Search docs by query (matches explains, content, filePath)

Lists all docs sorted by priority (constraints first, then essential, then supplementary). With a query, returns fuzzy-matched results with scores, filtered to relevant matches. Use pick on a doc nodeId to get its full content.

List and search flows

npx tskb flows                           # List all flows sorted by priority
npx tskb flows "build"                   # Search flows by query

Lists all flows sorted by priority. Essential flows are shown first. Use pick on a flow nodeId to see its steps and referenced nodes.

Get full context for an area

npx tskb context "ServiceLayer"          # Depth 1 (default): node + immediate children + docs
npx tskb context "ServiceLayer" --depth 2 # Deeper: includes grandchildren and their docs
npx tskb context "src/server/services"   # Also works with filesystem paths

Returns the target node, all neighborhood nodes (child folders, modules, exports) up to the specified depth, and all referencing docs — deduplicated and sorted by priority. Constraint doc IDs are surfaced at the top level so they can't be missed.

All commands output JSON by default. Use --plain for structured plain text optimized for AI assistants (fewer tokens, no JSON overhead), or --optimized for compact JSON.


Visualize

The build command automatically generates a Graphviz DOT file in .tskb/graph.dot.

To render it as an image:

dot -Tpng .tskb/graph.dot -o .tskb/graph.png

Or view it interactively:

xdot .tskb/graph.dot

Workflow integration

Pre-commit hook

Validate docs on every commit:

npm install --save-dev husky
npx husky init
echo "npm run docs" > .husky/pre-commit

CI/CD (GitHub Actions)

- name: Validate architecture docs
  run: npm run docs

- name: Upload graph artifact
  uses: actions/upload-artifact@v3
  with:
    name: architecture-graph
    path: .tskb/

This ensures documentation stays synchronized with code changes.


AI assistant integration

TSKB is designed to help AI assistants understand codebases efficiently:

  • Auto-generated integrations: Build produces a Claude Code skill (.claude/skills/tskb/SKILL.md) and Copilot instructions (.github/instructions/tskb.instructions.md) with folder tree, essential doc summaries, command response shapes, and workflow guidance baked in
  • Doc priority: Controls what AI assistants see — essential docs appear in generated files and ls output, constraint docs surface in pick/search with their priority visible, supplementary docs are graph-only
  • Constraint docs: Mark docs with priority="constraint" to define architectural rules. When an AI picks a node, constraint docs referencing that area appear in the results — signaling rules that must be followed before making changes
  • Docs command: docs lists or searches all documentation, with fuzzy matching across explains, content, and file paths — essential docs are boosted in search results
  • Context command: context returns a node's full neighborhood (children, modules, exports) with referencing docs — replacing multi-step pick → read → pick workflows with a single call
  • Plain text mode: --plain outputs structured text instead of JSON — ~30% fewer tokens for AI consumption while preserving all semantic content
  • Flows command: flows lists or searches named sequences through the system — essential flows are included in generated skill/instructions files
  • Structured queries: AI can use ls, pick, search, docs, flows, and context to navigate architecture — all return JSON (or plain text with --plain) with priority metadata on doc results

Instead of blindly exploring files, AI assistants can:

  1. Read the baked-in folder tree and essential doc summaries from the generated skill/instructions
  2. Use search to find relevant nodes for a task
  3. Use docs to find and filter documentation by topic
  4. Use context to get the full neighborhood — nodes, docs, and constraints in one call
  5. Use pick for targeted single-node lookups or to read a doc's full content
  6. Read only the files that matter

This dramatically reduces tokens spent on exploration and increases accuracy.

Generated skills

The build produces two skills for each integration (Claude Code and GitHub Copilot):

Skill Purpose Generated files
tskb Codebase map — folder tree, essential doc summaries, CLI commands. Loaded on every prompt. .claude/skills/tskb/SKILL.md
.github/instructions/tskb.instructions.md
tskb-update Writing and maintaining .tskb.tsx files — JSX syntax, registry primitives, session triggers, best practices. Applies to .tskb.tsx files. .claude/skills/tskb-update/SKILL.md
.github/instructions/tskb-update.instructions.md

How they work:

  • Claude Code: Skills in .claude/skills/ are loaded automatically based on context. The main tskb skill is always available; tskb-update activates when working with .tskb.tsx files.
  • GitHub Copilot: Instructions in .github/instructions/ use applyTo frontmatter patterns. tskb.instructions.md applies to all files (**), tskb-update.instructions.md applies to **/*.tskb.tsx.
  • Content is auto-generated: Every npm run docs build regenerates these files from the current graph. Don't edit them manually — they'll be overwritten.

To enable these integrations, select them during npx tskb init or create the directories manually (.claude/skills/ and/or .github/). The build detects their presence and writes the corresponding files.


How is this different?

vs ADRs / Markdown docs: Type-checked and validated against real code, not just text files that drift.

vs Structurizr / C4 / PlantUML: Native TypeScript (not a custom DSL), produces a queryable knowledge graph (not just static diagrams).

vs TypeDoc: Documents architecture and intent (why components exist, how they relate), not just API surfaces (what methods exist).

Unique to tskb:

  • Type-checks architecture docs at compile time
  • Validates against actual code via typeof import()
  • CLI for querying the graph (no file scanning needed)
  • Documents whole systems (multiple packages, monorepos)
  • Type-checked code snippets (not string literals)
  • First-class flows — named, ordered sequences as graph nodes
  • Doc priority system (essential, constraint, supplementary) for AI guidance
  • Optimized for AI assistants with structured queries and constraint enforcement

Roadmap

  • Architectural constraints validation
  • Interactive visualization (beyond Graphviz)
  • Plugin system for custom node types

License

MIT © Dimitar Mihaylov