ts-inspect-cli
v0.1.2
Published
A read-only TypeScript semantic inspection CLI built on ts-morph
Maintainers
Readme
ts-inspect
A read-only TypeScript semantic inspection CLI built on ts-morph. It answers compiler-derived questions about any TypeScript repository (params, return, properties, type, signature, definition, at, imports, exports) with compact, deterministic JSON intended for consumption by AI coding agents.
Sponsor
Brainy Builds
ts-inspect is sponsored by Brainy Builds. Thank you for supporting the project!
Purpose
Agents often need exact type information but should not dump source files into context. ts-inspect returns small semantic summaries - parameter lists, resolved types, object property contracts, signatures, declaration locations - computed by the TypeScript compiler through ts-morph, not by grep or string parsing.
Install
npm install -D ts-inspect-cliThe package ships a ts-inspect bin and a programmatic API. It requires Node.js >=20.19.0.
Rule / Skill auto-install for AI agents
npm install -D ts-inspect-cli runs a postinstall hook that installs agent guidance into the consumer project:
.cursor/rules/ts-inspect.mdc- Cursor rule.claude/skills/ts-inspect/SKILL.md- Claude Code skillAGENTS.md- appended between<!-- ts-inspect:start -->/<!-- ts-inspect:end -->sentinels for Codex, Gemini CLI, and other Agent Skills-compatible tools
To skip auto-install:
npm install -D ts-inspect-cli --ignore-scriptsTo re-run setup manually:
npx ts-inspect setup [flags]Flags: --cursor, --claude, --agents (select targets; default: all), --force (overwrite even if differs), --silent / --yes (never prompt, for CI / postinstall), --dry-run (print what would be written, write nothing).
Supported IDEs and agents: Cursor, Claude Code, Codex, Gemini CLI, GitHub Copilot, OpenCode, and any tool that follows the Agent Skills open standard (https://agentskills.io/).
The generated rule/skill files are intended to be committed to the consumer repo so the whole team shares the same agent guidance.
CLI usage
ts-inspect <command> <symbol|location|file>If the bin is not on PATH (for example inside a workspace), use npx ts-inspect or the local script form:
npx ts-inspect <command> <symbol|location|file>The CLI loads the project from the repository's tsconfig.json (discovered by walking up from the current working directory), so all configured compilerOptions.paths aliases resolve correctly through ts-morph. No manual alias parsing is performed.
Read-only guarantee
ts-inspect never modifies source files. It only inspects, resolves, navigates, and describes. It never calls save, emit, formatText, organizeImports, remove, rename, or any mutation API. Files added to the in-memory project (for at/imports/exports) are loaded in memory only; nothing is written to disk.
Commands
| Command | Argument | Purpose |
|---|---|---|
| params | symbol name | Parameters of a function-like symbol, with object-like parameters expanded to depth 1. |
| return | symbol name | Resolved return type, async status, Promise payload when applicable. |
| properties | symbol name | Properties of an object-like type (interface, type alias, class, intersection). Unions return structured members, never a flattened contract. |
| type | symbol name OR file:line:column | Resolved type of a symbol or of the node at a location. |
| signature | symbol name OR file:line:column | All call signatures (overloads preserved) plus construct signatures. |
| definition | symbol name | One or more declarations: kind, repo-relative path, 1-based line/column, external flag. |
| at | file:line:column | Bounded semantic snapshot at a precise location: node kind, bounded node text, symbol, type, definitions, call signatures, properties, enclosing declaration. |
| imports | file path | Direct import declarations: module specifier, external/internal, default/namespace/named, type-only, resolved path, alias usage. |
| exports | file path | Named exports, re-exports, and the default export. |
Location syntax
relative/path/to/file.ts:LINE:COLUMN (also .tsx / .mts / .cts). Line and column are 1-based. Example:
ts-inspect at src/hooks/notifyIndexNow.ts:10:15Malformed locations, missing files, and out-of-range lines/columns produce a structured error.
JSON output shape
Stdout is exclusively the machine-readable JSON envelope. Diagnostics never mix into stdout; there are no debug logs by default.
Success:
{
"ok": true,
"command": "params",
"query": { "symbol": "getButtonStyle" },
"result": { "...": "..." }
}Failure:
{
"ok": false,
"command": "params",
"query": { "symbol": "getButtonStyle" },
"error": { "code": "SYMBOL_NOT_FOUND", "message": "...", "candidates": null }
}Stable error codes: INVALID_COMMAND, INVALID_ARGUMENT, INVALID_LOCATION, FILE_NOT_FOUND, SOURCE_FILE_NOT_FOUND, SYMBOL_NOT_FOUND, AMBIGUOUS_SYMBOL, TYPE_NOT_OBJECT_LIKE, SIGNATURE_NOT_FOUND, DECLARATION_NOT_FOUND, UNSUPPORTED_DECLARATION, PROJECT_INITIALIZATION_FAILED, INSPECTION_FAILED.
Exit codes: 0 on success, 1 on any failure.
Symbol ambiguity behavior
Bare-name lookup across a large repository is inherently ambiguous. ts-inspect never uses "first match wins". When more than one project declaration matches a name, it returns AMBIGUOUS_SYMBOL with a bounded candidate list (file, line, column, kind):
{
"ok": false,
"command": "definition",
"query": { "symbol": "handleSubmit" },
"error": {
"code": "AMBIGUOUS_SYMBOL",
"message": "Multiple declarations named handleSubmit were found. Use \"at FILE:LINE:COLUMN\" for a precise lookup.",
"candidates": [
{ "name": "handleSubmit", "kind": "FunctionDeclaration", "location": { "file": "src/components/A/Form.tsx", "line": 42, "column": 1 }, "external": false },
{ "name": "handleSubmit", "kind": "FunctionDeclaration", "location": { "file": "src/components/B/Form.tsx", "line": 57, "column": 1 }, "external": false }
]
}
}For precise, unambiguous queries, prefer location-based forms (at, type FILE:LINE:COLUMN, signature FILE:LINE:COLUMN).
Paths
All output paths are repository-relative POSIX paths (src/hooks/notifyIndexNow.ts). Absolute machine-specific paths are never emitted in normal output.
Programmatic API
The package exports runTsInspect for programmatic use. It performs no stdout writes and sets no exit code:
import {
runTsInspect,
} from "ts-inspect-cli";
const result = await runTsInspect([
"params",
"getButtonStyle",
]);The result is the same envelope the CLI prints: { ok: true, command, query, result } or { ok: false, command, query, error }.
Overloads, unions, generics
- Overloaded functions: every call signature is returned; none are collapsed.
- Union types:
propertiesreturns structured members, each with its own properties. It never merges a union into a misleading required-property contract. - Generics: type parameters are preserved; a generic parameter's type is reported as its declared type parameter, not
unknown. - Promise detection is semantic (
Promisesymbol + type arguments), never string parsing of type text.
Known limitations
references,implementations,callers,calleesare NOT implemented. Accurate implementation/call-graph analysis in TypeScript is complicated by structural typing, aliases, higher-order functions, and overloads; a code-graph indexer such as SCIP is better suited to call-graph navigation.- Name-only lookups can be ambiguous by design; the CLI reports ambiguity rather than guessing.
- External dependency declarations are reported as bounded metadata only; they are never recursively expanded.
- The tool inspects project source statically; it never executes application code or imports runtime modules.
Performance considerations
Within a single invocation the project is initialized exactly once and reused across the command. Each command performs the narrowest lookup it can; no persistent caches are introduced.
Intended agent usage
| Need | Tool |
|---|---|
| Exact TypeScript type information | ts-inspect |
| Function object parameters | ts-inspect params |
| Resolved return type | ts-inspect return |
| Object/interface properties | ts-inspect properties |
| Known exact file location | ts-inspect at FILE:LINE:COLUMN |
| AST structural pattern | ast-grep (if installed) |
| Plain text/string search | ripgrep |
| Compiler validation | tsc --noEmit |
| Lint/style enforcement | ESLint |
ts-inspect does not compete with dependency-graph tools, dead-code analyzers, or bulk-refactor tooling.
Development
npm install
npm run typecheck
npm run lint:fix
npm run buildnpm run build bundles src/ into dist/ via tsup (esbuild). The ESM bundle inlines all @-prefixed path aliases and extensionless internal imports, so the emitted JavaScript resolves under plain Node without any runtime loader or post-processing. src/index.ts (library API) and src/ts-inspect.ts (CLI bin) are the two bundle entries.
Links
- GitHub: https://github.com/Brainy-Builds/ts-inspect-cli
- npm: https://www.npmjs.com/package/ts-inspect-cli
- ts-morph: https://ts-morph.com
- Agent Skills open standard: https://agentskills.io/
License
MIT
