- JavaScript 52.9%
- TypeScript 47.1%
| .forgejo/workflows | ||
| .github/workflows | ||
| decisions | ||
| docs | ||
| examples | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
fallow-ts
fallow-ts is a deterministic TypeScript/JavaScript codebase-intelligence
checkpoint for AI agents and reviewers.
It does not execute the project under analysis. It reads source files and package metadata, builds a conservative import/export graph, and reports the static evidence an agent should inspect before claiming a change is clean.
The current alpha is intentionally narrow. It is not a full dead-code analyzer and it does not try to replace TypeScript, ESLint, Biome, Knip, dependency cruiser, tests, or human review. Today it focuses on three review signals:
- unresolved relative internal imports;
- deterministic circular dependencies;
- likely-unused internal exports, with package entrypoints protected.
Use it as a cheap read-only guardrail and prompt-shaping layer: it tells an agent what deserves attention, not what is safe to delete automatically.
Non-affiliation
fallow-ts is operator-owned experimental software. It is not the official
fallow-rs/fallow project and does not imply affiliation with upstream Fallow
unless it is explicitly upstreamed later.
Install
From a fresh source checkout:
npm install
npm run build
npm run release:smoke
After the package is published, the intended package-manager path is:
npm install --save-dev fallow-ts
npx fallow-ts analyze --root . --format text
Until then, use the source checkout commands below.
Alpha Adoption Path
For a first repository, use fallow-ts as a read-only checkpoint:
- Run the demo so the current finding language is familiar.
- Run JSON or
agent-contextoutput on the target repo. - Create a baseline before enforcing CI on an existing project.
- Treat findings as review prompts. Do not delete code because a static alpha report says it looks unused.
Good early fits:
- small JS/TS libraries;
- package entrypoint review before cleanup;
- PR checks that should catch new unresolved relative imports;
- agent loops that need compact context before editing.
Bad early fits:
- framework-heavy reachability claims;
- dependency policy enforcement;
- auto-fix workflows;
- security or production-safety decisions.
CLI
npm run build
node dist/cli.js analyze --root .
node dist/cli.js analyze --root . --format json --output /tmp/fallow-ts-report.json
node dist/cli.js analyze --root . --format agent-context
node dist/cli.js baseline create --root . --output fallow-ts-baseline.json
node dist/cli.js analyze --root . --baseline fallow-ts-baseline.json --fail-on warning
The default command is analyze, so this is equivalent:
node dist/cli.js --root . --format json
--format agent-context emits compact Markdown for AI agents. See
docs/agent-context.md.
baseline create stores current finding fingerprints for CI adoption.
--fail-on warning exits 1 only for unbaselined findings at or above the
threshold. See docs/baseline.md.
Copy-paste CI examples live in examples/ci/, with Forgejo
Actions first and GitHub Actions as a mirror template.
For AI-agent loops, prefer agent-context over full JSON unless the agent needs
machine-readable fields. It keeps the prompt focused on findings, public
entrypoints, graph evidence, and limitations.
Demo
A small demo project lives in examples/demo-project/.
It intentionally contains one missing relative import, one circular dependency,
and one likely-unused export candidate.
npm run build
node dist/cli.js analyze --root examples/demo-project --format text
node dist/cli.js analyze --root examples/demo-project --format agent-context
For adoption guidance, see docs/adoption.md.
For release checks, npm run release:smoke packs the local package, installs
that tarball into a temporary clean project, and verifies the installed CLI can
print help, analyze JSON, and create/use a baseline.
Current JSON Contract
The full v0 contract is documented in
docs/report-schema-v0.md. The example below shows
the current shape.
{
"schema": "fallow-ts.report",
"schema_version": "0.1",
"tool": "fallow-ts",
"version": "0.1.0-alpha.2",
"root": ".",
"summary": {
"files": 2,
"modules": 2,
"imports": 1,
"exports": 2
},
"package": {
"path": "package.json",
"name": "example",
"type": "module",
"packageManager": "npm@10.0.0",
"main": "./src/index.ts",
"module": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"imports": {},
"dependencies": {},
"devDependencies": {}
},
"workspaces": [
{
"source": "package.json",
"manager": "npm",
"patterns": ["packages/*"]
}
],
"graph": {
"internalEdges": [
{
"importer": "src/index.ts",
"source": "./helper",
"kind": "static",
"line": 1,
"target": "src/helper.ts",
"targetModule": "src/helper"
}
],
"unresolvedInternalEdges": [],
"publicEntryPoints": [
{
"source": "package.json#exports",
"entry": ".",
"target": "src/index.ts",
"targetModule": "src"
}
],
"unresolvedPublicEntryPoints": [],
"cycles": []
},
"findings": [],
"classification": {
"auto_safe": [],
"decision_needed": [],
"blocking": []
},
"modules": [
{
"path": "src/index.ts",
"module": "src/index",
"imports": [],
"exports": [
{ "name": "main", "kind": "function", "line": 1 }
]
}
],
"errors": [],
"limitations": [
"Regex-based first contract; no TypeScript AST yet.",
"Template literals and comments are masked before import parsing; code inside template interpolation is not analyzed yet.",
"Likely-unused exports are conservative cleanup candidates, not deletion-safety claims.",
"Does not infer dependency policy or full framework entry points yet."
]
}
Scope
Current scope:
- discover
.ts,.tsx,.js,.jsx,.mts,.cts,.mjs,.cjs - skip generated/build directories such as
node_modules,dist,coverage - parse common static import, export, dynamic import, and
require()forms - read root
package.jsonmetadata needed for later graph work - detect shallow npm/yarn/pnpm workspace declarations
- resolve conservative relative internal import edges
- represent simple package public entrypoints from
main,module, andexports - report high-confidence unresolved relative internal imports
- detect deterministic cycles in the resolved internal graph
- report conservative likely-unused internal runtime exports
- emit a compact
agent-contextformat for prompt use - ignore import-looking text inside comments and template literals
- produce stable JSON and a compact text summary
Out of scope for the initial bootstrap:
- deletion-safety claims for unused export/file cleanup
- framework plugins
- package dependency policy
- MCP server
- auto-fix
- parity with
fallow-py
Why start this small?
Because the useful part is the contract: deterministic evidence first, analyzer
ambition second. fallow-py learned that public credibility comes from a tool
that can dogfood itself, explain its limitations, and fail honestly.