AST + LLM driven codebase analysis and visualization.
Squint indexes TypeScript and JavaScript source code into an SQLite database, then provides 80+ commands to systematically annotate symbols and relationships with human-readable descriptions — manually or via LLM. It detects architectural modules, cross-module interactions, user journey flows, and product-level features.
- Installation
- Quick Start
- Command Reference
- AI Agent Usage
- Understanding Workflow
- CI/CD Integration
- Database Schema
- Development
- License
# Global install
npm install -g @zbigniewsobiecki/squint
# Or run directly
npx @zbigniewsobiecki/squint --helpgit clone https://github.com/zbigniewsobiecki/squint.git
cd squint
pnpm install
pnpm run buildFull automated pipeline (parse, annotate, verify, generate modules/interactions/flows/features):
squint ingest ./srcManual step-by-step:
# 1. Index your codebase
squint parse ./src
# 2. Check what needs understanding
squint symbols understood
# 3. Annotate symbols with LLM
squint symbols annotate -a purpose -a domain -a role
# 4. Generate architectural modules
squint modules generate
# 5. Detect cross-module interactions
squint interactions generate
# 6. Trace user journey flows
squint flows generate
# 7. Group flows into product features
squint features generate
# 8. Get a compact overview
squint overview| Namespace | Commands |
|---|---|
| Top-level | parse, ingest, browse, overview, stats, gaps |
| symbols | list, show, set, unset, annotate, verify, ready, next, deps, prereqs, understood |
| relationships | list, show, set, unset, annotate, verify, next |
| domains | list, show, create, update, delete, sync, rename, merge |
| modules | list, show, create, update, delete, assign, unassign, generate, verify, prune |
| interactions | list, show, create, update, delete, generate, validate, verify |
| flows | list, show, create, update, delete, add-step, remove-step, trace, generate, verify |
| features | list, show, create, update, delete, assign, unassign, generate |
| files | list, show, imports, imported-by, orphans |
| hierarchy | (default: inheritance tree) |
| process-groups | list |
All commands accept -d, --database <path> (default: <directory>/.squint.db) and most accept --json for machine-readable output.
The database path can also be set via the SQUINT_DB_PATH environment variable, which takes precedence over the default walk-up discovery but is overridden by an explicit -d flag:
export SQUINT_DB_PATH=/path/to/my-project.db
squint flows list # uses SQUINT_DB_PATH
squint flows list -d other.db # explicit flag winsScans TypeScript/JavaScript files and builds an SQLite index of definitions, references, and symbol usages.
squint parse <directory> [-o <output.db>]| Flag | Default | Description |
|---|---|---|
-o, --output |
.squint.db or $SQUINT_DB_PATH |
Output database file path |
Runs the complete pipeline in sequence: parse, annotate symbols, verify symbols, annotate relationships, verify relationships, generate modules, verify modules, generate interactions, verify interactions, generate flows, verify flows, and generate features.
squint ingest <directory> [flags]| Flag | Description |
|---|---|
--from <stage> |
Resume from a specific stage |
--force |
Re-run stages even if data exists |
--dry-run |
Don't persist LLM results |
-m, --model |
LLM model alias |
Launches a web-based visualization of the indexed codebase.
squint browse [-p <port>] [--no-open]Shows a complete codebase overview: stats, features, module tree, and file tree.
squint overview [flags]Shows aggregate statistics and pipeline progress: parsed counts, annotation coverage, module assignment, interactions, flows, and features.
squint stats [--json]Lists unannotated symbols, unannotated relationships, empty modules, and unassigned symbols.
squint gaps [flags]| Flag | Description |
|---|---|
-t, --type |
Gap type: symbols, relationships, modules, unassigned (default: all) |
--limit |
Max items per section (default: 20) |
--kind |
Filter symbols by kind |
Manage symbol definitions (functions, classes, variables, types, interfaces, enums).
Lists all symbols in the index. This is the default when running squint symbols.
squint symbols [flags]| Flag | Description |
|---|---|
--kind |
Filter by kind: function, class, variable, type, interface, enum |
--file |
Filter to symbols in a specific file |
--has <key> |
Filter to symbols that have this metadata key |
--missing <key> |
Filter to symbols missing this metadata key |
--domain <name> |
Filter to symbols with this domain tag |
--pure <bool> |
Filter by purity |
--domains |
List all unique domains in use |
Shows detailed information about a symbol including source code, callsites, metadata, and interactions. Also supports file-level aggregation when --file is used without a symbol name.
# Single symbol
squint symbols show <name> [--id <id>] [-f <file>] [-c <context-lines>] [--json]
# File aggregation (all symbols, relationships, interactions, flows for a file)
squint symbols show --file <path> [--json]In single-symbol mode, interactions are filtered to symbol-level precision: incoming interactions where the symbol's name appears in the interaction's symbols JSON field, and outgoing interactions where any of the symbol's dependencies appear. In file mode, data is aggregated and deduplicated across all symbols in the file.
Sets metadata (annotations) on a symbol.
squint symbols set <key> <value> --name <symbol>
squint symbols set <key> <value> --id <id>Common metadata keys: purpose, domain (JSON array), role, pure.
Supports --batch (stdin) and -i, --input-file for bulk annotation.
Removes a metadata key from a symbol.
squint symbols unset <key> --name <symbol>Uses an LLM to automatically annotate symbols in dependency order (leaves first).
squint symbols annotate -a <aspect> [flags]| Flag | Description |
|---|---|
-a, --aspect |
(required, repeatable) Metadata key to annotate |
-m, --model |
LLM model alias |
-b, --batch-size |
Symbols per LLM call (default: 5) |
--max-iterations |
Max iterations, 0 = unlimited |
-k, --kind |
Filter by symbol kind |
-f, --file |
Filter by file path pattern |
-x, --exclude |
Glob pattern to exclude |
--force |
Annotate even if dependencies aren't annotated |
--dry-run |
Parse LLM output but don't persist |
squint symbols annotate -a purpose -a domain -a role
squint symbols annotate -a purpose --kind function --exclude "**/*.test.ts"Verifies existing symbol annotations using LLM and flags incorrect ones.
squint symbols verify [flags]Lists symbols ready to annotate — all their dependencies already have the specified aspect.
squint symbols ready --aspect <key> [-l <limit>] [-k <kind>] [-f <file>] [-v]Shows the next symbol ready to understand with its full source code.
squint symbols next --aspect <key> [-c <count>] [-m <max-lines>] [--json]Shows what other symbols a given symbol depends on, with annotation status.
squint symbols deps <name> [-a <aspect>] [--json]Shows unmet dependencies in topological order — what to understand before a target symbol.
squint symbols prereqs <name> --aspect <key>Shows understanding coverage statistics per aspect.
squint symbols understood [-a <aspect>] [-k <kind>] [-f <file>] [--json]Manage semantic annotations on call/use edges between symbols.
Lists all annotated relationships. Default when running squint relationships.
squint relationships [--from <symbol>] [--to <symbol>] [--count] [--json]Shows detail for a relationship between two definitions.
squint relationships show --from <symbol> --to <symbol>Sets a semantic annotation on a relationship.
squint relationships set "<description>" --from <source> --to <target>
squint relationships set "<description>" --from-id <id> --to-id <id>Removes a relationship annotation.
squint relationships unset --from <source> --to <target>Uses an LLM to annotate relationships between symbols.
squint relationships annotate [flags]Verifies existing relationship annotations using LLM.
squint relationships verify [flags]Shows the next unannotated relationship with context (both symbols' metadata, other relationships, source code).
squint relationships next [--count <n>] [--from <symbol>] [--json]Manage business/architectural domain tags that group related symbols.
Lists registered domains with symbol counts. Default when running squint domains.
squint domains [--unregistered] [--json]Shows domain details including assigned symbols.
squint domains show <name>Registers a new domain.
squint domains create <name> [--description "..."]Updates a domain description.
squint domains update <name> --description "..."Removes a domain from the registry.
squint domains delete <name> [--force]Bulk-registers all domains currently in use by symbols.
squint domains syncRenames a domain in the registry and updates all symbol metadata.
squint domains rename <old-name> <new-name>Merges the source domain into the target, updating all symbols.
squint domains merge <from-domain> <into-domain>Manage architectural module hierarchy. Modules use dot-notation paths (e.g., project.backend.services.auth).
Lists all modules with member counts. Default when running squint modules.
squint modules [--tree] [--json]Shows module details including all members.
squint modules show <name> [--json]Creates a new module under a parent.
squint modules create <name> [flags]Updates a module name or description.
squint modules update <name> [flags]Deletes a module.
squint modules delete <name>Assigns a symbol to a module.
squint modules assign --module <module> --name <symbol>Removes a symbol from its module.
squint modules unassign --name <symbol>Uses a two-phase LLM approach to create a hierarchical module tree and assign symbols.
squint modules generate [flags]| Flag | Description |
|---|---|
-b, --batch-size |
Symbols per assignment batch (default: 30) |
--dry-run |
Show detected modules without persisting |
--force |
Re-detect even if modules exist |
-m, --model |
LLM model alias |
Verifies existing module assignments using LLM.
squint modules verify [flags]Removes empty leaf modules.
squint modules pruneManage module-to-module interaction edges derived from the call graph.
Lists all detected module interactions. Default when running squint interactions.
squint interactions [--json]Shows details for a specific interaction.
squint interactions show <id> [--json]Creates a new module interaction.
squint interactions create [flags]Updates an interaction.
squint interactions update <id> [flags]Deletes an interaction.
squint interactions delete <id>Detects module interactions from the call graph and generates semantics using LLM.
squint interactions generate [--force] [--dry-run] [-m <model>] [--json]Validates LLM-inferred interactions using deterministic checks against the call graph.
squint interactions validate [flags]Verifies existing interactions using LLM.
squint interactions verify [flags]Manage user journey flows that trace paths through module interactions.
Lists all detected flows. Default when running squint flows.
squint flows [--domain <domain>] [--json]Shows flow details with interaction steps.
squint flows show <name> [--json]Creates a new flow.
squint flows create <name> [flags]Updates a flow.
squint flows update <name> [flags]Deletes a flow.
squint flows delete <name>Adds an interaction step to a flow.
squint flows add-step --flow <flow> --interaction <interaction-id> [--step-order <n>]Removes a step from a flow.
squint flows remove-step --flow <flow> --step-order <n>Traces the call graph from a symbol, showing reachable symbols as a tree.
squint flows trace --name <symbol> [--depth <n>] [--json]Detects user journey flows from entry points and traces through interactions.
squint flows generate [flags]| Flag | Description |
|---|---|
--min-steps |
Minimum steps for a valid flow (default: 2) |
--max-depth |
Maximum traversal depth (default: 15) |
--domain |
Only detect flows in a specific domain |
--from |
Start from a specific entry point |
--dry-run |
Show detected flows without persisting |
--force |
Re-detect even if flows exist |
--skip-llm |
Skip LLM naming |
-m, --model |
LLM model alias |
Verifies existing flows using LLM.
squint flows verify [flags]Manage product-level feature groupings of flows.
Lists all features with flow counts. Default when running squint features.
squint features [--json]Shows feature details with associated flows.
squint features show <name> [--json]Creates a new feature.
squint features create <name> [flags]Updates a feature.
squint features update <name> [flags]Deletes a feature.
squint features delete <name>Assigns a flow to a feature.
squint features assign --feature <feature> --flow <flow>Removes a flow from a feature.
squint features unassign --feature <feature> --flow <flow>Groups flows into product-level features using LLM.
squint features generate [--force] [--dry-run] [-m <model>] [--json]Explore the indexed file structure.
Lists all indexed files. Default when running squint files.
squint files [--stats]Shows file details including definitions and imports.
squint files show <path>Lists files imported by a specific file.
squint files imports <path>Lists files that import a specific file.
squint files imported-by <path>Finds files with no incoming imports.
squint files orphansShows class/interface inheritance trees or call hierarchies.
squint hierarchy [flags]| Flag | Description |
|---|---|
--type |
Relationship type: extends, implements, calls, imports, uses (default: extends) |
--root |
Start from a specific symbol |
--depth |
Max depth (default: 10) |
squint hierarchy # All extends relationships
squint hierarchy --type calls --root main # Call hierarchy from main()
squint hierarchy --type implements # Interface implementationsLists process groups (connected components in the import graph).
squint process-groupsSquint is designed for both human and AI-driven codebase exploration. Every show and list command supports the --json flag, which produces structured JSON output suitable for programmatic consumption by AI agents, scripts, and tooling.
The recommended approach is a top-down drill-down: start with the highest-level overview and progressively narrow focus into specific entities.
- Start with overview:
squint overview --jsonreturns aggregate stats, the features list, the module tree, and the file tree. This gives the big picture. - Drill into features:
squint features show <slug> --jsonreturns enriched flows (withstepCount,stakeholder,entryPath), modules involved, interactions, and stats. - Drill into flows:
squint flows show <slug> --jsonreturns features, an entry point (with definition details and metadata), ordered interaction steps, modules involved, and the definition trace (function-level call chain). - Drill into interactions:
squint interactions show <id> --jsonreturns module descriptions, resolved symbols (matched to definitions), related interactions from the same source module, flows using this interaction, and features. - Drill into modules:
squint modules show <path> --jsonreturns parent, children, outgoing/incoming interactions, flows, features, and all member symbols. - Drill into symbols:
squint symbols show <name> --jsonreturns module, outgoing/incoming relationships, dependencies, dependents (with count), flows, symbol-level interactions, source code, and call sites. 6b. Drill into files:squint symbols show --file <path> --jsonaggregates all symbols, relationships, interactions, and flows for every symbol in the file — useful for understanding a file's full role. - Drill into files:
squint files show <path> --jsonreturns definitions (enriched with module and metadata), imports, imported-by, and relationships. - Drill into relationships:
squint relationships show --from <id> --to <id> --jsonreturns metadata for both symbols, module context, the module interaction, and flows. - Drill into domains:
squint domains show <name> --jsonreturns symbols, module distribution, and intra-domain relationships.
Each show command returns a JSON object. The schemas below document the top-level keys and their types.
{
"id": 1,
"name": "Authentication",
"slug": "authentication",
"description": "...",
"createdAt": "2024-01-01T00:00:00.000Z",
"flows": [
{ "id": 1, "name": "UserLoginFlow", "slug": "user-login", "description": "...", "stakeholder": "user", "entryPath": "POST /api/login", "stepCount": 3 }
],
"modulesInvolved": [
{ "id": 2, "name": "Controllers", "fullPath": "project.api.controllers" }
],
"interactions": [
{ "id": 1, "fromModulePath": "project.api.controllers", "toModulePath": "project.services", "pattern": "business", "semantic": "..." }
],
"stats": { "flowCount": 2, "byStakeholder": { "user": 2 } }
}{
"id": 1, "name": "UserLoginFlow", "slug": "user-login",
"stakeholder": "user", "entryPath": "POST /api/login", "description": "...",
"steps": [
{ "stepOrder": 1, "interaction": { "id": 1, "fromModulePath": "...", "toModulePath": "...", "pattern": "business", "semantic": "..." } }
],
"features": [{ "id": 1, "name": "Authentication", "slug": "authentication" }],
"entryPoint": { "id": 10, "name": "handleLogin", "kind": "function", "filePath": "src/controller.ts", "line": 5, "metadata": { "purpose": "..." } },
"modulesInvolved": [{ "id": 2, "name": "Controllers", "fullPath": "project.api.controllers" }],
"definitionSteps": [
{ "stepOrder": 1, "fromDefinitionName": "handleLogin", "toDefinitionName": "authenticate", "fromFilePath": "...", "toFilePath": "..." }
]
}{
"interaction": { "id": 1, "fromModuleId": 2, "toModuleId": 3, "fromModulePath": "...", "toModulePath": "...", "direction": "uni", "pattern": "business", "semantic": "...", "weight": 5, "symbols": ["createUser"] },
"fromModuleDescription": "Request handlers",
"toModuleDescription": "Business logic",
"resolvedSymbols": [{ "name": "createUser", "kind": "function", "filePath": "...", "line": 10 }],
"relatedInteractions": [{ "id": 2, "toModulePath": "...", "pattern": "...", "semantic": "...", "weight": 1 }],
"flows": [{ "id": 1, "name": "UserLoginFlow", "slug": "user-login" }],
"features": [{ "id": 1, "name": "Authentication", "slug": "authentication" }]
}{
"id": 2, "name": "Controllers", "fullPath": "project.api.controllers", "description": "...", "depth": 2,
"parent": { "id": 1, "name": "API", "fullPath": "project.api" },
"children": [{ "id": 5, "name": "Auth", "fullPath": "project.api.controllers.auth", "description": "..." }],
"outgoingInteractions": [{ "id": 1, "toModulePath": "...", "pattern": "business", "semantic": "...", "weight": 5 }],
"incomingInteractions": [{ "id": 3, "fromModulePath": "...", "pattern": "...", "semantic": "...", "weight": 2 }],
"flows": [{ "id": 1, "name": "UserLoginFlow", "slug": "user-login", "stakeholder": "user" }],
"features": [{ "id": 1, "name": "Authentication", "slug": "authentication" }],
"members": [{ "id": 10, "name": "handleLogin", "kind": "function", "filePath": "...", "line": 5 }]
}{
"id": 10, "name": "handleLogin", "kind": "function", "filePath": "...", "line": 5, "endLine": 15, "isExported": true,
"metadata": { "purpose": "...", "domain": "[\"auth\"]", "role": "controller" },
"module": { "id": 2, "name": "Controllers", "fullPath": "project.api.controllers" },
"relationships": [{ "toDefinitionId": 20, "toName": "authenticate", "toKind": "function", "relationshipType": "calls", "semantic": "...", "toFilePath": "...", "toLine": 10 }],
"incomingRelationships": [{ "fromDefinitionId": 5, "fromName": "router", "fromKind": "variable", "relationshipType": "calls", "semantic": "...", "fromFilePath": "...", "fromLine": 3 }],
"dependencies": [{ "id": 20, "name": "authenticate", "kind": "function", "filePath": "...", "line": 10 }],
"dependents": { "count": 3, "sample": [{ "id": 5, "name": "router", "kind": "variable", "filePath": "...", "line": 3 }] },
"flows": [{ "id": 1, "name": "UserLoginFlow", "slug": "user-login", "stakeholder": "user" }],
"interactions": {
"incoming": [{ "id": 1, "fromModulePath": "project.api.routes", "toModulePath": "project.api.controllers", "pattern": "business", "semantic": "...", "weight": 3, "direction": "uni", "source": "ast" }],
"outgoing": [{ "id": 2, "fromModulePath": "project.api.controllers", "toModulePath": "project.services", "pattern": "business", "semantic": "...", "weight": 5, "direction": "uni", "source": "ast" }]
},
"sourceCode": ["export async function handleLogin(req) {", " ..."],
"callSites": [{ "filePath": "...", "line": 20, "containingFunction": "router", "contextLines": ["..."], "contextStartLine": 18 }]
}{
"file": "src/controllers/auth.ts",
"symbols": [
{ "id": 10, "name": "handleLogin", "kind": "function", "line": 5, "endLine": 15, "isExported": true },
{ "id": 11, "name": "handleRegister", "kind": "function", "line": 20, "endLine": 35, "isExported": true }
],
"modules": [{ "name": "Controllers", "fullPath": "project.api.controllers" }],
"relationships": {
"outgoing": [{ "toDefinitionId": 20, "toName": "authenticate", "toKind": "function", "relationshipType": "calls", "semantic": "...", "toFilePath": "...", "toLine": 10 }],
"incoming": [{ "fromDefinitionId": 5, "fromName": "router", "fromKind": "variable", "relationshipType": "calls", "semantic": "...", "fromFilePath": "...", "fromLine": 3 }]
},
"interactions": {
"incoming": [{ "id": 1, "fromModulePath": "project.api.routes", "toModulePath": "project.api.controllers", "pattern": "business", "semantic": "...", "weight": 3, "direction": "uni", "source": "ast" }],
"outgoing": [{ "id": 2, "fromModulePath": "project.api.controllers", "toModulePath": "project.services", "pattern": "business", "semantic": "...", "weight": 5, "direction": "uni", "source": "ast" }]
},
"flows": [{ "id": 1, "name": "UserLoginFlow", "slug": "user-login", "stakeholder": "user" }]
}{
"file": { "id": 1, "path": "...", "language": "typescript", "sizeBytes": 1234 },
"definitions": [
{ "id": 10, "name": "handleLogin", "kind": "function", "isExported": true, "line": 5, "endLine": 15, "module": { "id": 2, "name": "Controllers", "fullPath": "..." }, "metadata": { "purpose": "..." } }
],
"imports": [{ "source": "./service", "toFilePath": "src/service.ts", "isExternal": false, "isTypeOnly": false }],
"importedBy": [{ "id": 2, "path": "src/router.ts", "line": 1 }],
"relationships": [{ "fromName": "handleLogin", "toName": "authenticate", "toFilePath": "...", "toLine": 10, "relationshipType": "calls", "semantic": "..." }]
}{
"relationship": { "id": 1, "fromDefinitionId": 10, "toDefinitionId": 20, "relationshipType": "calls", "semantic": "delegates authentication" },
"from": { "id": 10, "name": "handleLogin", "kind": "function", "filePath": "...", "line": 5 },
"to": { "id": 20, "name": "authenticate", "kind": "function", "filePath": "...", "line": 10 },
"fromMetadata": { "purpose": "...", "domain": "[\"auth\"]" },
"toMetadata": { "purpose": "..." },
"fromModule": { "id": 2, "name": "Controllers", "fullPath": "project.api.controllers" },
"toModule": { "id": 3, "name": "Services", "fullPath": "project.services" },
"interaction": { "id": 1, "pattern": "business", "weight": 5, "semantic": "..." },
"flows": [{ "id": 1, "name": "UserLoginFlow", "slug": "user-login" }]
}{
"domain": { "name": "auth", "description": "Authentication and authorization", "createdAt": "..." },
"symbols": [{ "id": 10, "name": "handleLogin", "kind": "function", "filePath": "...", "line": 5, "purpose": "..." }],
"moduleDistribution": [{ "id": 2, "name": "Controllers", "fullPath": "project.api.controllers", "count": 3 }],
"intraDomainRelationships": [{ "fromName": "handleLogin", "toName": "authenticate", "relationshipType": "calls", "semantic": "..." }]
}The following shows a concrete example of how an AI agent would explore a codebase using the top-down approach:
# 1. Get the big picture
squint overview --json
# 2. Explore the "Authentication" feature
squint features show authentication --json
# -> See 2 flows, 3 modules involved, 2 interactions
# 3. Drill into the registration flow
squint flows show user-registration --json
# -> See entry point handleRegister(), 2 interaction steps, definition trace
# 4. Understand the controller-to-service interaction
squint interactions show 1 --json
# -> See resolved symbols, module descriptions, related interactions
# 5. Examine the controller module's role
squint modules show project.api.controllers --json
# -> See 3 members, outgoing interactions, flows, features
# 6. Deep-dive into a specific symbol
squint symbols show handleRegister --json
# -> See module, relationships, dependencies, dependents, flows, interactions, source code
# 7. Or view everything for a file at once
squint symbols show --file src/controllers/auth.ts --json
# -> See all symbols, aggregated relationships, interactions, and flows for the filesquint parse ./src
squint stats
squint symbols understoodAutomatic (LLM):
squint symbols annotate -a purpose -a domain -a role
squint symbols verify
squint symbols understoodManual:
squint symbols ready --aspect purpose
squint symbols next --aspect purpose
squint symbols set purpose "Validates user credentials" --name authenticatesquint relationships annotate
squint relationships verifysquint symbols --domains
squint domains create auth --description "Authentication and authorization"
squint symbols set domain '["auth"]' --name validateTokensquint modules generate
squint modules verify
squint modules --treesquint interactions generate
squint interactions validate
squint interactions verifysquint flows generate
squint flows verify
squint flowssquint features generate
squint featuressquint overview
squint browseOr run the entire pipeline at once:
squint ingest ./srcsquint sync is designed for automated pipelines. It incrementally updates the SQLite database to match source code changes — no LLM required for the core AST sync.
# Initial setup (run once)
squint parse ./src
# On every push — incremental sync
squint sync ./srcsquint parse creates the database from scratch. squint sync detects new, modified, and deleted files via content hashing, then applies only the necessary changes inside a single atomic transaction. If the process is interrupted, the database rolls back to its previous consistent state.
Use --check for a dry-run that reports changes without modifying the database:
squint sync ./src --check| Exit code | Meaning |
|---|---|
| 0 | Database is in sync with source code |
| 1 | Database is out of sync (changes detected) |
This is useful as a CI gate to ensure the database was committed alongside code changes.
When running with --enrich, enrichment steps (LLM annotation, module assignment, etc.) may produce warnings. By default these are non-fatal. Use --strict to fail the pipeline:
squint sync ./src --enrich --strict| Exit code | Meaning |
|---|---|
| 0 | Sync and enrichment succeeded |
| 1 | Out of sync (with --check) |
| 2 | Enrichment completed with warnings (--strict mode) |
The .squint.db file must persist between CI runs. Common approaches:
- Commit to repository — simplest; the DB stays in sync with the code it describes
- CI cache — cache the DB keyed on a hash of the source directory;
squint synchandles staleness - Artifact storage — download from a previous run, sync, then re-upload
| Variable | Description |
|---|---|
SQUINT_DB_PATH |
Override the default database path (respected by all commands) |
NO_COLOR |
Disable colored output (standard convention) |
squint sync acquires an exclusive database lock during writes. If two processes attempt to sync concurrently, the second will wait up to 5 seconds before producing a clear SQLITE_BUSY error. In CI, this is rarely an issue since sync is typically a serial pipeline step.
- name: Sync squint database
run: squint sync ./src --check
# Fails if the committed DB is stale
- name: Update and enrich
run: squint sync ./src --enrich --strict
# Fails if enrichment has warningsThe SQLite database contains:
| Table | Description |
|---|---|
metadata |
Index metadata (version, timestamp, source directory) |
files |
Indexed files with content hash and modification time |
definitions |
All symbol definitions with position and export info |
imports |
File import/export relationships |
symbols |
Imported symbols linked to their definitions |
usages |
Where each symbol is used in the codebase |
definition_metadata |
Key-value annotations on symbols |
relationship_annotations |
Semantic descriptions of symbol relationships |
domains |
Registered domain tags with descriptions |
modules |
Hierarchical module tree (parent, slug, path, description) |
module_members |
Symbol-to-module assignments |
interactions |
Module-to-module edges (direction, weight, pattern, semantic) |
flows |
User journey flows with entry points and stakeholders |
flow_steps |
Ordered interaction steps within flows |
flow_definition_steps |
Ordered definition-level call edges within flows |
features |
Product-level feature groupings |
feature_flows |
Flow-to-feature associations |
pnpm install
pnpm run build # Build server + UI
pnpm run build:server # Build server only
pnpm test # Run tests
pnpm run test:watch # Watch mode
pnpm run test:coverage # Coverage report
pnpm run typecheck # Type checking
pnpm run lint # Biome linter
pnpm run lint:fix # Auto-fix lint issues
pnpm run format # Format with Biome
pnpm run dev ./src # Development mode (ts-node)This project uses conventional commits. All commit messages are validated by commitlint. Releases are automated via semantic-release on merge to main.
MIT