{"id":13432947,"url":"https://github.com/antoine-coulon/skott","last_synced_at":"2025-05-14T05:10:33.443Z","repository":{"id":41448430,"uuid":"509605009","full_name":"antoine-coulon/skott","owner":"antoine-coulon","description":"All-in-one devtool to automatically analyze, search and visualize project modules and dependencies from JavaScript, TypeScript (JSX/TSX) and Node.js (ES6, CommonJS)","archived":false,"fork":false,"pushed_at":"2024-11-22T13:05:09.000Z","size":1532,"stargazers_count":731,"open_issues_count":19,"forks_count":29,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-11T15:57:12.072Z","etag":null,"topics":["commonjs","dependencies","es6","graph","javascript","jsx","nodejs","static-analysis","tree","tsx","typescript","visualization"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antoine-coulon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-07-01T22:38:46.000Z","updated_at":"2025-03-28T04:36:36.000Z","dependencies_parsed_at":"2023-12-19T09:58:14.197Z","dependency_job_id":"15b58ce7-663b-4ea1-8987-e3b76e1ea48f","html_url":"https://github.com/antoine-coulon/skott","commit_stats":{"total_commits":356,"total_committers":11,"mean_commits":32.36363636363637,"dds":0.300561797752809,"last_synced_commit":"d2b630c19b9c7321be3ab3f63e5304ca1c541686"},"previous_names":[],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoine-coulon%2Fskott","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoine-coulon%2Fskott/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoine-coulon%2Fskott/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antoine-coulon%2Fskott/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antoine-coulon","download_url":"https://codeload.github.com/antoine-coulon/skott/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254076849,"owners_count":22010611,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["commonjs","dependencies","es6","graph","javascript","jsx","nodejs","static-analysis","tree","tsx","typescript","visualization"],"created_at":"2024-07-31T02:01:18.888Z","updated_at":"2025-05-14T05:10:33.418Z","avatar_url":"https://github.com/antoine-coulon.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\t\u003cimg alt=\"skott\" src=\"https://github.com/antoine-coulon/skott/assets/43391199/4f1dfaa7-af3b-43cb-9f5c-a2ca0f960265\" width=\"350\"\u003e\n\u003c/p\u003e\n\n\n![version](https://img.shields.io/badge/dynamic/json.svg?url=https://raw.githubusercontent.com/antoine-coulon/skott/main/packages/skott/package.json\u0026query=$.version\u0026label=Version)\n[![npm](https://img.shields.io/npm/dm/skott.svg)](https://www.npmjs.com/package/skott)\n[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/antoine-coulon/skott/commit-activity)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n\n**skott** is a minimalist developer tool that can be used to efficiently generate directed graphs from your **JavaScript/TypeScript/Node.js** project. It can **automatically collect metadata** such as _file size_, _third-party_ or _builtin dependencies_, **detect circular dependencies**, **finding unused npm dependencies**, help you **building tools relying on graph data structures** thanks to the exposed primitives. Many display modes exists (such as **embedded interactive web application** shown just below) but also other from the CLI (file-tree, graph). Static files **(.svg, .png, .md, .json)** can also be generated.\n\n\u003cp align=\"center\"\u003e\n\t\u003cimg alt=\"skott\" src=\"https://github.com/antoine-coulon/skott/assets/43391199/90456c53-d554-43cc-b493-004849bb501a\"\u003e\n\u003c/p\u003e\n\n**skott** exposes **directed graphs primitives** so that it can be used to implement tools on top of graph structures e.g. affected/incremental patterns as it exposes a way to know precisely and deeply dependencies for each graph node. More generally speaking, anything that can be implemented using graphs can be implemented using **skott**.\n\n✅ Works for modern **JavaScript/TypeScript** projects (TSX/JSX, ECMAScript and CommonJS modules all supported). **TypeScript**'s path aliases are also supported.\n\n✅ Deeply detects **circular dependencies** in an efficient way, with the ability to provide a max depth for the search\n\n✅ Detect **unused source code files**. Eliminate dead code by finding files not imported anywhere else in the graph.\n\n✅ Detect **unused npm third-party dependencies**. Note that all unused `devDependencies` are not guaranteed to be detected as `depcheck` [only provides analysis for set of supported libraries](https://github.com/depcheck/depcheck) (eslint, karma, mocha, etc).\n\n✅ Many **builtin visualization modes** including a web application or terminal-based outputs such as file-tree or graph views. Visualization modes can be rendered using both the CLI and programatically using the API.\n\n✅ Builtin **watch mode** updating the graph when file changes are detected. It works with all display modes (webapp and all CLIs visualization modes). Support all options of file ignoring/filtering from skott.\n\n✅ File tree traversal supports **ignore patterns** and **Git ignored files** (via `.gitignore` files)\n\n✅ Runs **incrementally** (experimental), meaning that skott will _only analyze_ files that were modified/added since the last run, offering performance boosts.\n\n✅ Works with any custom **dependency resolver** (useful for specific monorepos integration where module identifiers need to be mapped to a specific workspace package) \n\n✅ Deeply **collect all dependencies of the project graph**, including third-party and builtin.\n\n✅ Graph API including deep **parent and child dependencies traversals** using DFS and BFS algorithms.\n\n✅ Metadata collection per traversed node (file size, dependencies)\n\n✅ Generate static files including raw JSON, [mermaid-js](https://github.com/mermaid-js/mermaid) diagrams (.svg, .png, .md) representing your project's graph directly generated from the CLI.\n\n`skott` can be used either via its CLI or JavaScript API. It can either build the project graph using an entrypoint file or build it starting from the current root directory and recursively traverse all directories/folders. Currently, supported files are **.js, .jsx, .cjs, .mjs, .ts, .tsx**. **skott does not rely on module systems for path resolution**, it will resolve `require/import` no matter the configuration.\n\n## Getting started\n\nThis is a quick start, **please check the [complete documentation at the skott package level](https://github.com/antoine-coulon/skott/tree/main/packages/skott#readme)** to see more. There are also some **[examples available there](https://github.com/antoine-coulon/skott/blob/main/packages/skott/examples/api.ts)**.\n\nInstall `skott` from npm using whatever package manager you like:\n\n```sh\n\u003cinsert-your-package-manager\u003e install skott\n```\n\nLet's see examples of an analysis that will traverse all files (minus the ignored ones via the ignorePatterns + .gitignore) starting from the current working directory.\n\n**Using the CLI**\n\n```sh\nskott --displayMode=webapp --trackThirdPartyDependencies --ignorePattern=\"test/**/*\"\n```\n\n**Using the API**\n\n```js\nimport skott from \"skott\";\n\nconst { getStructure, getWorkspace, findUnusedDependencies, useGraph } = await skott({\n    ignorePatterns: [\"test/**/*\"],\n    dependencyTracking: {\n        builtin: false,\n        thirdParty: true,\n        typeOnly: true\n    }\n});\n\n// Do whatever you want with the generated graph\nconst { graph, files } = getStructure();\nconst workspace = getWorkspace();\nconst unusedDependencies = await findUnusedDependencies();\nconst { findCircularDependencies, collectFilesDependencies, ...traversalApi } = useGraph();\n```\n\n**Note**: the API is currently published as ESM only.\n\nBecause the graph can become heavy on large codebases, you also have the ability to reduce the scope of the analysis:\n\n**Specificying a sub-folder**\n\n```sh\nskott --cwd=packages/skott \n```\n\nor \n\n```js\nimport skott from \"skott\";\n\nconst api = await skott({\n    cwd: \"packages/skott\"\n});\n```\n\n**Specifying an entrypoint**\n\nThis will strictly traverse the graph starting from the provided entrypoint, discarding all other files not part of that graph.\n\n```sh\nskott packages/skott/index.ts\n```\n\nor\n\n```js\nimport skott from \"skott\";\n\nconst api = await skott({\n    entrypoint: \"packages/skott/index.ts\"\n});\n```\n\n## Why you should use skott or an equivalent project\n\nThe whole purpose of skott is to build a graph from your project source code and offer many features relying on that generated graph.\n\nOverall, a generated project graph in software engineering acts as a **powerful tool that enhances code comprehension, project management, code maintenance and refactoring, and collaboration**. It provides a holistic view of the project's structure, dependencies, and relationships, enabling developers to make informed decisions and streamline their development process.\n\nMoreover, skott aims to provide a comprehensive visual representation of the project's structure, dependencies, and relationships between different components. This visual overview **allows developers to better understand the overall architecture and organization of the codebase, making it easier to navigate and identify potential areas of improvement or optimization**. \n\nIn the essence the main goal of skott is to **help developers understand the codebase's structure and to enable more effective refactoring, reducing code duplication, getting rid of circular dependencies and improving overall code quality**.\n\n## Why you should care about circular dependencies and dead code\n\n1. **Circular (also known as cyclic) dependencies**\n\nLet's start with an example of a simple circular dependency between three graph nodes:\n\u003e In the context of **skott**, nodes represent JavaScript files.\n\n```mermaid  \n  graph LR\n    src/fileA.js --\u003e src/fileB.js\n    src/fileB.js --\u003e src/fileC.js\n    src/fileC.js --\u003e src/fileA.js\n```\n\n**What is the problem with cycles?**\n\nCircular dependencies can make your program crash or introduce inconsistencies while modules are being loaded. [Node.js module systems](https://nodejs.org/api/modules.html) try to resolve circular dependencies using different approaches which are more or less successful. For example, [CommonJS](https://nodejs.org/api/modules.html#modules-commonjs-modules) can (due to its dynamic nature of resolving imports) [introduce inconsistencies when building the project graph](https://nodejs.org/api/modules.html#cycles).\n\nIf you're using [ECMAScript modules](https://nodejs.org/api/esm.html), you can consider yourself safe about module resolution inconsistencies mentioned above, mostly thanks to its static nature.\n\nNevertheless, cyclic dependencies at the file-level are sometimes choices but more often [code smells](https://en.wikipedia.org/wiki/Code_smell) revealing design misconceptions, so be sure to double check that.\n\n2. **Dead code**\n\n_Dead code_ can be defined as a code literally having no impact on the application, meaning that removing dead code should not alter in any way the behavior of the system. Some module bundlers such as [Rollup](https://rollupjs.org) and [Webpack](https://webpack.js.org) allow to delete some of the dead code [leveraging tree shaking](https://webpack.js.org/guides/tree-shaking). \n\nHowever, tree shaking is not an easy task and can mostly work with module systems using static-based imports/exports such as ECMAScript modules. To avoid removing code that appears to be used at runtime, module bundlers are being very precise about determining automatically chunks of code that can be safely removed. Module bundlers can also be helped by providing them manually clues about what can be safely removed e.g. `/*#__PURE__*/` for Webpack.\n\nAlso, bundling might not be possible or might not even be a target. In that context, it's even more important to care about dead code elimination. Dead code can harm cold start and have unwanted side-effects.\n\n**skott** exposes information that can help identifying dead code and getting rid of it. Check documentation to get more information about identifying unused files and dependencies. \n\n## Graph Management\n\n**skott** is powered by [digraph-js](https://github.com/antoine-coulon/digraph-js), a _0 dependency_ Node.js library to make Directed Graph construction and traversal effortless.\n\n## Parsers\n\nWhile traversing the project, **skott** automatically loads the appropriate parser required. When meeting **\".js, .cjs, .mjs, .jsx\"** files, a specific JS parser will be used, otherwise for **\".ts, .tsx\"** files\na specific TS parser will be used instead.\n\n- JavaScript: JavaScript/JSX parsing is done using [meriyah](https://github.com/meriyah/meriyah)\n- TypeScript: TypeScript/TSX parsing is done using [typescript-estree](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/typescript-estree)\n\n## Contributors\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/daniel-relay\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/88200787?v=4?s=100\" width=\"100px;\" alt=\"Daniel Sadilek\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDaniel Sadilek\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=daniel-relay\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://dev.to/antoinecoulon\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/43391199?v=4?s=100\" width=\"100px;\" alt=\"Antoine Coulon\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAntoine Coulon\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=antoine-coulon\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/tarrsalah\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/909959?v=4?s=100\" width=\"100px;\" alt=\"Salah Eddine Taouririt\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eSalah Eddine Taouririt\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=tarrsalah\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ACHP\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/9294168?v=4?s=100\" width=\"100px;\" alt=\"Alexis CHAPPRON\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAlexis CHAPPRON\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=ACHP\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/robertoyoc\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/16704638?v=4?s=100\" width=\"100px;\" alt=\"Roberto Yoc\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRoberto Yoc\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=robertoyoc\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://www.pedrolamas.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/85504?v=4?s=100\" width=\"100px;\" alt=\"Pedro Lamas\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ePedro Lamas\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=pedrolamas\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/AlexandrHoroshih\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/32790736?v=4?s=100\" width=\"100px;\" alt=\"Alexander Khoroshikh\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAlexander Khoroshikh\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=AlexandrHoroshih\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://aniravi.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/5902976?v=4?s=100\" width=\"100px;\" alt=\"Ani Ravi\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAni Ravi\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=aniravi24\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/MengLinMaker\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/39476147?v=4?s=100\" width=\"100px;\" alt=\"Meng Lin\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMeng Lin\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/antoine-coulon/skott/commits?author=MengLinMaker\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantoine-coulon%2Fskott","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantoine-coulon%2Fskott","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantoine-coulon%2Fskott/lists"}