Skip to content

zbigniewsobiecki/squint

Repository files navigation

Squint

AST + LLM driven codebase analysis and visualization.

npm version CI License: MIT

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.


Table of Contents


Installation

End users

# Global install
npm install -g @zbigniewsobiecki/squint

# Or run directly
npx @zbigniewsobiecki/squint --help

Contributors

git clone https://github.com/zbigniewsobiecki/squint.git
cd squint
pnpm install
pnpm run build

Quick Start

Full automated pipeline (parse, annotate, verify, generate modules/interactions/flows/features):

squint ingest ./src

Manual 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

Command Reference

Command Summary

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 wins

Top-Level Commands

squint parse — Index a Codebase

Scans 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

squint ingest — Full Analysis Pipeline

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

squint browse — Interactive Code Browser

Launches a web-based visualization of the indexed codebase.

squint browse [-p <port>] [--no-open]

squint overview — Compact Codebase Overview

Shows a complete codebase overview: stats, features, module tree, and file tree.

squint overview [flags]

squint stats — Database Statistics

Shows aggregate statistics and pipeline progress: parsed counts, annotation coverage, module assignment, interactions, flows, and features.

squint stats [--json]

squint gaps — Find Incomplete Entities

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

symbols

Manage symbol definitions (functions, classes, variables, types, interfaces, enums).

squint symbols list

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

squint symbols show

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.

squint symbols set

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.

squint symbols unset

Removes a metadata key from a symbol.

squint symbols unset <key> --name <symbol>

squint symbols annotate

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"

squint symbols verify

Verifies existing symbol annotations using LLM and flags incorrect ones.

squint symbols verify [flags]

squint symbols ready

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]

squint symbols next

Shows the next symbol ready to understand with its full source code.

squint symbols next --aspect <key> [-c <count>] [-m <max-lines>] [--json]

squint symbols deps

Shows what other symbols a given symbol depends on, with annotation status.

squint symbols deps <name> [-a <aspect>] [--json]

squint symbols prereqs

Shows unmet dependencies in topological order — what to understand before a target symbol.

squint symbols prereqs <name> --aspect <key>

squint symbols understood

Shows understanding coverage statistics per aspect.

squint symbols understood [-a <aspect>] [-k <kind>] [-f <file>] [--json]

relationships

Manage semantic annotations on call/use edges between symbols.

squint relationships list

Lists all annotated relationships. Default when running squint relationships.

squint relationships [--from <symbol>] [--to <symbol>] [--count] [--json]

squint relationships show

Shows detail for a relationship between two definitions.

squint relationships show --from <symbol> --to <symbol>

squint relationships set

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>

squint relationships unset

Removes a relationship annotation.

squint relationships unset --from <source> --to <target>

squint relationships annotate

Uses an LLM to annotate relationships between symbols.

squint relationships annotate [flags]

squint relationships verify

Verifies existing relationship annotations using LLM.

squint relationships verify [flags]

squint relationships next

Shows the next unannotated relationship with context (both symbols' metadata, other relationships, source code).

squint relationships next [--count <n>] [--from <symbol>] [--json]

domains

Manage business/architectural domain tags that group related symbols.

squint domains list

Lists registered domains with symbol counts. Default when running squint domains.

squint domains [--unregistered] [--json]

squint domains show

Shows domain details including assigned symbols.

squint domains show <name>

squint domains create

Registers a new domain.

squint domains create <name> [--description "..."]

squint domains update

Updates a domain description.

squint domains update <name> --description "..."

squint domains delete

Removes a domain from the registry.

squint domains delete <name> [--force]

squint domains sync

Bulk-registers all domains currently in use by symbols.

squint domains sync

squint domains rename

Renames a domain in the registry and updates all symbol metadata.

squint domains rename <old-name> <new-name>

squint domains merge

Merges the source domain into the target, updating all symbols.

squint domains merge <from-domain> <into-domain>

modules

Manage architectural module hierarchy. Modules use dot-notation paths (e.g., project.backend.services.auth).

squint modules list

Lists all modules with member counts. Default when running squint modules.

squint modules [--tree] [--json]

squint modules show

Shows module details including all members.

squint modules show <name> [--json]

squint modules create

Creates a new module under a parent.

squint modules create <name> [flags]

squint modules update

Updates a module name or description.

squint modules update <name> [flags]

squint modules delete

Deletes a module.

squint modules delete <name>

squint modules assign

Assigns a symbol to a module.

squint modules assign --module <module> --name <symbol>

squint modules unassign

Removes a symbol from its module.

squint modules unassign --name <symbol>

squint modules generate

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

squint modules verify

Verifies existing module assignments using LLM.

squint modules verify [flags]

squint modules prune

Removes empty leaf modules.

squint modules prune

interactions

Manage module-to-module interaction edges derived from the call graph.

squint interactions list

Lists all detected module interactions. Default when running squint interactions.

squint interactions [--json]

squint interactions show

Shows details for a specific interaction.

squint interactions show <id> [--json]

squint interactions create

Creates a new module interaction.

squint interactions create [flags]

squint interactions update

Updates an interaction.

squint interactions update <id> [flags]

squint interactions delete

Deletes an interaction.

squint interactions delete <id>

squint interactions generate

Detects module interactions from the call graph and generates semantics using LLM.

squint interactions generate [--force] [--dry-run] [-m <model>] [--json]

squint interactions validate

Validates LLM-inferred interactions using deterministic checks against the call graph.

squint interactions validate [flags]

squint interactions verify

Verifies existing interactions using LLM.

squint interactions verify [flags]

flows

Manage user journey flows that trace paths through module interactions.

squint flows list

Lists all detected flows. Default when running squint flows.

squint flows [--domain <domain>] [--json]

squint flows show

Shows flow details with interaction steps.

squint flows show <name> [--json]

squint flows create

Creates a new flow.

squint flows create <name> [flags]

squint flows update

Updates a flow.

squint flows update <name> [flags]

squint flows delete

Deletes a flow.

squint flows delete <name>

squint flows add-step

Adds an interaction step to a flow.

squint flows add-step --flow <flow> --interaction <interaction-id> [--step-order <n>]

squint flows remove-step

Removes a step from a flow.

squint flows remove-step --flow <flow> --step-order <n>

squint flows trace

Traces the call graph from a symbol, showing reachable symbols as a tree.

squint flows trace --name <symbol> [--depth <n>] [--json]

squint flows generate

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

squint flows verify

Verifies existing flows using LLM.

squint flows verify [flags]

features

Manage product-level feature groupings of flows.

squint features list

Lists all features with flow counts. Default when running squint features.

squint features [--json]

squint features show

Shows feature details with associated flows.

squint features show <name> [--json]

squint features create

Creates a new feature.

squint features create <name> [flags]

squint features update

Updates a feature.

squint features update <name> [flags]

squint features delete

Deletes a feature.

squint features delete <name>

squint features assign

Assigns a flow to a feature.

squint features assign --feature <feature> --flow <flow>

squint features unassign

Removes a flow from a feature.

squint features unassign --feature <feature> --flow <flow>

squint features generate

Groups flows into product-level features using LLM.

squint features generate [--force] [--dry-run] [-m <model>] [--json]

files

Explore the indexed file structure.

squint files list

Lists all indexed files. Default when running squint files.

squint files [--stats]

squint files show

Shows file details including definitions and imports.

squint files show <path>

squint files imports

Lists files imported by a specific file.

squint files imports <path>

squint files imported-by

Lists files that import a specific file.

squint files imported-by <path>

squint files orphans

Finds files with no incoming imports.

squint files orphans

hierarchy

Shows 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 implementations

process-groups

squint process-groups list

Lists process groups (connected components in the import graph).

squint process-groups

AI Agent Usage

Squint 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.

Exploration Strategy

The recommended approach is a top-down drill-down: start with the highest-level overview and progressively narrow focus into specific entities.

  1. Start with overview: squint overview --json returns aggregate stats, the features list, the module tree, and the file tree. This gives the big picture.
  2. Drill into features: squint features show <slug> --json returns enriched flows (with stepCount, stakeholder, entryPath), modules involved, interactions, and stats.
  3. Drill into flows: squint flows show <slug> --json returns features, an entry point (with definition details and metadata), ordered interaction steps, modules involved, and the definition trace (function-level call chain).
  4. Drill into interactions: squint interactions show <id> --json returns module descriptions, resolved symbols (matched to definitions), related interactions from the same source module, flows using this interaction, and features.
  5. Drill into modules: squint modules show <path> --json returns parent, children, outgoing/incoming interactions, flows, features, and all member symbols.
  6. Drill into symbols: squint symbols show <name> --json returns 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> --json aggregates all symbols, relationships, interactions, and flows for every symbol in the file — useful for understanding a file's full role.
  7. Drill into files: squint files show <path> --json returns definitions (enriched with module and metadata), imports, imported-by, and relationships.
  8. Drill into relationships: squint relationships show --from <id> --to <id> --json returns metadata for both symbols, module context, the module interaction, and flows.
  9. Drill into domains: squint domains show <name> --json returns symbols, module distribution, and intra-domain relationships.

Show Command JSON Schemas

Each show command returns a JSON object. The schemas below document the top-level keys and their types.

squint features show <id-or-slug> --json

{
  "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 } }
}

squint flows show <identifier> --json

{
  "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": "..." }
  ]
}

squint interactions show <id> --json

{
  "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" }]
}

squint modules show <name> --json

{
  "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 }]
}

squint symbols show <name> --json

{
  "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 }]
}

squint symbols show --file <path> --json

{
  "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" }]
}

squint files show <path> --json

{
  "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": "..." }]
}

squint relationships show --from <id> --to <id> --json

{
  "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" }]
}

squint domains show <name> --json

{
  "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": "..." }]
}

Example Drill-Down Session

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 file

Understanding Workflow

Phase 1: Index and Explore

squint parse ./src
squint stats
squint symbols understood

Phase 2: Annotate Symbols

Automatic (LLM):

squint symbols annotate -a purpose -a domain -a role
squint symbols verify
squint symbols understood

Manual:

squint symbols ready --aspect purpose
squint symbols next --aspect purpose
squint symbols set purpose "Validates user credentials" --name authenticate

Phase 3: Annotate Relationships

squint relationships annotate
squint relationships verify

Phase 4: Organize Domains

squint symbols --domains
squint domains create auth --description "Authentication and authorization"
squint symbols set domain '["auth"]' --name validateToken

Phase 5: Detect Modules

squint modules generate
squint modules verify
squint modules --tree

Phase 6: Detect Interactions

squint interactions generate
squint interactions validate
squint interactions verify

Phase 7: Trace Flows

squint flows generate
squint flows verify
squint flows

Phase 8: Group Features

squint features generate
squint features

Phase 9: Overview

squint overview
squint browse

Or run the entire pipeline at once:

squint ingest ./src

CI/CD Integration

squint 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.

The parse → sync Lifecycle

# Initial setup (run once)
squint parse ./src

# On every push — incremental sync
squint sync ./src

squint 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.

--check as a CI Gate

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.

--strict for Enrichment Quality Gates

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)

Database Persistence Strategies

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 sync handles staleness
  • Artifact storage — download from a previous run, sync, then re-upload

Environment Variables

Variable Description
SQUINT_DB_PATH Override the default database path (respected by all commands)
NO_COLOR Disable colored output (standard convention)

Concurrency

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.

Example GitHub Actions Workflow

- 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 warnings

Database Schema

The 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

Development

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.

License

MIT

About

AST meets LLM

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors