JetBrains/thinkrail
Vibe code with pi in a lightweight, real IDE that customises itself around the way you work — The Vibe You Need
TypeScript★ 2,012+51 that day#5 on trending
C69.9/100
Duplication79
2.9% in typescript, tsx, bash, astro, powershell, javascript, sqlDead code97
0.3%Complexity45
58.3% The score is jscpd's own --health model: markup, data and text left out, tests kept. The numbers below are the trending scan's.
0.74%duplicated code · 1,120 of 152,162 lines
100clones in code
879code files of 1,848 scanned
2.84%duplicated over all files · 988 clones
Most complex files
- apps/web/src/store/appStore.ts1544 cx
- packages/server/src/agent/agentSessionManager.ts758 cx
- packages/server/src/agent/agentSessionManager.test.ts610 cx
- apps/web/src/shell/layout/model.ts528 cx
- packages/pi-dag/runtime/service.ts508 cx
- apps/web/src/store/appStore.test.ts488 cx
- apps/web/src/chat/useChatScroll.ts432 cx
- apps/web/src/chat/tools/AskUserQuestionCard.tsx403 cx
- packages/pi-delegation/src/service.ts398 cx
- packages/server/src/host/handlers.ts385 cx
Dead code 0.34% unused · 45 findings
- apps/desktop/src/preload.tsunused-file
- apps/desktop/preBuild.tsunused-file
- scripts/pi-package-parity.node.mjsunused-file
- packages/pi-dag/runtime/recovery.fixture.tsunused-file
- packages/server/src/subprocess/windowsConsole.fixture.tsunused-file
- apps/desktop/src/pageZoom.ts:installPageZoomGesturesunused-export
- packages/pi-dag/persistence/fixtures.tsunused-file
- packages/pi-dag/runtime/provider.fixture.tsunused-file
- packages/pi-dag/persistence/process.fixture.tsunused-file
- packages/pi-background-commands/src/test-support.tsunused-file
The code number leaves out tests, fixtures, docs, examples, data files, styles, translations and vendored code, and 1 generated file: apps/web/src/chat/generated/providerGlyphs.ts.
Largest clones in the code
- 36 lines in 3 placeshtml200 tokensapps/website/src/pages/agentic-development/index.astro:1–36apps/website/src/pages/agentic-ide/index.astro:1–38apps/website/src/pages/vibecoding/index.astro:1–36
1--- 2import Analytics from "../../components/Analytics.astro"; 3import { Landing, siteMetadata } from "../../vibecoding"; 4 5const canonicalUrl = new URL(siteMetadata.path, siteMetadata.origin); 6const ogImageUrl = new URL(siteMetadata.openGraphImagePath, siteMetadata.origin); 7--- 8 9<!doctype html> 10<html lang="en">First 10 of 36 lines.
- 7 lines in 6 placeshtml73 tokensapps/website/src/components/InstallPicker.astro:67–73apps/website/src/components/InstallPicker.astro:77–83apps/website/src/components/InstallPicker.astro:87–93apps/website/src/pages/index.astro:284–287apps/website/src/pages/index.astro:291–294and 1 more
67 <button type="button" class="copy-btn" data-copy={installCommands.windows.powershell} aria-label="Copy PowerShell install command"> 68 <svg class="i" aria-hidden="true"><use href="#i-copy" /></svg> 69 <svg class="i i-done" aria-hidden="true"><use href="#i-check" /></svg> 70 </button> 71 </div> 72</div> 73<div class="windows-shell-panel" id={`${idPrefix}-shell-cmd`} role="tabpanel" aria-labelledby={`${idPrefix}-shell-cmd-tab`} data-windows-shell-panel="cmd">77 <button type="button" class="copy-btn" data-copy={installCommands.windows.cmd} aria-label="Copy Command Prompt (cmd) install command"> 78 <svg class="i" aria-hidden="true"><use href="#i-copy" /></svg> 79 <svg class="i i-done" aria-hidden="true"><use href="#i-check" /></svg> 80 </button> 81 </div> 82</div> 83<div class="windows-shell-panel" id={`${idPrefix}-shell-wsl`} role="tabpanel" aria-labelledby={`${idPrefix}-shell-wsl-tab`} data-windows-shell-panel="wsl"> - 34 lines in 2 placestypescript346 tokensapps/website/src/attribution/protocol.ts:60–93packages/server/src/persistence/attributionProtocol.ts:54–87
60export function normalizeCampaignValue(value: string, limit: number): string | undefined { 61 const withoutControls = Array.from(value) 62 .filter((character) => { 63 const codePoint = character.codePointAt(0) ?? 0; 64 return codePoint > 31 && (codePoint < 127 || codePoint > 159); 65 }) 66 .join(""); 67 const normalized = Array.from(withoutControls.trim()).slice(0, limit).join(""); 68 return normalized.length > 0 ? normalized : undefined; 69}First 10 of 34 lines.
7 more
- 27 lines in 2 placestsx167 tokens
- 10 lines in 3 placestsx75 tokens
- 20 lines in 2 placestsx138 tokens
- 19 lines in 2 placestsx137 tokens
- 9 lines in 2 placestypescript113 tokens
- 17 lines in 2 placestsx113 tokens
- 22 lines in 2 placestsx112 tokens
Largest clones over all files, tests and data included
- 6 lines in 19 placestypescripttests62 tokenspackages/server/src/todos/artifacts.test.ts:152–157packages/server/src/todos/artifacts.test.ts:188–193packages/server/src/todos/artifacts.test.ts:258–267packages/server/src/todos/artifacts.test.ts:306–311packages/server/src/todos/artifacts.test.ts:336–341and 14 more
152test("done attaches the delta of changes since the in_progress baseline", async () => { 153 const { store, root } = tempStore(); 154 try { 155 const todo = store.add({ title: "step" }); 156 store.update(todo.id, { status: "in_progress" }); 157 await reconcileChangeArtifacts(store, root, SESSION, async () => ["a.ts"]);188test("a done reconcile cannot commit an item reopened during its git read", async () => { 189 const { store, root } = tempStore(); 190 try { 191 const todo = store.add({ title: "step" }); 192 store.update(todo.id, { status: "in_progress" }); 193 await reconcileChangeArtifacts(store, root, SESSION, async () => []); - 9 lines in 6 placescssgenerated85 tokensapps/web/src/styles/generated/typography.css:161–169apps/web/src/styles/generated/typography.css:233–241apps/web/src/styles/generated/typography.css:280–288apps/web/src/styles/generated/typography.css:361–369apps/web/src/styles/generated/typography.css:370–378and 1 more
161 font-family: var(--tr-font-family-interface); 162 font-size: var(--tr-font-size-s14); 163 font-weight: var(--tr-font-weight-light); 164 line-height: var(--tr-line-height-reading); 165 letter-spacing: var(--tr-letter-spacing-normal); 166 text-transform: none; 167 font-style: normal; 168} 169.tr-text-ui {233 font-family: var(--tr-font-family-interface); 234 font-size: var(--tr-font-size-s14); 235 font-weight: var(--tr-font-weight-light); 236 line-height: var(--tr-line-height-reading); 237 letter-spacing: var(--tr-letter-spacing-normal); 238 text-transform: none; 239 font-style: normal; 240} 241.tr-code-text { - 10 lines in 5 placescssgenerated104 tokensapps/web/src/styles/generated/typography.css:124–133apps/web/src/styles/generated/typography.css:133–142apps/web/src/styles/generated/typography.css:297–306apps/web/src/styles/generated/typography.css:456–465apps/web/src/styles/generated/typography.css:519–528
124.tr-title-dialog { 125 font-family: var(--tr-font-family-interface); 126 font-size: var(--tr-font-size-s14); 127 font-weight: var(--tr-font-weight-semibold); 128 line-height: var(--tr-line-height-compact); 129 letter-spacing: var(--tr-letter-spacing-normal); 130 text-transform: none; 131 font-style: normal; 132} 133.tr-title-card {133.tr-title-card { 134 font-family: var(--tr-font-family-interface); 135 font-size: var(--tr-font-size-s14); 136 font-weight: var(--tr-font-weight-semibold); 137 line-height: var(--tr-line-height-compact); 138 letter-spacing: var(--tr-letter-spacing-normal); 139 text-transform: none; 140 font-style: normal; 141} 142.tr-title-section { - 10 lines in 5 placescssgenerated102 tokens
- 9 lines in 7 placestypescripttests67 tokens
By format, code only
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| tsx | 273 | 54,641 | 54 | 602 | 1.1% |
| typescript | 574 | 94,899 | 38 | 429 | 0.45% |
| html | 13 | 992 | 8 | 89 | 8.97% |
| bash | 2 | 665 | 0 | 0 | 0% |
| astro | 13 | 485 | 0 | 0 | 0% |
| powershell | 1 | 361 | 0 | 0 | 0% |
| javascript | 3 | 119 | 0 | 0 | 0% |
By format, all files
| Format | Files | Lines | Clones | Duplicated lines | Duplication |
|---|---|---|---|---|---|
| typescript | 1,213 | 238,187 | 833 | 8,021 | 3.37% |
| css | 9 | 4,436 | 68 | 539 | 12.15% |
| tsx | 315 | 59,362 | 56 | 629 | 1.06% |
| yaml | 62 | 1,333 | 10 | 113 | 8.48% |
| json | 46 | 7,886 | 9 | 239 | 3.03% |
| html | 13 | 992 | 8 | 89 | 8.97% |
| markdown | 149 | 26,582 | 3 | 37 | 0.14% |
| diff | 1 | 70 | 1 | 6 | 8.57% |
| bash | 6 | 858 | 0 | 0 | 0% |
| astro | 13 | 485 | 0 | 0 | 0% |
Trending appearances
| Day | Rank | Stars | Files | Lines | Clones | All files | Code | Health | Commit |
|---|---|---|---|---|---|---|---|---|---|
| Oct 26, 2026 | #5 | 2,012 (+51) | 1,848 | 340,904 | 988 | 2.84% | 0.74% | C 69.9 | d299f20 |
Want this for your own project? Install jscpd and run jscpd ., or measure it the way the baselines were measured.