earendil-works/pi
AI agent toolkit: unified LLM API, agent loop, TUI, coding agent CLI
The score is jscpd's own --health model: markup, data and text left out, tests kept. The numbers below are the trending scan's.
Most complex files
- packages/coding-agent/src/modes/interactive/interactive-mode.ts1500 cx
- packages/ai/scripts/generate-models.ts961 cx
- packages/coding-agent/src/core/agent-session.ts705 cx
- packages/chord/src/delta/tracker.ts692 cx
- packages/coding-agent/src/core/package-manager.ts594 cx
- packages/coding-agent/src/core/export-html/template.js562 cx
- packages/ai/src/api/openai-completions.ts524 cx
- packages/tui/src/tui-alt-screen.ts520 cx
- packages/durable/test/harness-structured.test.ts461 cx
- packages/tui/src/components/editor.ts456 cx
Dead code 0.49% unused · 22 findings
- packages/evals/src/harness.tsunused-file
- .pi/extensions/prompt-url-widget.tsunused-file
- packages/evals/evals/tui.docs.eval.tsunused-file
- packages/evals/evals/acme-server.tsunused-file
- packages/evals/evals/configured-runtime.tsunused-file
- packages/ai/src/api/cloudflare-ai-binding.tsunused-file
- packages/evals/evals/custom-provider.docs.eval.tsunused-file
- packages/evals/evals/documentation-audit.eval.tsunused-file
- packages/evals/evals/openai-provider.docs.eval.tsunused-file
- packages/evals/evals/extensions.docs.eval.tsunused-file
The code number leaves out tests, fixtures, docs, examples, data files, styles, translations and vendored code, and 43 generated files: packages/ai/src/models.generated.ts, packages/ai/src/providers/amazon-bedrock.models.ts, packages/ai/src/providers/ant-ling.models.ts, packages/ai/src/providers/anthropic.models.ts, packages/ai/src/providers/azure-openai-responses.models.ts, packages/ai/src/providers/baseten.models.ts, packages/ai/src/providers/cerebras.models.ts, packages/ai/src/providers/cloudflare-ai-gateway.models.ts, packages/ai/src/providers/cloudflare-workers-ai.models.ts, packages/ai/src/providers/deepseek.models.ts, packages/ai/src/providers/fireworks.models.ts, packages/ai/src/providers/github-copilot.models.ts, packages/ai/src/providers/google-vertex.models.ts, packages/ai/src/providers/google.models.ts, packages/ai/src/providers/groq.models.ts, packages/ai/src/providers/huggingface.models.ts, packages/ai/src/providers/kimi-coding.models.ts, packages/ai/src/providers/meta.models.ts, packages/ai/src/providers/minimax-cn.models.ts, packages/ai/src/providers/minimax.models.ts and 23 more.
Largest clones in the code
- 655 lines in 2 placestypescript5,420 tokenspackages/coding-agent/src/experimental/durable/tui.ts:1–655packages/coding-agent/src/experimental/vacation/tui.ts:1–655
1import type { AssistantMessage, ToolResultMessage, Usage, UserMessage } from "@earendil-works/pi-ai"; 2import type { 3 ConversationId, 4 EntryRecord, 5 InboxState, 6 LiveState, 7 TaskGraph, 8 TaskGraphNode, 9 UsageState, 10} from "@earendil-works/pi-durable";First 10 of 655 lines.
- 202 lines in 2 placestypescript1,703 tokenspackages/coding-agent/src/experimental/durable/runtime.ts:152–353packages/coding-agent/src/experimental/vacation/runtime.ts:149–350
152 cwd: location.cwd, 153 ...(initial?.model === undefined ? {} : { model: initial.model }), 154 ...(initial?.thinkingLevel === undefined ? {} : { thinkingLevel: initial.thinkingLevel }), 155 }, 156}); 157const label = (id: ConversationId): string => (id === root.id ? "main" : `subagent ${id}`); 158const opened = harness; 159const summaries: ConversationSummary[] = []; 160let cursor: Cursor | undefined; 161do {First 10 of 202 lines.
- 256 lines in 2 placestypescript1,499 tokenspackages/coding-agent/src/core/tools/edit-diff.ts:244–499packages/durable/src/tools/edit-diff.ts:245–500
244 }; 245} 246 247function countOccurrences(content: string, oldText: string): number { 248 const fuzzyContent = normalizeForFuzzyMatch(content); 249 const fuzzyOldText = normalizeForFuzzyMatch(oldText); 250 return fuzzyContent.split(fuzzyOldText).length - 1; 251} 252 253function getNotFoundError(path: string, editIndex: number, totalEdits: number): Error {First 10 of 256 lines.
7 more
- 184 lines in 2 placestypescript1,096 tokens
- 237 lines in 2 placestypescript1,082 tokens
- 83 lines in 2 placestypescript649 tokens
- 98 lines in 2 placestypescript587 tokens
- 13 lines in 6 placestypescript102 tokens
- 61 lines in 2 placestypescript379 tokens
- 45 lines in 2 placestypescript298 tokens
Largest clones over all files, tests and data included
- 655 lines in 2 placestypescript5,420 tokenspackages/coding-agent/src/experimental/durable/tui.ts:1–655packages/coding-agent/src/experimental/vacation/tui.ts:1–655
1import type { AssistantMessage, ToolResultMessage, Usage, UserMessage } from "@earendil-works/pi-ai"; 2import type { 3 ConversationId, 4 EntryRecord, 5 InboxState, 6 LiveState, 7 TaskGraph, 8 TaskGraphNode, 9 UsageState, 10} from "@earendil-works/pi-durable";First 10 of 655 lines.
- 231 lines in 2 placestypescripttests2,810 tokens
1import { describe, expect, it } from "vitest"; 2import { 3 applyImmutable, 4 assertValidOp, 5 assertValidWireOp, 6 decoder, 7 diffRevisions, 8 encoder, 9 type Op, 10} from "../src/delta/index.ts";First 10 of 231 lines.
- 20 lines in 20 placestypescripttests129 tokenspackages/ai/test/empty.test.ts:148–167packages/ai/test/empty.test.ts:168–187packages/ai/test/empty.test.ts:188–207packages/ai/test/empty.test.ts:230–249packages/ai/test/empty.test.ts:250–269and 15 more
148const llm = getModel("google", "gemini-2.5-flash"); 149 150it("should handle empty content array", { retry: 3, timeout: 30000 }, async () => { 151 await testEmptyMessage(llm); 152}); 153 154it("should handle empty string content", { retry: 3, timeout: 30000 }, async () => { 155 await testEmptyStringMessage(llm); 156}); 157First 10 of 20 lines.
- 16 lines in 19 placestypescripttests101 tokens
- 15 lines in 24 placestypescripttests75 tokens
By format, code only
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| typescript | 648 | 174,452 | 331 | 5,930 | 3.4% |
| javascript | 31 | 8,771 | 29 | 298 | 3.4% |
| bash | 19 | 1,499 | 0 | 0 | 0% |
| c | 2 | 515 | 0 | 0 | 0% |
| c-header | 3 | 369 | 0 | 0 | 0% |
| perl | 1 | 174 | 0 | 0 | 0% |
| objectivec | 1 | 132 | 0 | 0 | 0% |
| powershell | 1 | 68 | 0 | 0 | 0% |
By format, all files
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| typescript | 1,536 | 378,166 | 2,337 | 30,607 | 8.09% |
| markdown | 106 | 33,645 | 51 | 608 | 1.81% |
| javascript | 46 | 9,571 | 31 | 314 | 3.28% |
| yaml | 14 | 2,350 | 17 | 230 | 9.79% |
| json | 42 | 3,063 | 2 | 85 | 2.78% |
| css | 1 | 1,076 | 2 | 17 | 1.58% |
| bash | 37 | 1,842 | 0 | 0 | 0% |
| c | 5 | 828 | 0 | 0 | 0% |
| c-header | 3 | 369 | 0 | 0 | 0% |
| text | 15 | 354 | 0 | 0 | 0% |
Trending appearances
| Day | Rank | Stars | Files | Lines | Clones | All files | Code | Health | Commit |
|---|---|---|---|---|---|---|---|---|---|
| Oct 4, 2026 | #6 | 112,259 (+408) | 1,812 | 431,756 | 2,440 | 7.38% | 3.35% | C 58.8 | 2003871 |
| Oct 2, 2026 | #5 | 111,357 (+298) | 1,805 | 431,431 | 2,450 | 7.45% | 3.54% | C 58.6 | 7fbbd5f |
| Sep 16, 2026 | #9 | 105,898 (+458) | 1,714 | 413,821 | 2,519 | 8.03% | 3.96% | — | 60e7e76 |
Want this for your own project? Install jscpd and run jscpd ., or measure it the way the baselines were measured.