{\_/} │
(O,O) │ "Round eyes.
(:::) │ Sharp placement."
-^-^v--│
└──────────────────────────────────────
Structural scoring system for TypeScript codebases — answers "where should this code live?"
Early stage project — Kural is under active development and evolving rapidly. Check out Projects for the roadmap ahead. We welcome feedback, ideas, and contributions — reach out at hello@razyones.com to collaborate or share your thoughts.
Kural embeds every type, function, file, and directory into vector space, measures how well the codebase is distributed in that space, and surfaces specific, actionable structural issues.
┌─────────────────────┐
│ PLACE │ Roof: the payoff
├──────────┬──────────┤
│ SCORE │ AUDIT │ Pillars: cross-validate each other
├──────────┴──────────┤
│ EMBED │ Foundation: everything rests on this
└─────────────────────┘
AI coding agents write code. They add functions, create files, move things around. But they have no idea whether the code they just wrote landed in the right place. They can't see that the function they added to utils/ is semantically identical to one in core/, or that the file they created in commands/ drifts toward the analysis engine's vocabulary.
Kural gives your codebase a structural map. Kural skills give your AI assistant the ability to read that map.
Without skills, the agent generates code blind to structure. With skills, it knows the four-phase resolution pipeline, understands why descriptions carry 50% weight in the identity vector, and can work through audit findings methodically — fixing docs before restructuring, restructuring before suppressing.
This is the difference between an agent that writes code and an agent that writes code in the right place.
An AI agent without structural awareness will accumulate architectural debt faster than a human developer — it produces more code per hour but has zero intuition about where that code belongs. Kural skills are the structural intuition layer.npm install -g kuralexport AI_GATEWAY_API_KEY=your-api-keySupported providers: Vercel (default), OpenAI, OpenRouter, Ollama (local, no key required). Even local models like Qwen3 Embedding 4B via Ollama perform very well. Gemini Embedding 2 is the recommended model.
Descriptions carry 50% weight in the identity vector. This is the most impactful step.
Add JSDoc comments to files, functions, and types. Add KURAL.md files to directories.
/**
* The gateway. Crosses the network boundary to turn text into vectors
* via an external AI service. It is the only module that speaks the
* AI SDK protocol — no other part of the system calls embedding APIs
* directly.
*/Annotate functions with @kuralPure (no side effects) or @kuralCauses (describes side effects):
/**
* Computes cosine similarity between two vectors.
* Wraps DruidJS cosine distance: cos(acos(similarity)) recovers similarity.
* Returns 0 if either vector is empty.
* @param a - First vector
* @param b - Second vector
* @returns Cosine similarity in range [-1, 1]
* @kuralPure
*/
function cosineSimilarity(a: number[], b: number[]): number {
/* ... */
}
/**
* Persists computed health metrics so downstream commands can query scores
* without re-running the pipeline.
* @param collections - Snapshot collections to write into
* @param cards - Computed score cards to persist
* @returns Resolves when score card rows are persisted
* @kuralCauses persists score card rows to the snapshot database
*/
async function writeScoreCards(
collections: SnapshotCollections,
cards: ScoreCard[],
): Promise<void> {
/* ... */
}See the description principles and Kural Params for full guidance.
kural snapshot generate srcWalks src/, extracts types and functions from the AST, embeds them using 7 structural facets, computes scores, and stores everything in .kural-db/.
kural scorekural audit15 statistical audits surface outliers, duplicates, containment problems, and more.
kural snapshot generate <path> Parse, embed, and score a codebase
kural score Display structural scores
kural audit Run structural audits
kural snapshot list List all history snapshots
kural snapshot pin <id> <name> Pin a snapshot (prevents eviction)
kural snapshot unpin <id> Remove a pin
kural snapshot delete <id> Delete a snapshot
-p, --path <path> Score a specific node or subtree
-e, --explain Show detailed breakdown table
-c, --compare <id> Compare against a previous snapshot
-l, --limit <n> Max rows in breakdown (default 20, 0 for all)
--json Output as JSON
-k, --sensitivity <n> Standard deviations from mean to flag (default 2.0)
-f, --filter <categories> Comma-separated audit categories to show
-d, --disable <names> Comma-separated audit names to skip
-e, --expand Show all findings (no truncation)
--json Output as JSON
-p, --provider <name> Embedding provider (vercel, openai, openrouter, ollama)
-m, --model <id> Model ID override
-k, --apiKey <key> API key (defaults to AI_GATEWAY_API_KEY env var)
--pin <name> Pin the snapshot after generation
--json Output as JSON
Create kural.config.json in your project root:
{
"embeddings": {
"provider": "vercel"
},
"domainKeywords": ["scoring", "embedding", "audit"],
"dictionary": {
"SOST": "structural scoring tree"
},
"audits": {
"sensitivity": 2.0,
"disable": ["incomplete-docs"]
}
}JSDoc annotations that declare structural realities the vector space can't capture alone:
| Param | Purpose |
|---|---|
@kuralPure |
Marks functions with no side effects |
@kuralCauses <desc> |
Describes what a function does beyond its type signature |
@kuralUtil |
Excludes from domain scoring, scored in own sandbox |
@kuralHelper |
Participates in scoring, excluded from audits |
@kuralPatterns <group> |
Deduplicates siblings to a centroid representative |
@kuralCompanion <group> |
Groups structurally coupled units |
@kuralBound inward/outward |
Adjusts scoring for entry points and primary exports |
@kuralResidual <audit> [hash] |
Suppresses a specific audit finding |
Kural is a five-stage pipeline:
- Parse — Walk the filesystem, extract functions, types, and descriptions from the AST
- Embed — Produce identity and leaf vectors via 7-facet embedding (name, description, path, signature, causes, calls, parent context)
- Score — Compute fit, uniqueness, and subtree health for every node
- Store — Persist units, scores, and metadata to a SQLite snapshot
- Query — Read snapshots for scoring, auditing, and comparison
Every node gets a score card:
- Fit — how well the node's content matches its parent's identity (-1...1)
- Uniqueness — mean distance to siblings (-1...1)
- Score — harmonic mean of fit and uniqueness
- Children — direct children quality (containers only)
- Subtree — recursive health of the entire subtree below (containers only)
- Overall — harmonic mean of self and subtree scores
| Layer | Tool |
|---|---|
| CLI framework | Gunshi |
| AI | Multiple providers (Vercel, OpenAI, OpenRouter, Ollama) |
| Local persistence | TanStack DB + SQLite |
| Runtime | Node.js, ESM |
- Describe your codebase — JSDoc on files, functions, and types; KURAL.md in directories
- Annotate structural realities —
@kuralPure/@kuralCauseson functions,@kuralUtilon utilities - Generate a snapshot —
kural snapshot generate src - Score the overall structure —
kural score - Audit for specific issues —
kural audit - Fix the flagged issues, regenerate to verify improvement
- Compare before and after —
kural score -c <old-snapshot-id>
- Stable docs — latest release (
main) - Alpha docs — preview of upcoming changes (
alpha)
- Getting Started — installation, codebase preparation, and first run
- Architecture — pipeline, tiers, data model, and sync design
- Embedding — 7-facet embedding with structural signals
- Scoring — fit, uniqueness, and subtree health metrics
- Audits — 14 statistical checks for structural issues
- Kural Params — annotations for codebase realities
- Database — SQLite snapshot persistence and schema
Kural is built on the shoulders of these open-source projects:
Core
- Gunshi — CLI framework
- AI SDK — embedding provider gateway
- TanStack DB — reactive persistence layer
- better-sqlite3 — SQLite driver
- Zod — schema validation
- DruidJS — dimensionality reduction and vector math
- Poppinss CLI UI — terminal formatting
- TypeScript — language service for AST parsing
Toolchain
- Vite+ — unified dev, build, lint, test, and format
- Vitest — test runner
- Oxlint — linter
- tsdown — library bundler
Documentation site
- Fumadocs — documentation framework
- TanStack Start — full-stack React framework
- Tailwind CSS — styling
- Orama — client-side search
- KaTeX — math rendering
- Lucide — icons
Thank you to every maintainer and contributor behind these projects.
Apache 2.0 — see LICENSE for details.