[{"data":1,"prerenderedAt":703},["ShallowReactive",2],{"navigation_docs":3,"-guides-history":173,"-guides-history-surround":698},[4,50,72,89,125,147,163,168],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30,35,40,45],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Configuration","\u002Fgetting-started\u002Fconfiguration","1.getting-started\u002F4.configuration","i-lucide-settings",{"title":26,"path":27,"stem":28,"icon":29},"Supported Formats","\u002Fgetting-started\u002Fsupported-formats","1.getting-started\u002F5.supported-formats","i-lucide-file-code",{"title":31,"path":32,"stem":33,"icon":34},"Agent Skill","\u002Fgetting-started\u002Fagent-skill","1.getting-started\u002F6.agent-skill","i-lucide-cpu",{"title":36,"path":37,"stem":38,"icon":39},"Changelog","\u002Fgetting-started\u002Fchangelog","1.getting-started\u002F7.changelog","i-lucide-scroll-text",{"title":41,"path":42,"stem":43,"icon":44},"Migrating from v4 to v5","\u002Fgetting-started\u002Fmigration","1.getting-started\u002F8.migration","i-lucide-arrow-right-left",{"title":46,"path":47,"stem":48,"icon":49},"jscpd v4 (TypeScript)","\u002Fgetting-started\u002Fv4","1.getting-started\u002F9.v4","i-simple-icons-typescript",{"title":51,"path":52,"stem":53,"children":54,"icon":6},"Guides","\u002Fguides","2.guides\u002F1.index",[55,57,62,67],{"title":51,"path":52,"stem":53,"icon":56},"i-lucide-book-open",{"title":58,"path":59,"stem":60,"icon":61},"Types of Code Clones","\u002Fguides\u002Fclone-types","2.guides\u002F2.clone-types","i-lucide-copy",{"title":63,"path":64,"stem":65,"icon":66},"How Detection Works","\u002Fguides\u002Fhow-detection-works","2.guides\u002F3.how-detection-works","i-lucide-scan-search",{"title":68,"path":69,"stem":70,"icon":71},"Duplication Trend over Git History","\u002Fguides\u002Fhistory","2.guides\u002F4.history","i-lucide-chart-no-axes-combined",{"title":73,"path":74,"stem":75,"children":76,"icon":6},"CI & Hooks","\u002Fci-and-hooks","3.ci-and-hooks\u002F1.index",[77,79,84],{"title":73,"path":74,"stem":75,"icon":78},"i-lucide-git-pull-request",{"title":80,"path":81,"stem":82,"icon":83},"Use jscpd in CI","\u002Fci-and-hooks\u002Fci","3.ci-and-hooks\u002F2.ci","i-lucide-github",{"title":85,"path":86,"stem":87,"icon":88},"Use jscpd in Pre-Commit Hook","\u002Fci-and-hooks\u002Fpre-commit","3.ci-and-hooks\u002F3.pre-commit","i-lucide-git-commit",{"title":90,"path":91,"stem":92,"children":93,"icon":95},"Reporters","\u002Freporters","4.reporters\u002F1.index",[94,96,100,105,110,115,120],{"title":90,"path":91,"stem":92,"icon":95},"i-lucide-file-chart-column",{"title":97,"path":98,"stem":99,"icon":29},"HTML Reporter","\u002Freporters\u002Fhtml","4.reporters\u002F2.html",{"title":101,"path":102,"stem":103,"icon":104},"JSON Reporter","\u002Freporters\u002Fjson","4.reporters\u002F3.json","i-lucide-braces",{"title":106,"path":107,"stem":108,"icon":109},"Badge Reporter","\u002Freporters\u002Fbadge","4.reporters\u002F4.badge","i-lucide-award",{"title":111,"path":112,"stem":113,"icon":114},"SARIF Reporter","\u002Freporters\u002Fsarif","4.reporters\u002F5.sarif","i-lucide-shield-check",{"title":116,"path":117,"stem":118,"icon":119},"CodeClimate \u002F GitLab Reporter","\u002Freporters\u002Fcodeclimate","4.reporters\u002F6.codeclimate","i-lucide-flag-triangle-right",{"title":121,"path":122,"stem":123,"icon":124},"OpenMetrics Reporter","\u002Freporters\u002Fopenmetrics","4.reporters\u002F7.openmetrics","i-lucide-activity",{"title":126,"path":127,"stem":128,"children":129,"icon":6},"Benchmarks","\u002Fbenchmarks","5.benchmarks\u002F1.index",[130,132,137,142],{"title":126,"path":127,"stem":128,"icon":131},"i-lucide-gauge",{"title":133,"path":134,"stem":135,"icon":136},"Detection Speed","\u002Fbenchmarks\u002Fdetection-speed","5.benchmarks\u002F2.detection-speed","i-lucide-zap",{"title":138,"path":139,"stem":140,"icon":141},"Multi-Format Detection","\u002Fbenchmarks\u002Fcross-format","5.benchmarks\u002F3.cross-format","i-lucide-layers",{"title":143,"path":144,"stem":145,"icon":146},"AI Token Efficiency","\u002Fbenchmarks\u002Fai-token-efficiency","5.benchmarks\u002F4.ai-token-efficiency","i-lucide-sparkles",{"title":148,"path":149,"stem":150,"children":151,"icon":153},"API","\u002Fapi","6.api\u002F1.index",[152,154,159],{"title":148,"path":149,"stem":150,"icon":153},"i-lucide-code",{"title":155,"path":156,"stem":157,"icon":158},"Rust Crates (v5)","\u002Fapi\u002Fcore","6.api\u002F2.core","i-lucide-box",{"title":160,"path":161,"stem":162,"icon":158},"MCP Server","\u002Fapi\u002Fmcp-server","6.api\u002F4.mcp-server",{"title":164,"path":165,"stem":166,"icon":167},"Trending","\u002Ftrending","7.trending","i-lucide-trending-up",{"title":169,"path":170,"stem":171,"icon":172},"Research","\u002Fresearch","8.research","i-lucide-graduation-cap",{"id":174,"title":68,"body":175,"description":689,"extension":690,"links":691,"meta":692,"navigation":693,"path":69,"seo":694,"stem":70,"__hash__":697},"docs\u002F2.guides\u002F4.history.md",{"type":176,"value":177,"toc":683},"minimark",[178,187,200,205,284,299,394,415,419,430,438,474,529,533,539,622,632,636,669,679],[179,180,181,182,186],"p",{},"A single scan tells you how much duplication a codebase has today. ",[183,184,185],"code",{},"--history"," tells you where it is heading: it scans every commit in a git range with the run's own configuration and prints the series as a chart and a table, without a hosted dashboard.",[188,189,190,191,195,196,199],"note",{},"Available from jscpd ",[192,193,194],"strong",{},"5.2.1",". Needs ",[183,197,198],{},"git"," on the PATH and the commits present locally.",[201,202,204],"h2",{"id":203},"running-it","Running it",[206,207,213],"pre",{"className":208,"code":209,"filename":210,"language":211,"meta":212,"style":212},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","jscpd src --history v5.0.0..HEAD           # every commit in the range\njscpd src --history-since 2026-01-01       # every commit since a date, up to HEAD\njscpd src --history main --history-since 2026-06-01 --history-every 5 --history-limit 12\n","Terminal","bash","",[183,214,215,238,254],{"__ignoreMap":212},[216,217,220,224,228,231,234],"span",{"class":218,"line":219},"line",1,[216,221,223],{"class":222},"sBMFI","jscpd",[216,225,227],{"class":226},"sfazB"," src",[216,229,230],{"class":226}," --history",[216,232,233],{"class":226}," v5.0.0..HEAD",[216,235,237],{"class":236},"sHwdD","           # every commit in the range\n",[216,239,241,243,245,248,251],{"class":218,"line":240},2,[216,242,223],{"class":222},[216,244,227],{"class":226},[216,246,247],{"class":226}," --history-since",[216,249,250],{"class":226}," 2026-01-01",[216,252,253],{"class":236},"       # every commit since a date, up to HEAD\n",[216,255,257,259,261,263,266,268,271,274,278,281],{"class":218,"line":256},3,[216,258,223],{"class":222},[216,260,227],{"class":226},[216,262,230],{"class":226},[216,264,265],{"class":226}," main",[216,267,247],{"class":226},[216,269,270],{"class":226}," 2026-06-01",[216,272,273],{"class":226}," --history-every",[216,275,277],{"class":276},"sbssI"," 5",[216,279,280],{"class":226}," --history-limit",[216,282,283],{"class":276}," 12\n",[179,285,286,287,294,295,298],{},"For each selected commit jscpd checks the tree out into a temporary detached worktree, the same mechanism ",[288,289,291],"a",{"href":290},"\u002Fci-and-hooks\u002Fci#baseline-from-a-git-ref",[183,292,293],{},"--baseline-from-ref"," uses, scans it, and keeps the totals. The current run is the last point of the series, labelled ",[183,296,297],{},"working",". Scans run one after another; each scan is already parallel across files.",[300,301,302,318],"table",{},[303,304,305],"thead",{},[306,307,308,312,315],"tr",{},[309,310,311],"th",{},"Option",[309,313,314],{},"Effect",[309,316,317],{},"Default",[319,320,321,345,364,379],"tbody",{},[306,322,323,329,342],{},[324,325,326],"td",{},[183,327,328],{},"--history \u003Crange>",[324,330,331,334,335,338,339],{},[183,332,333],{},"git log"," revision range to walk, e.g. ",[183,336,337],{},"v5.0.0..HEAD"," or ",[183,340,341],{},"main",[324,343,344],{},"—",[306,346,347,352,362],{},[324,348,349],{},[183,350,351],{},"--history-since \u003Cdate>",[324,353,354,355,358,359,361],{},"Select commits since a date; alone it walks ",[183,356,357],{},"HEAD",", with ",[183,360,185],{}," it bounds the range",[324,363,344],{},[306,365,366,371,374],{},[324,367,368],{},[183,369,370],{},"--history-every \u003CN>",[324,372,373],{},"Keep every Nth commit, counted from the newest so the latest is always in",[324,375,376],{},[183,377,378],{},"1",[306,380,381,386,389],{},[324,382,383],{},[183,384,385],{},"--history-limit \u003CN>",[324,387,388],{},"Cap the series by sampling it evenly, keeping both ends",[324,390,391],{},[183,392,393],{},"30",[179,395,396,397,400,401,404,405,404,408,404,411,414],{},"The same keys work in ",[183,398,399],{},".jscpd.json",": ",[183,402,403],{},"history",", ",[183,406,407],{},"historySince",[183,409,410],{},"historyEvery",[183,412,413],{},"historyLimit",".",[201,416,418],{"id":417},"reading-the-output","Reading the output",[179,420,421,422,425,426,429],{},"The ",[183,423,424],{},"console"," and ",[183,427,428],{},"console-full"," reporters append a block after the normal report:",[206,431,436],{"className":432,"code":434,"language":435},[433],"language-text","History (since 2026-01-01: 4 commits + working tree)\n  duplicated lines, % of all lines: min 0.0%  max 58.1%  now 42.9%\n    58.1% ┤       ██\n          │       ██\n          │    ▇▇ ██ ▇▇ ▇▇\n    29.0% ┤    ██ ██ ██ ██\n          │    ██ ██ ██ ██\n          │    ██ ██ ██ ██\n          │    ██ ██ ██ ██\n     0.0% ┤ ▁▁ ██ ██ ██ ██\n          └────────────────\n            1  2  3  4  5\n\n  #  COMMIT   DATE        FILES  LINES  CLONES  DUP LINES   DUP%  CHANGE  SUBJECT\n  1  0a3e3d5  2026-08-01      1     11       0          0   0.0%          initial helpers\n  2  6728f91  2026-08-08      2     21       1          9  42.9%   +42.9  copy total() into b.js\n  3  aff51e5  2026-08-15      3     31       2         18  58.1%   +15.2  and again into c.js\n  4  817b39d  2026-08-22      2     21       1          9  42.9%   -15.2  b.js imports total() instead\n  5  working  2026-09-12      2     21       1          9  42.9%       =  (uncommitted changes)\nTrend: +42.9 points since 0a3e3d5 (2026-08-01)\nThreshold 50.0% has 7.1 points of headroom: the series never needed it, tighten it with --threshold 42.9\n","text",[183,437,434],{"__ignoreMap":212},[439,440,441,452,458,464],"ul",{},[442,443,444,447,448,451],"li",{},[192,445,446],{},"The chart"," plots the duplicated-lines percentage, one column per point. Its y-axis spans the series' own minimum and maximum, so a drift from 2.0% to 2.4% is visible instead of a flat line on a 0-based axis. The numbers under it are the ",[183,449,450],{},"#"," column of the table.",[442,453,454,457],{},[192,455,456],{},"CHANGE"," is the difference to the previous point in percentage points, red when duplication rose and green when it fell.",[442,459,460,463],{},[192,461,462],{},"Trend"," is the change from the first point to the last.",[442,465,466,469,470,473],{},[192,467,468],{},"The threshold line"," appears when ",[183,471,472],{},"--threshold"," is set and the latest value sits below it. It is the manual form of a ratchet: jscpd reports how far the threshold could be tightened and leaves the change to you. When the latest value is over the threshold, the usual threshold error fires instead and the run exits 1.",[179,475,476,477,480,481,483,484,404,487,404,490,493,494,404,497,404,500,404,503,404,506,404,509,404,512,404,515,404,518,404,521,524,525,528],{},"Other reporters: ",[183,478,479],{},"json"," adds a ",[183,482,403],{}," object (",[183,485,486],{},"range",[183,488,489],{},"threshold",[183,491,492],{},"points[]"," with ",[183,495,496],{},"commit",[183,498,499],{},"short",[183,501,502],{},"date",[183,504,505],{},"subject",[183,507,508],{},"sources",[183,510,511],{},"lines",[183,513,514],{},"tokens",[183,516,517],{},"clones",[183,519,520],{},"duplicatedLines",[183,522,523],{},"percentage","), ",[183,526,527],{},"ai"," prints one compact line per point. The rest are unchanged.",[201,530,532],{"id":531},"in-ci","In CI",[179,534,535,536,538],{},"The GitHub Action exposes the range as the ",[183,537,403],{}," input. The range must be present in the checkout, so disable the shallow clone:",[206,540,545],{"className":541,"code":542,"filename":543,"language":544,"meta":212,"style":212},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","- uses: actions\u002Fcheckout@v4\n  with:\n    fetch-depth: 0\n- uses: kucherenko\u002Fjscpd@v5\n  with:\n    history: v5.0.0..HEAD\n    threshold: 3\n",".github\u002Fworkflows\u002Fjscpd.yml","yaml",[183,546,547,563,571,581,593,600,611],{"__ignoreMap":212},[216,548,549,553,557,560],{"class":218,"line":219},[216,550,552],{"class":551},"sMK4o","-",[216,554,556],{"class":555},"swJcz"," uses",[216,558,559],{"class":551},":",[216,561,562],{"class":226}," actions\u002Fcheckout@v4\n",[216,564,565,568],{"class":218,"line":240},[216,566,567],{"class":555},"  with",[216,569,570],{"class":551},":\n",[216,572,573,576,578],{"class":218,"line":256},[216,574,575],{"class":555},"    fetch-depth",[216,577,559],{"class":551},[216,579,580],{"class":276}," 0\n",[216,582,584,586,588,590],{"class":218,"line":583},4,[216,585,552],{"class":551},[216,587,556],{"class":555},[216,589,559],{"class":551},[216,591,592],{"class":226}," kucherenko\u002Fjscpd@v5\n",[216,594,596,598],{"class":218,"line":595},5,[216,597,567],{"class":555},[216,599,570],{"class":551},[216,601,603,606,608],{"class":218,"line":602},6,[216,604,605],{"class":555},"    history",[216,607,559],{"class":551},[216,609,610],{"class":226}," v5.0.0..HEAD\n",[216,612,614,617,619],{"class":218,"line":613},7,[216,615,616],{"class":555},"    threshold",[216,618,559],{"class":551},[216,620,621],{"class":276}," 3\n",[179,623,624,625,425,628,631],{},"The chart and table land in the job log. For a scheduled job on a long-lived repository, ",[183,626,627],{},"--history-every",[183,629,630],{},"--history-limit"," keep the run short: 30 points is a readable series, and each point costs one scan.",[201,633,635],{"id":634},"good-to-know","Good to know",[439,637,638,641,657,663],{},[442,639,640],{},"Paths that did not exist at a commit count as zero files for that point, so a series can start before the scanned directory was created.",[442,642,643,644,646,647,404,650,425,653,656],{},"The range is passed to ",[183,645,333],{}," as is: tags, branches, ",[183,648,649],{},"A..B",[183,651,652],{},"A...B",[183,654,655],{},"--history-since"," dates all work as they do on the command line.",[442,658,659,660,662],{},"Uncommitted changes are included through the ",[183,661,297],{}," point only; every other point is a clean checkout of its commit.",[442,664,665,666,414],{},"To see what one of the earlier points contained, scan the commit directly: ",[183,667,668],{},"git worktree add \u002Ftmp\u002Fold \u003Csha> && jscpd \u002Ftmp\u002Fold\u002Fsrc",[179,670,671,672,674,675,678],{},"See ",[288,673,58],{"href":59}," for what the percentage counts, and the ",[288,676,677],{"href":22},"configuration reference"," for the full option list.",[680,681,682],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}",{"title":212,"searchDepth":240,"depth":240,"links":684},[685,686,687,688],{"id":203,"depth":240,"text":204},{"id":417,"depth":240,"text":418},{"id":531,"depth":240,"text":532},{"id":634,"depth":240,"text":635},"Scan every commit in a range with --history and see whether duplication is going up or down, as a chart and a table in the terminal.","md",null,{},{"icon":71},{"title":695,"description":696},"Duplication Trend over Git History with jscpd --history","jscpd --history scans each commit in a git range with the same configuration and prints a bar chart, a per-commit table, the change between points and how far --threshold could be tightened.","Sa_3Gqxrf9MsKVTW9THRq4ULrmO9D48NnAWgtqB39yQ",[699,701],{"title":63,"path":64,"stem":65,"description":700,"icon":66,"children":-1},"How jscpd turns source code into language tokens before it looks for duplicates, and what that means for the clones you get.",{"title":73,"path":74,"stem":75,"description":702,"icon":78,"children":-1},"Integrate jscpd into your CI pipeline and git hooks.",1789454707597]