한국어 | English | 中文 | Español | 日本語
죽은 코드를 가차 없이 찾아냅니다.
라이선스 · 기여 가이드 · 행동 강령 · 보안 · 후원
Kratos는 JavaScript/TypeScript 프로젝트에서 사용되지 않는 파일, 끊어진 import, 사용되지 않는 export, 고립된 모듈을 찾아 리포트로 남기는 CLI 도구입니다. 현재 구조는 Rust core/CLI와 npm launcher를 결합하며, npm 패키지 @jeremyfellaz/kratos가 플랫폼별 native addon 패키지를 선택적으로 불러 실행합니다.
Kratos는 자동 삭제 도구라기보다 안전한 정리 흐름을 위한 분석 도구입니다. clean은 기본적으로 dry-run이며, 실제 삭제는 리포트를 검토한 뒤 --apply를 명시했을 때만 수행합니다.
- 사용되지 않는 파일과 고립된 component/module 후보 탐지
- 끊어진 내부 import 탐지
- 사용되지 않는 export와 import 후보 탐지
- Next.js
app//pages/route entrypoint 휴리스틱 tsconfig.json/jsconfig.json의baseUrl,pathsalias 해석package.json의main,module,types,bin,exportsentrypoint 해석package.jsonscripts, GitHub Actions workflow/composite actionrun명령이 실행하는 로컬 script entrypoint 보호scripts/verify-*,scripts/*smoke*,scripts/*validation*형태의 수동 검증 script 보호- 스캔 대상 source tree 안의
*.test.*,*.spec.*,src/__tests__/**테스트 파일을 삭제 후보에서 제외하고 테스트 import edge 반영 - Next.js framework-consumed export, 인식 가능한 dynamic import wrapper, 순수 re-export barrel 보수 처리
- 저장된 리포트 요약, JSON, Markdown 출력
- 두 리포트 간 finding 변화 비교
- 신뢰도 기준값을 적용한 안전 삭제 후보 미리보기
패키지 사용자 기준 기본 실행 방식은 npx입니다.
npx @jeremyfellaz/kratos scan ./my-app
npx @jeremyfellaz/kratos report ./my-app
npx @jeremyfellaz/kratos report ./my-app --format md
npx @jeremyfellaz/kratos clean ./my-app --min-confidence 0.9리포트를 확인한 뒤 실제 삭제가 필요할 때만 --apply를 붙입니다.
npx @jeremyfellaz/kratos clean ./my-app --apply --min-confidence 0.9두 시점의 리포트를 비교할 수도 있습니다.
npx @jeremyfellaz/kratos scan ./my-app --output .kratos/before.json
# 코드를 정리하거나 브랜치를 바꾼 뒤
npx @jeremyfellaz/kratos scan ./my-app --output .kratos/after.json
npx @jeremyfellaz/kratos diff ./my-app/.kratos/before.json ./my-app/.kratos/after.jsonscan --output에 상대 경로를 넘기면 스캔 대상 root 기준으로 해석됩니다. 기본 저장 위치는 <root>/.kratos/latest-report.json입니다.
프로젝트를 분석하고 report JSON을 저장합니다.
root를 생략하면 현재 작업 디렉터리를 스캔합니다.--output path는 report 저장 위치를 지정합니다.--json은 콘솔 요약 대신 전체 JSON report를 stdout으로 출력합니다.- 기본 출력 경로는
<root>/.kratos/latest-report.json입니다.
저장된 report를 사람이 읽기 쉬운 형식 또는 원본 JSON으로 출력합니다.
summary는 기본 콘솔 요약입니다.json은 저장된 report JSON을 pretty-print합니다.md는 공유하기 쉬운 Markdown report를 출력합니다.- 입력이 프로젝트 root이면
.kratos/latest-report.json을 자동으로 찾습니다.
두 report의 finding 변화를 비교합니다.
- 기본 형식은
summary입니다. json은 introduced/resolved/persisted finding을 machine-readable 형식으로 출력합니다.md는 리뷰나 이슈에 붙이기 쉬운 Markdown diff를 출력합니다.- 각 입력은 report 파일 경로 또는 프로젝트 root가 될 수 있습니다.
삭제 후보를 preview하거나 실제로 삭제합니다.
- 기본 동작은 dry-run입니다.
--apply를 붙인 경우에만 파일 삭제를 수행합니다.--min-confidence value는0.0부터1.0까지의 confidence threshold입니다.--min-confidence를 생략하면kratos.config.json의thresholds.cleanMinConfidence를 사용하고, 설정이 없으면0.0을 사용합니다.
fixtures/demo-app을 스캔하면 요약 출력은 아래와 같은 형태입니다.
Kratos scan complete.
Impact: 6 actionable findings: 1 broken import, 2 cleanup candidates, 3 dead exports.
Best next move: Fix broken imports before deleting files.
Root: <root>
Files scanned: 5
Entrypoints: 1
Broken imports: 1
Orphan files: 2
Dead exports: 3
Unused imports: 0
Route entrypoints: 1
Deletion candidates: 2
Saved report: <root>/.kratos/latest-report.json
Next steps:
- Preview cleanup: kratos clean <root>/.kratos/latest-report.json
- Shareable markdown: kratos report <root>/.kratos/latest-report.json --format md
Broken imports:
- src/lib/broken.ts -> ./missing-helper
Top cleanup candidates:
- src/components/DeadWidget.tsx (confidence 0.92, Component-like module has no inbound references.)
- src/lib/broken.ts (confidence 0.88, Module has no inbound references and is not treated as an entrypoint.)
Orphan files:
- src/components/DeadWidget.tsx
- src/lib/broken.ts
Dead exports:
- src/components/DeadWidget.tsx#DeadWidget
- src/lib/broken.ts#brokenFeature
- src/lib/math.ts#multiply
clean --min-confidence 0.9는 신뢰도 기준값을 통과한 삭제 후보와 제외된 후보를 나눠 보여줍니다.
Kratos clean dry run.
Deletion targets: 1
- <root>/src/components/DeadWidget.tsx (confidence 0.92, Component-like module has no inbound references.)
Threshold-skipped targets: 1
- <root>/src/lib/broken.ts (confidence 0.88, Module has no inbound references and is not treated as an entrypoint.)
Re-run with --apply to delete these files.
동일한 두 리포트를 비교하면 새로 생기거나 해결된 탐지 결과 없이 유지 중인 개수만 표시됩니다.
Kratos diff complete.
Before: <before-report>
After: <after-report>
Broken imports: introduced 0, resolved 0, persisted 1
Orphan files: introduced 0, resolved 0, persisted 2
Dead exports: introduced 0, resolved 0, persisted 3
Unused imports: introduced 0, resolved 0, persisted 0
Route entrypoints: introduced 0, resolved 0, persisted 1
Deletion candidates: introduced 0, resolved 0, persisted 2
Totals: introduced 0, resolved 0, persisted 9
현재 scan은 schemaVersion: 2 report를 생성합니다.
{
"schemaVersion": 2,
"summary": {
"filesScanned": 5,
"entrypoints": 1,
"brokenImports": 1,
"orphanFiles": 2,
"deadExports": 3,
"unusedImports": 0,
"routeEntrypoints": 1,
"deletionCandidates": 2
}
}findings에는 brokenImports, orphanFiles, deadExports, unusedImports, routeEntrypoints, deletionCandidates가 들어갑니다. graph.modules에는 분석된 모듈 경로, entrypoint 여부, import/export 개수가 기록됩니다.
프로젝트 root에 kratos.config.json을 둘 수 있습니다. JSONC 스타일 주석과 trailing comma를 허용합니다.
{
"ignore": ["storybook-static", "generated"],
"ignorePatterns": ["src/generated/**", "!src/generated/keep.ts"],
"keepPatterns": ["scripts/manual-*.mjs"],
"entry": ["src/bootstrap.ts"],
"roots": ["src", "app", "pages"],
"thresholds": {
"cleanMinConfidence": 0.85
},
"suppressions": [
{
"kind": "deadExport",
"file": "src/components/LazyCard.tsx",
"export": "default",
"reason": "Loaded dynamically by route metadata."
},
{
"kind": "brokenImport",
"file": "src/legacy/shim.ts",
"source": "./generated-shim",
"reason": "Generated at deploy time."
}
]
}ignore: 기본 ignore 목록에 추가할 디렉터리 이름입니다.ignorePatterns:.gitignore스타일 경로 패턴입니다.!로 예외를 둘 수 있습니다.- Kratos는 기본 ignore 디렉터리 이후 프로젝트 root의
.gitignore를 자동으로 읽고, 그 다음ignorePatterns를 적용해 예외/override를 줄 수 있습니다. keepPatterns:.gitignore스타일 경로 패턴입니다. 매칭된 파일은 스캔에서 제외하지 않고 orphan/deletion candidate에서만 보호합니다.entry: entrypoint로 강제 지정할 프로젝트 root 기준 상대 파일 경로입니다.roots: 스캔 범위를 제한할 프로젝트 root 기준 상대 디렉터리입니다.thresholds.cleanMinConfidence:clean의 기본 신뢰도 기준값입니다.suppressions: 의도적으로 무시할 탐지 결과입니다.kind는brokenImport,orphanFile,deadExport,unusedImport,deletionCandidate중 하나입니다.
Kratos는 .kratos/suppressions.json이 있으면 같은 suppression 형식으로 함께 읽습니다. file 값은 프로젝트 root 기준 상대 경로여야 합니다.
필수 조건:
- Node.js 18+
- npm 9+
- Rust stable toolchain
설치:
npm install권장 검증:
cargo test --workspace
npm run verify
npm run smoke저장소 checkout에서는 published native addon 패키지가 없을 수 있으므로 npx @jeremyfellaz/kratos ...보다 아래 명령이 안전합니다.
npm run scan -- ./fixtures/demo-app
npm run report -- ./fixtures/demo-app/.kratos/latest-report.json
npm run clean -- ./fixtures/demo-app/.kratos/latest-report.json
cargo run -p kratos-cli -- diff ./fixtures/demo-app ./fixtures/demo-app- root npm package는
@jeremyfellaz/kratos입니다. - CLI binary 이름은
kratos입니다. - platform addon package는 macOS arm64/x64, Linux x64/arm64, Windows x64를 대상으로 합니다.
- root package의
optionalDependencies는 같은 릴리스 버전의 platform addon package를 가리킵니다. - raw checkout에서는 native addon이 없을 수 있지만, 릴리스 패키지에서는 launcher가 현재 플랫폼에 맞는 addon을 로드합니다.
릴리스는 vX.Y.Z 또는 vX.Y.Z-prerelease.N 형태의 semver tag를 기준으로 움직입니다.
Manual Release Bumpworkflow는 대상 버전으로package.json과 platformoptionalDependencies버전을 맞추는 version-only PR을 준비합니다.- tag를 만들기 전에는 같은 commit에서
cargo test --workspace,npm run verify, native packaging CI가 통과해야 합니다. Release Publishworkflow는 지정된 tag ref를 checkout하고 Node package 검증, Rust workspace test, platform native artifact build를 수행합니다.- platform addon npm package를 먼저 pack/smoke/publish하고, 마지막에 root package를 publish한 뒤 GitHub Release를 생성하거나 갱신합니다.
Release Published Follow-upworkflow는 게시된 릴리스에 대응하는 publish run 성공 여부와 릴리스 asset 존재 여부를 감사합니다. 이 workflow는 publish를 다시 실행하지 않습니다.
release tag push, npm publish, GitHub Release 게시 같은 작업은 유지보수자 확인 후에만 진행합니다.
Kratos는 MIT 라이선스로 공개되는 오픈소스 프로젝트입니다.
- 버그 제보와 기능 제안은 GitHub Issues를 사용해 주세요.
- 보안 이슈는 공개 이슈로 올리지 말고 SECURITY.md의 절차를 따라 주세요.
- 기여 전에는 CONTRIBUTING.md와 CODE_OF_CONDUCT.md를 확인해 주세요.
- 프로젝트 유지에 도움이 되고 싶다면 GitHub Sponsors를 통해 후원할 수 있습니다.
Kratos는 보수적인 정적 분석과 휴리스틱을 함께 사용합니다. 현재 구현은 알려진 Next.js route export, package/workflow/action script entrypoint, 수동 검증 script, tooling config, 테스트 파일, 인식 가능한 React.lazy/next/dynamic wrapper, 순수 re-export barrel을 보호합니다. 그래도 custom runtime entrypoint, 생성 파일, 프로젝트 고유 loader는 정적 분석 밖에 있을 수 있으므로 필요하면 entry, keepPatterns, suppression으로 명시하고, 남은 deletion candidate는 --apply 전에 report와 diff로 확인하세요.