{"id":13483364,"url":"https://github.com/local-npm/local-npm","last_synced_at":"2025-05-15T18:11:29.494Z","repository":{"id":19351574,"uuid":"22590963","full_name":"local-npm/local-npm","owner":"local-npm","description":"Local and offline-first npm mirror","archived":false,"fork":false,"pushed_at":"2020-02-24T19:45:19.000Z","size":4945,"stargazers_count":1166,"open_issues_count":33,"forks_count":81,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-07T02:02:20.315Z","etag":null,"topics":["mirror","node","npm","offline","registrty"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/local-npm.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-04T03:36:53.000Z","updated_at":"2025-04-08T11:58:48.000Z","dependencies_parsed_at":"2022-09-10T20:12:12.724Z","dependency_job_id":null,"html_url":"https://github.com/local-npm/local-npm","commit_stats":null,"previous_names":["nolanlawson/local-npm"],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/local-npm%2Flocal-npm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/local-npm%2Flocal-npm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/local-npm%2Flocal-npm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/local-npm%2Flocal-npm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/local-npm","download_url":"https://codeload.github.com/local-npm/local-npm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254394726,"owners_count":22063984,"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":["mirror","node","npm","offline","registrty"],"created_at":"2024-07-31T17:01:10.466Z","updated_at":"2025-05-15T18:11:29.475Z","avatar_url":"https://github.com/local-npm.png","language":"JavaScript","funding_links":[],"categories":["Packages","JavaScript","npm"],"sub_categories":["Other"],"readme":"\u003cimg alt=\"local-npm\" width=\"500px\" src=\"https://cdn.rawgit.com/local-npm/local-npm/8a78d31af0ecfd1d9dfb06ac985a7beacc343f35/assets/logo.svg\" /\u003e\n\n[![Build Status](https://travis-ci.org/local-npm/local-npm.svg)](https://travis-ci.org/local-npm/local-npm) [![Coverage Status](https://lcov-server.herokuapp.com/badge/github%2Ecom/local-npm/local-npm.svg)](https://lcov-server.herokuapp.com/coverage/github%2Ecom/local-npm/local-npm)\n\n`local-npm` is a Node server that acts as a local npm registry. It serves modules, caches them, and updates them whenever they change. Basically it's a local mirror, but without having to replicate the entire npm registry.\n\nThis allows your `npm install` commands to (mostly) work offline. Also, they get faster and faster over time, as commonly-installed modules are aggressively cached.\n\n\u003c!-- TOC depthFrom:1 depthTo:6 withLinks:1 updateOnSave:1 orderedList:0 --\u003e\n\n- [Introduction](#introduction)\n- [Usage](#usage)\n\t- [Listening for events](#listening-for-events)\n- [Command line options](#command-line-options)\n- [Browser UI](#browser-ui)\n- [Switching with npmrc](#switching-with-npmrc)\n- [Speed test](#speed-test)\n- [How it works](#how-it-works)\n- [Using with Docker](#using-with-docker)\n\n\u003c!-- /TOC --\u003e\n\n# Introduction\n\n`local-npm` acts as a proxy between you and the main npm registry. You run `npm install` commands like normal, but under the hood, all requests are sent through the local server.\n\nWhen you first `npm install` a module, it'll be fetched from the main npm registry. After that, the module and all its dependencies (at that version) are stored in a local database, so you can expect subsequent installs to be much faster.\n\nThe server will also listen for changes from the remote registry, so you can expect updates to a module's metadata to be replicated within seconds of being published. (I.e. you won't get stuck with old versions.)\n\nIf you're organizing a conference/meetup/whatever, you can also share this local server with multiple people.  So if your teammates are constantly installing the same modules over and over again, this can save a lot of time in the long run.\n\n`local-npm` is also a good way to make `npm install` work offline. Assuming new versions of a package haven't been published since you last installed, subsequent `npm install`s will all serve from the cache, without ever hitting a remote server.\n\nAddy Osmani has [a nice post](https://addyosmani.com/blog/using-npm-offline/) comparing `local-npm` to other options.\n\n# Usage\n\nIf you're using OS X, take a look at [local-npm-launch-agent](https://github.com/local-npm/local-npm-launch-agent), a one-liner that sets everything up automatically. Otherwise:\n\n    $ npm install -g local-npm\n\nThen\n\n    $ local-npm\n\nto start the server. (Note that it will write files in whatever directory you run it from.)\n\nThen set `npm` to point to the local server:\n\n    $ npm set registry http://127.0.0.1:5080\n\nTo switch back, you can do:\n\n    $ npm set registry https://registry.npmjs.org\n\nThe same rules as for the [npm Australia mirror](http://www.npmjs.org.au/) apply here.\n\n## Listening for events\n\n\u003e to listen to process level events to collecting metrics use the global event emitter to introspect on these - _events can be one of the following_ (info, warn, missed, cached, request)\n\n```javascript\nrequire('local-npm')({\n    port: 5080,\n    pouchPort: 6789,\n    remote: 'https://registry.npmjs.org',\n    remoteSkim: 'https://replicate.npmjs.com',\n    url: 'http://127.0.0.1:5080',\n    directory: './'\n});\nprocess.on('request', (msg) =\u003e {\n  console.log(msg);\n})\n```\n\n# Command line options\n\n```\nUsage: local-npm [options]\n\nOptions:\n\n\t-h, --help                   output usage information\n\t-V, --version                output the version number\n\t-p, --port [port]            The port to run local-npm on\n\t-pp, --pouch-port [port]     The port to run the pouch db server on\n\t-l, --log-level [level]      The level to log information to the console from local-npm\n\t-r, --remote [url]           The registry to fallback information gathering and tars on\n\t-rs, --remote-skim [url]     The remote skimdb to sync couchdb information from\n\t-u, --url [url]              The default access url that local-npm will be hosted on\n\t-d, --directory [directory]  directory to store data\n```\n\n**Protip**: You can replicate from your friend's `local-npm` to your own `local-npm` by simply pointing at it:\n\n```\n$ local-npm \\\n   --remote http://\u003cfriends_hostname\u003e:5080 \\\n   --remote-skim http://\u003cfriends_hostname\u003e:16984/skimdb\n```\n\nWhile your friend does:\n\n```\n$ local-npm \\\n   --url http://\u003cfriends_hostname\u003e:5080\n```\n\nIn this way, you can create a daisy chain of awesome.\n\n**Protip 2**: If you want to set up a single `local-npm` for multiple people to use, such as for conferences or workplaces, then just daemonize it (e.g. using [forever](https://www.npmjs.org/package/forever)), and then when you run it, specify the URL that clients will use to access the server, e.g.:\n\n```\n$ local-npm \\\n    --url http://192.168.x.x:5080\n```\n\nThis will ensure that clients fetch tarballs from `192.168.x.x` instead of `127.0.0.1`.\n\nIf you want a GUI or don't want to run it from the command-line is an electron app for that! [https://github.com/local-npm/local-npm-daemon](https://github.com/local-npm/local-npm-daemon)\n\n![local-npm-daemon](https://github.com/local-npm/local-npm-daemon/raw/master/assets/example.png)\n\n# Browser UI\n\nA rudimentary npm-like UI that allows you to search modules and see their descriptions can be found at [http://localhost:5080/_browse](http://localhost:5080/_browse).\n\n| main | package |\n|------|---------|\n| ![main.png](./assets/main.png) | ![package.png](./assets/package.png) |\n\nIf you haven't finished replicating the remote skimdb, then not all the modules will be visible yet.\n\n# Switching with npmrc\n\nFeatures like `npm search` are currently unsupported. So to avoid having to remember URLs when switching back and forth, you can use `npmrc` like so (based on the instructions for [the Australian mirror of npm](http://www.npmjs.org.au/)):\n\n\n    $ npm install -g npmrc\n    $ npmrc -c local\n    $ npm set registry http://127.0.0.1:5080\n\nthen to search:\n\n    $ npmrc default\n\nand to switch back:\n\n    $ npmrc local\n\nIncidentally, though, `local-npm` does allow you to do `npm login` and `npm publish`. These commands will just be proxied to the main npm registry.\n\n# Speed test\n\nFor a speed test of `local-npm` versus regular npm, [see these results](https://github.com/local-npm/test-local-npm-speed#readme).\n\n# How it works\n\nnpm is built on top of CouchDB, so `local-npm` works by replicating the full \"skimdb\" database to a local [PouchDB Server](https://github.com/pouchdb/pouchdb-server). You can inspect the running database at [http://127.0.0.1:16984/_utils](http://127.0.0.1:16984/_utils). (Don't write to it!)\n\nThe entire \"skimdb\" (metadata) is replicated locally, but for the \"fullfatdb\" (metadata plus tarballs), only what you `npm install` is stored. To start from scratch, just delete whatever directory you started the server in.\n\nCouchDB has a changes feed, so `local-npm` just listens to the `skimdb` changes to know when it needs to refresh an outdated module. Changes should replicate within a few seconds of being published. (You can watch this happen in realtime by reading the logs, which is kind of fun! An update comes in whenever someone publishes a module.)\n\nNote that new tarballs aren't downloaded until you explicitly `npm install` them, though. So e.g. if you install `v1.0.0` of a package, then `v1.0.1` is published, and your range says `^1.0.0`, then the next `npm install` will fail unless you're online and can fetch the new tarball.\n\n# Using with Docker\n\nUsing local-npm with Docker can help speed up build times during development.\nThe awkward way to use this would be something like:\n\n```\nRUN local-npm \u0026\u0026 \\\n    npm set registry http://... \u0026\u0026 \\\n    npm set proxy .... \u0026\u0026 \\\n    npm install some packages etc ...\n```\n\nRunning services inside of a Docker build command isn't really Docker's business.  The friendly scenario works better in this case, i.e. you run local-npm on the host machine:\n\n```\nlocal-npm --url=http://\u003cnetwork host or ip\u003e:5080\n```\n\nAnd adding the npm registry/proxy commands to your Dockerfile:\n\n```\nRUN npm config set proxy http://\u003cnetwork host or ip\u003e:5080\nRUN npm config set proxy http://\u003cnetwork host or ip\u003e:5080\nRUN npm config set registry http://\u003cnetwork host or ip\u003e:5080\nRUN npm config set strict-ssl false\nRUN npm install project dependencies ...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocal-npm%2Flocal-npm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocal-npm%2Flocal-npm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocal-npm%2Flocal-npm/lists"}