Detect copy-pasted and structurally similar code

Overview

jsinspect

Detect copy-pasted and structurally similar JavaScript code. Requires Node.js 6.0+, and supports ES6, JSX as well as Flow. Note: the project has been mostly rewritten for the 0.10 release and saw several breaking changes.

Build Status

Overview

We've all had to deal with code smell, and duplicate code is a common source. While some instances are easy to spot, this type of searching is the perfect use-case for a helpful CLI tool.

Existing solutions do exist for this purpose, but some struggle with code that has wildly varying identifiers or literals, and others have lackluster support for the JS ecosystem: ES6, JSX, Flow, ignoring module declarations and imports, etc.

And copy-pasted code is but one type of code duplication. Common boilerplate and repeated logic can be identified as well using jsinspect, since it doesn't operate directly on tokens - it uses the ASTs of the parsed code.

You have the freedom to specify a threshold determining the smallest subset of nodes to analyze. This will identify code with a similar structure, based on the AST node types, e.g. BlockStatement, VariableDeclaration, ObjectExpression, etc. By default, it searches nodes with matching identifiers and literals for copy-paste oriented detection, but this can be disabled. For context, identifiers include the names of variables, methods, properties, etc, while literals are strings, numbers, etc.

The tool accepts a list of paths to parse and prints any found matches. Any directories among the paths are walked recursively, and only .js and .jsx files are analyzed. You can explicitly pass file paths that include a different extension as well. Any node_modules and bower_components dirs are also ignored.

screenshot

Installation

It can be installed via npm using:

npm install -g jsinspect

Usage

Usage: jsinspect [options] <paths ...>


Detect copy-pasted and structurally similar JavaScript code
Example use: jsinspect -I -L -t 20 --ignore "test" ./path/to/src


Options:

  -h, --help                         output usage information
  -V, --version                      output the version number
  -t, --threshold <number>           number of nodes (default: 30)
  -m, --min-instances <number>       min instances for a match (default: 2)
  -c, --config [config]              path to config file (default: .jsinspectrc)
  -r, --reporter [default|json|pmd]  specify the reporter to use
  -I, --no-identifiers               do not match identifiers
  -L, --no-literals                  do not match literals
  -C, --no-color                     disable colors
  --ignore <pattern>                 ignore paths matching a regex
  --truncate <number>                length to truncate lines (default: 100, off: 0)
  --debug                            print debug information

If a .jsinspectrc file is located in the project directory, its values will be used in place of the defaults listed above. For example:

{
  "threshold":     30,
  "identifiers":   true,
  "literals":      true,
  "color":         true,
  "minInstances":  2,
  "ignore":        "test|spec|mock",
  "reporter":      "json",
  "truncate":      100,
}

On first use with a project, you may want to run the tool with the following options, while running explicitly on the lib/src directories, and not the test/spec dir.

jsinspect -t 50 --ignore "test" ./path/to/src

From there, feel free to try decreasing the threshold, ignoring identifiers using the -I flag and ignoring literals with -L. A lower threshold may lead you to discover new areas of interest for refactoring or cleanup.

Integration

It's simple to run jsinspect on your library source as part of a build process. It will exit with an error code of 0 when no matches are found, resulting in a passing step, and a positive error code corresponding to its failure. For example, with Travis CI, you could add the following entries to your .travis.yml:

before_script:
  - "npm install -g jsinspect"

script:
  - "jsinspect ./path/to/src"

Note that in the above example, we're using a threshold of 30 for detecting structurally similar code. A higher threshold may be appropriate as well.

To have jsinspect run with each job, but not block or fail the build, you can use something like the following:

script:
  - "jsinspect ./path/to/src || true"

Reporters

Aside from the default reporter, both JSON and PMD CPD-style XML reporters are available. Note that in the JSON example below, indentation and formatting has been applied. Furthermore, the id property available in these reporters is useful for parsing by automatic scripts to determine whether or not duplicate code has changed between builds.

JSON

[{
  "id":"6ceb36d5891732db3835c4954d48d1b90368a475",
  "instances":[
    {
      "path":"spec/fixtures/intersection.js",
      "lines":[1,5],
      "code":"function intersectionA(array1, array2) {\n  array1.filter(function(n) {\n    return array2.indexOf(n) != -1;\n  });\n}"
    },
    {
      "path":"spec/fixtures/intersection.js",
      "lines":[7,11],
      "code":"function intersectionB(arrayA, arrayB) {\n  arrayA.filter(function(n) {\n    return arrayB.indexOf(n) != -1;\n  });\n}"
    }
  ]
}]

PMD CPD XML

<?xml version="1.0" encoding="utf-8"?>
<pmd-cpd>
<duplication lines="10" id="6ceb36d5891732db3835c4954d48d1b90368a475">
<file path="/jsinspect/spec/fixtures/intersection.js" line="1"/>
<file path="/jsinspect/spec/fixtures/intersection.js" line="7"/>
<codefragment>
spec/fixtures/intersection.js:1,5
function intersectionA(array1, array2) {
  array1.filter(function(n) {
    return array2.indexOf(n) != -1;
  });
}

spec/fixtures/intersection.js:7,11
function intersectionB(arrayA, arrayB) {
  arrayA.filter(function(n) {
    return arrayB.indexOf(n) != -1;
  });
}
</codefragment>
</duplication>
</pmd-cpd>
Comments
  • pmd-cpd report

    pmd-cpd report

    A pmd-cpd reporter would be nice. I could hook this up to Jenkins and have it create graphs overtime of violations.

    Looking at a few outputs from other tools that I use, it looks like it needs to be in the format: <?xml version="1.0" encoding="utf-8"?> <pmd-cpd> <duplication lines="2" tokens="38"> <file path="file/path1.js" line="1373"/> <file path="file/path2.js" line="1389"/> <codefragment> XML Escaped Code Fragment </codefragment> </duplication> </pmd-cpd>

    opened by trichins 18
  • False positives when matching identifiers is not set

    False positives when matching identifiers is not set

    Hi, jsinspect produces false positives for a check with the linked 2 files, when the -i parameter is NOT set. I used the node level 30, 40 Looks like for function arguments that are callback functions the function code is not checked. best regards Armin

    https://github.com/agienger/issue_files/blob/master/jsinspect/callBack1.js https://github.com/agienger/issue_files/blob/master/jsinspect/callBack2.js

    opened by agienger 10
  • SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

    SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

    Hi, Daniel,

    I have just tried this on 2 projects, got identical error block like this:

    /usr/local/lib/node_modules/jsinspect/lib/inspector.js:10 class Inspector extends EventEmitter { ^^^^^

    SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode at exports.runInThisContext (vm.js:53:16) at Module._compile (module.js:374:25) at Object.Module._extensions..js (module.js:417:10) at Module.load (module.js:344:32) at Function.Module._load (module.js:301:12) at Module.require (module.js:354:17) at require (internal/module.js:12:17) at Object. (/usr/local/lib/node_modules/jsinspect/bin/jsinspect:9:17) at Module._compile (module.js:410:26) at Object.Module._extensions..js (module.js:417:10)

    Not sure if this rule is over-enforced here. I have worked on 2 large existing ES6 projects. ES6 modules and classes are strict by default. Any chance you can take a look at this? Do you have a configuration entry that will suppress this error? Or a workaround?

    Thanks! William

    opened by williamku 8
  • Expose module additionally to binary

    Expose module additionally to binary

    Hey hey,

    just had a look on how to wrap jsinspect with a grunt task.

    In my mind, it would be much cleaner (and easier) if jsinspect would expose a binary and additionally a module, which makes it easier for other projects to use.

    Usually the binary is only for parsing arguments and handing it over to the module.

    E.g. a grunt task could spawn and child process using the binary, but an implemented module would be great.

    Please let me know, what you think of this.

    opened by stefanjudis 8
  • 0.11.4 false positive

    0.11.4 false positive

    0.11.4 is reporting the following duplication even though our threshold is set to 40 in the jsinspectrc. It wasn't reporting this false positive in 0.9:

    Match - 2 instances
    
    ./App/Containers/GuestJoinLayout.js:168,168
    </Animatable.View>
    
    ./App/Containers/SignInLayout.js:160,160
    </Animatable.View>
    
    ------------------------------------------------------------
    

    The relevant part of GuestJoinLayout.js:

     render () {
        return (
          <View style={Styles.container}>
            <View style={Styles.content}>
              <Animatable.View ref='content' animation='fadeInUp' duration={2000} ease='ease-in'>
                <LinearGradient
                  start={{x: 0.0, y: 0.0}} end={{x: 0.0, y: 1.0}}
                  locations={[0, 1]}
                  colors={['#074595', '#6589A4']}
                  style={Styles.signInContainer}
                >
                  {this.renderTitle()}
                  {this.renderMeetingId()}
                  {this.renderPasscode()}
                  {this.renderUsernameInput()}
                  {this.renderDropdown()}
                  {this.renderJoinButton()}
                  {/* this.renderSignIn() */}
                </LinearGradient>
              </Animatable.View>
            </View>
          </View>
        )
      }
    

    and SignInLayout.js:

    render () {
        return (
          <Animatable.View ref='container' style={Styles.container} easing='ease-in'>
            <LinearGradient
              start={{x: 0.0, y: 0.0}} end={{x: 0.0, y: 1.0}}
              locations={[0, 1]}
              colors={['#074595', '#6589A4']}
              style={Styles.blurOverlay}>
              <View style={Styles.content}>
                {this.renderLogo()}
                {this.renderErrorMessage()}
                {this.renderUsernameInput()}
                {this.renderPasswordInput()}
                {this.renderNextButton()}
                {this.renderSignInOptions()}
                {this.renderSignUp()}
              </View>
            </LinearGradient>
          </Animatable.View>
        )
      }
    
    opened by matthargett 6
  • Reexporting is not supported

    Reexporting is not supported

    I have this code:

    export * as util from './util';
    

    Checking of this files throws the type of null error I fixed it by refactoring:

    import * as util from './util';
    export { util };
    

    Anyway it will be great to fix it

    opened by timbset 6
  • Alternative parser

    Alternative parser

    I plan in creating a Vscode extension that provides in editor feedback for copy pasted code. The only problem i have is that i need to process code with Flowtype type annotations in it. I have been using flowparser package with great success previously since it produces output compatible with most of the other parsers and also works fine with tools such as Recast, Jscodeshift etc. Wondering if there is an easy way to make the parser configurable via options ? thanks.

    opened by gcazaciuc 5
  • GNU message format

    GNU message format

    Came across it at https://github.com/anandthakker/doiuse/issues/1

    Seems rather trivial in comparison to the current default format, to add support for this format style. Format specified https://www.gnu.org/prep/standards/html_node/Errors.html

    opened by paazmaya 5
  • ignore files in .gitignore ?

    ignore files in .gitignore ?

    is a good feature ignore the files and directories in .gitignore file ?

    normally .gitignore have files/directories like coverage, lib-cov, results, etc

    opened by juanpabloaj 4
  • throws error if run as npm script

    throws error if run as npm script

    When I run $ jsinspect <path> directly from the command line, it works as expected. However when I run it as an npm script ($ npm run jsinspect)

    "scripts": {
      "jsinspect": "jsinspect src/"
    },
    

    and matches are found, error is thrown:

     1 match found across 2 files
    
    npm ERR! Darwin 15.5.0
    npm ERR! argv "/Users/aborowski/.nvm/versions/node/v6.3.1/bin/node" "/Users/aborowski/.nvm/versions/node/v6.3.1/bin/npm" "run" "jsinspect"
    npm ERR! node v6.3.1
    npm ERR! npm  v3.10.3
    npm ERR! code ELIFECYCLE
    npm ERR! [email protected] jsinspect: `jsinspect src/`
    npm ERR! Exit status 1
    
    opened by adekbadek 3
  • Process out of memory

    Process out of memory

    I have a Windows 10 machine with 8 gb of RAM. First time I run jsinspect in one of my projects and I get this:

    $ jsinspect
    [
    <--- Last few GCs --->
    
      208383 ms: Scavenge 1402.4 (1457.2) -> 1402.4 (1457.2) MB, 15.8 / 0 ms (+ 2.0 ms in 1 steps since last GC) [allocation failure] [incremental marking delaying mark-sweep].
      210220 ms: Mark-sweep 1402.4 (1457.2) -> 1401.4 (1456.2) MB, 1836.9 / 0 ms (+ 4.0 ms in 2 steps since start of marking, biggest step 2.0 ms) [last resort gc].
      211992 ms: Mark-sweep 1401.4 (1456.2) -> 1400.9 (1457.2) MB, 1771.8 / 0 ms [last resort gc].
    
    
    <--- JS stacktrace --->
    
    ==== JS stack trace =========================================
    
    Security context: 000003A02DCB4639 <JS Object>
        1: finishNode [C:\Users\miparnisari\AppData\Roaming\npm\node_modules\jsinspect\node_modules\acorn\dist\acorn_loose.js:~647] [pc=00000259F86AE55F] (this=000001850C2CBAB1 <a LooseParser with map 0000035629E4CA89>,node=0000010720CDDF69 <a Node with map 0000035629E4D6E9>,type=000000B68F9CC089 <String[16]: MemberExpression>)
        2: parseSubscripts [C:\Users\miparnisari\AppData\Roaming\npm\node...
    
    FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
    

    I am using these settings:

    {
      "threshold":     30,
      "identifiers":   true,
      "matches":       3,
      "ignore":        "Test.js|Spec.js",
      "jsx":           false,
      "reporter":      "json",
      "suppress":      100
    }
    

    EDIT: I used WindDirStat to know how many JS files there are: 23,540. It's a lot but I'm assuming that we are not scanning the files within .git or node_modules, right?

    opened by miparnisari 3
  • Is this project still maintained?

    Is this project still maintained?

    I really like this project and I'm an active user of jsinspect, it helps me improve my code quality, but I can not use it with newer JS and JSX features. As I see no changes were merged into the master branch already 2 years and some PRs with some updates to support new features are still waiting to be reviewed for at least one year. @danielstjules is this repo still maintained or you'd like to give to somebody else to take care of it?

    opened by micnic 3
  • Single line match reported when there is no match

    Single line match reported when there is no match

    Hi! Thanks for the awesome tool!

    The following blocks of code

    const query = new Query()
    // q (Keyword query)
      .addParam('q', queryToString(params.searchText, '+'))
    

    and

    const query = JobQueries.manageableQuery()
      .includeCompany()
    

    Together reported by jsinspect

    ------------------------------------------------------------
    Match - 2 instances
    
    ./service1.js:78,78
    const query = new Query()
    
    ./service2.js:316,316
    const query = JobQueries.manageableQuery()
    ------------------------------------------------------------
    

    Which apparently shouldn't happen.

    opened by elmeister 0
  • [feature request] support suffix other than .js or .jsx

    [feature request] support suffix other than .js or .jsx

    Hi Thanks for creating this brilliant tool. Our project is trying to use this tool, however we want to apply it to a script language defined by our own. It's syntax is a subset of JavaScript so the tool works well on the texts. The only problem is that we are using a suffix defined by ourself. Is it possible to let JsInspect accept an argument to include certain type of files? Thanks

    opened by JillShu 2
  • FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

    FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

    When i run the command jsinspect ./myfolder/ it results in out of memory issue.

    <--- Last few GCs --->

    [79346:0x103801600] 27292 ms: Mark-sweep 1369.3 (1445.8) -> 1358.1 (1447.3) MB, 959.0 / 0.2 ms (average mu = 0.122, current mu = 0.068) allocation failure scavenge might not succeed [79346:0x103801600] 28349 ms: Mark-sweep 1372.3 (1447.8) -> 1361.1 (1449.3) MB, 989.9 / 0.2 ms (average mu = 0.093, current mu = 0.063) allocation failure scavenge might not succeed

    <--- JS stacktrace --->

    ==== JS stack trace =========================================

    0: ExitFrame [pc: 0x3f21725be3d]
    

    Security context: 0x145d8079e6e1 1: _insert [0x145d574a83e1] [/usr/local/lib/node_modules/jsinspect/lib/inspector.js:~142] [pc=0x3f21791c0ad](this=0x145d9c582271 ,nodes=0x145d017f2309 <JSArray[30]>) 2: /* anonymous /(aka / anonymous */) [0x145d017ee941] [/usr/local/lib/node_modules/jsinspect/lib/inspector.js:64] [bytecode=0x145dabc68fb1 offset=11]...

    FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory 1: 0x10003ae75 node::Abort() [/usr/local/bin/node] 2: 0x10003b07f node::OnFatalError(char const*, char const*) [/usr/local/bin/node] 3: 0x1001a7ae5 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [/usr/local/bin/node] 4: 0x100572ef2 v8::internal::Heap::FatalProcessOutOfMemory(char const*) [/usr/local/bin/node] 5: 0x1005759c5 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [/usr/local/bin/node] 6: 0x10057186f v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [/usr/local/bin/node] 7: 0x10056fa44 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [/usr/local/bin/node] 8: 0x10057c2dc v8::internal::Heap::AllocateRawWithLigthRetry(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node] 9: 0x10057c35f v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [/usr/local/bin/node] 10: 0x10054b6f6 v8::internal::Factory::NewFixedArrayWithFiller(v8::internal::Heap::RootListIndex, int, v8::internal::Object*, v8::internal::PretenureFlag) [/usr/local/bin/node] 11: 0x100690ffc v8::internal::DescriptorArray::Allocate(v8::internal::Isolate*, int, int, v8::internal::PretenureFlag) [/usr/local/bin/node] 12: 0x10068ba3e v8::internal::Map::EnsureDescriptorSlack(v8::internal::Handlev8::internal::Map, int) [/usr/local/bin/node] 13: 0x100697f09 v8::internal::Map::ShareDescriptor(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::DescriptorArray, v8::internal::Descriptor*) [/usr/local/bin/node] 14: 0x1006838c4 v8::internal::Map::CopyAddDescriptor(v8::internal::Handlev8::internal::Map, v8::internal::Descriptor*, v8::internal::TransitionFlag) [/usr/local/bin/node] 15: 0x1006836e2 v8::internal::Map::CopyWithField(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::FieldType, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Representation, v8::internal::TransitionFlag) [/usr/local/bin/node] 16: 0x100699f32 v8::internal::Map::TransitionToDataProperty(v8::internal::Handlev8::internal::Map, v8::internal::Handlev8::internal::Name, v8::internal::Handlev8::internal::Object, v8::internal::PropertyAttributes, v8::internal::PropertyConstness, v8::internal::Object::StoreFromKeyed) [/usr/local/bin/node] 17: 0x100664b38 v8::internal::LookupIterator::PrepareTransitionToDataProperty(v8::internal::Handlev8::internal::JSReceiver, v8::internal::Handlev8::internal::Object, v8::internal::PropertyAttributes, v8::internal::Object::StoreFromKeyed) [/usr/local/bin/node] 18: 0x10068a394 v8::internal::Object::AddDataProperty(v8::internal::LookupIterator*, v8::internal::Handlev8::internal::Object, v8::internal::PropertyAttributes, v8::internal::ShouldThrow, v8::internal::Object::StoreFromKeyed) [/usr/local/bin/node] 19: 0x1007f1459 v8::internal::Runtime::SetObjectProperty(v8::internal::Isolate*, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, v8::internal::Handlev8::internal::Object, v8::internal::LanguageMode) [/usr/local/bin/node] 20: 0x1007f4ca3 v8::internal::Runtime_SetProperty(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/local/bin/node] 21: 0x3f21725be3d Abort trap: 6

    How to resolve this issue?

    opened by tonystark93 0
  • Consider different font colour for showing matching code blocks

    Consider different font colour for showing matching code blocks

    Just found jsinspect, and it's really cool. Great work. I wanted to mention one issue I found while using it. In my terminal (iTerm2) I use Solarized Dark for the colour theme (pretty common), and here is what the matching code blocks look like, (i.e., invisible):

    screen shot 2018-12-09 at 2 43 53 pm

    It might be good to consider just using the same colour you already use for the file/lines, since that shows up perfectly.

    opened by humphd 1
Releases(0.12.7)
Owner
Daniel St. Jules
Daniel St. Jules
Find and fix problems in your JavaScript code.

ESLint Website | Configuring | Rules | Contributing | Reporting Bugs | Code of Conduct | Twitter | Mailing List | Chat Room ESLint is a tool for ident

ESLint 22k Jan 8, 2023
🌟 JavaScript Style Guide, with linter & automatic code fixer

JavaScript Standard Style Sponsored by English • Español (Latinoamérica) • Français • Bahasa Indonesia • Italiano (Italian) • 日本語 (Japanese) • 한국어 (Ko

Standard JS 27.8k Dec 31, 2022
ECMAScript code beautifier/formatter

esformatter ECMAScript code beautifier/formatter. Important This tool is still missing support for many important features. Please report any bugs you

Miller Medeiros 968 Nov 1, 2022
The easiest way of running code in a browser environment

browser-run The easiest way of running code in a browser environment. Bundles electronjs by default! Usage $ echo "console.log('Hey from ' + location)

Julian Gruber 415 Dec 19, 2022
Started pack for working with the new GameTest Framework API. Usable in windows, and mobile in worlds and realms!

GameTest FrameWork GameTest FrameWork is a new feature in Minecraft Bedrock Edition. This gives you the ability to script! In this example I will be u

null 40 Dec 24, 2022
A CLI to add and remove local development environments and create HTTPS certificates for them.

A CLI used to create a local https dev environment with the green lock. Setup takes less than 5 minutes and all of your projects will be running locally over HTTPS with custom domain names in no time!

Entrostat (Pty) Ltd 5 Sep 19, 2022
Infinite Red's cutting edge React Native project boilerplate, along with a CLI, component/model generators, and more!

Ignite - the hottest React Native boilerplate Battle-tested React Native boilerplate The culmination of five years of constant React Native developmen

Infinite Red, Inc. 14.7k Dec 29, 2022
Test your internet connection speed and ping using speedtest.net from the CLI

speed-test Test your internet connection speed and ping using speedtest.net from the CLI Install Ensure you have Node.js version 8+ installed. Then ru

Sindre Sorhus 3.8k Jan 7, 2023
Move files and directories to the trash

Move files and folders to the trash Works on macOS (10.12+), Linux, and Windows (8+). Note: The Linux implementation is not very good and not maintain

Sindre Sorhus 2.4k Dec 29, 2022
Pipeable javascript. Quickly filter, map, and reduce from the terminal

Pipeable JavaScript - another utility like sed/awk/wc... but with JS! Quickly filter, map and reduce from the command line. Features a streaming API.

Daniel St. Jules 410 Dec 10, 2022
Kill all Chrome tabs to improve performance, decrease battery usage, and save memory

kill-tabs Kill all Chrome tabs to improve performance, decrease battery usage, and save memory Works on macOS, Linux, Windows. I'm a tab-abuser and I

Sindre Sorhus 371 Jan 8, 2023
📜 Create mutable log lines into the terminal, and give life to your logs!

Because Logging can be pretty and fun Installation $ npm install draftlog What it does It allows you to re-write a line of your log after being writt

Ivan Seidel 1.2k Dec 31, 2022
HMSC (How Much Stuffs CLI) analyst for your files and folders

HMSC ?? About HMSC (How Much Stuffs CLI) analyst for your files and folders ?? Screenshot ?? Requirements Node.js NPM ?? Installation $ npm i -g hmsc

Abdullah Veliyev 26 Jan 10, 2022
Add a hungry turtle to your terminal and feed it every time you mistype 'npm' as 'nom'

Nom Does this ever happen to you? You happily code away on a project, navigating the command line like a pro, testing, error logging, installing packa

Meike Hankewicz 5 Apr 26, 2022
replacement for comma.ai backend and useradmin dashboard. comes bundled with a modified cabana instance for seamless drive reviewing.

retropilot-server Replacement for comma.ai backend and useradmin dashboard. Bundled with a modified version of comma's cabana to allow viewing & analy

Florian Brede 39 Dec 4, 2022
Tasks Management CLI application with Nodejs, Mongodb, inquirer.js, and commander

Tasks CLI Tasks CLI is a program to manage your tasks in a database using terminal or console. This is a sample project for beginners Requirements Nod

Fazt Web 9 Nov 17, 2022
A simple CLI tool to create and manage xhelpers-api projects

A simple CLI tool to create and manage xhelpers-api projects

null 2 Feb 25, 2022
A fullstack(NestJS、React) framework for building efficient and scalable applications

A fullstack(NestJS、React) framework for building efficient and scalable applications. Description The Kunlun CLI is a command-line interface tool that

图灵人工智能研究院前端技术团队 3 Mar 12, 2022