Redirecting… Click here if not redirected.

On the Shoulders of Giants: Package Registries, Node & NPM

Tutorial — You don't need to build everything from scratch. Learn how packages and registries work—the infrastructure that powers modern development. You'll see this pattern everywhere: NPM, Docker Hub, ClawHub, and more.

Series: Foundations of Digital Agency — Part 7 Part 6: Commanding the Command Line Part 8: All About AI & Using LLM Tools
You've mastered the command line. In the last lesson, you even installed software with `sudo apt install` — that was your first brush with a package manager pulling from a registry. Now it's time to understand what's actually happening under the hood, and how modern developers leverage the work of others at scale: through packages, registries, and package managers.

Everything that comes next—Claude Code, Docker, OpenClaw, web applications—builds on the concepts you're about to learn. And at the center of all of it is a simple idea: **reusable code, stored in a central place, installed with a single command**. This is where we leverage the power of the Internet and begin to see the open-source community come into play.

Let's start with the why, then move to the how.

---

## What is a Package?

A **package** (also called a module or library) is a collection of reusable code that someone else wrote, tested, and shared. Instead of writing authentication from scratch, you install a package that handles it. Instead of building a web server from the ground up, you install a package that does it for you.

Packages can be:
- **Small utilities**: A function that formats dates, validates emails, or parses JSON
- **Large frameworks**: Complete systems for building web applications, managing databases, or running AI agents
- **Tools and CLIs**: Command-line applications you run directly

## What Problem Do Registries Solve?

Before registries, developers had to email code to each other, host code on personal websites, track versions manually, and hope dependencies didn't break. A **registry** is a centralized, organized library where developers can publish packages and others can install them. Think of it like an app store, but for code.

The most famous registry nowadays is the **NPM Registry**—the default home for JavaScript/Node.js packages. But the pattern appears everywhere:
- **APT** — Registry for Ubuntu/Debian Linux packages (you used this in the last lesson with `sudo apt install`)
- **Docker Hub** — Registry for container images
- **PyPI** — Registry for Python packages
- **ClawHub** — Registry for OpenClaw AI agent configurations

## What About GitHub?
GitHub isn't a registry for packages, but it plays a similar role and is crucial in the ecosystem: it’s a code repository hosting platform (one of several) where developers store their source code using Git version control. Most open-source packages (NPM, Docker, etc.) have their source code hosted on GitHub. Developers also collaborate on code through GitHub. And, while you can also install packages directly from GitHub repos (`npm install github:username/repo`), you'll also be able to clone many GitHub code repositories that are not packages, such as apps and projects. Like package registries, it's a vital way to build on the success of others.

## How Registries Work

Here's the flow:

1. **Developer writes code** (e.g., a useful function)
2. **Developer publishes to registry** with a version number and metadata
3. **You install from registry** with a single command: `npm install package-name`
4. **Registry delivers the code** to your project
5. **You use the code** in your application

That's it. The registry is the middleman—a trusted place where packages live, versions are tracked, and installation is automatic.

You've already seen this exact flow in action. In the last lesson, when you ran:
```bash
sudo apt-get update
sudo apt install tree
```
`apt-get update` fetched the latest list of available packages from Ubuntu's registry. `apt install` then pulled `tree` down and installed it. Same pattern — different registry, different package manager, same idea.

## Risks You Need to Know

Registries are powerful, but they come with responsibilities:

**1. Security Vulnerabilities**
Packages can have bugs or security holes. A popular package with a vulnerability could affect thousands of projects. Always:
- Keep packages updated (`npm update`)
- Check package reputation before installing
- Use `npm audit` to find known vulnerabilities

The same applies to your Linux system packages. Run these periodically to pull the latest security patches from the APT registry:
```bash
sudo apt update && sudo apt upgrade
```

**2. Unmaintained Packages**
A developer might stop maintaining a package. If it breaks or has a security issue, you're on your own. Check:
- When was the last update?
- Is the repository active?
- How many people use it? (Popular = more eyes, more fixes)

**3. Breaking Changes**
New versions of packages might not work with your code. A seemingly small update could break your entire application. This is why **versioning** matters (we'll cover this below).

**4. Supply Chain Risk**
If you install 10 packages, and each installs 5 more, you're now depending on 50+ packages. One vulnerability in any of them affects you. Be intentional about what you install.

Further down we'll cover how to audit your packages.

## How Packages Are Versioned

Packages use **semantic versioning** (semver): `MAJOR.MINOR.PATCH`

Example: `1.2.3`
- **1** (major) — Breaking changes. Code might not work.
- **2** (minor) — New features, but backwards compatible.
- **3** (patch) — Bug fixes only, always safe.

When you install a package, you specify which versions you're willing to accept:
- `1.2.3` — Exactly this version
- `^1.2.3` — Any version up to `2.0.0` (minor and patch updates okay)
- `~1.2.3` — Any version up to `1.3.0` (patch updates only)
- `*` or `latest` — Always the newest (risky!)

Your `package.json` file tracks this, ensuring your project stays reproducible.

---

## What is Node.js?
JavaScript is one of the most accessible and widely-used programming languages. It's forgiving and relatively easy to learn. For decades, it only ran in browsers. Then Node.js arrived in 2009. **Node.js** is a JavaScript runtime environment. It lets you run JavaScript on your computer, on servers, and in development tools.

This means you can write or download JavaScript scripts and applications that run on your machine -- some as CLIs.

Result: NPM (Node Package Manager) is now the largest package registry in the world (over 2 million packages). JavaScript developers could write reusable code once and share it. That accessibility cascaded into an ecosystem. This is why you'll see Node.js/JavaScript everywhere in development tools—from build systems to CLI tools to web servers.

## Installing Node.js and NPM

Node.js and NPM come together. When you install Node.js, you automatically get NPM.

Download and install nvm:
```bash
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
```
In lieu of restarting the shell:
```bash
\. "$HOME/.nvm/nvm.sh"
```
Download and install Node.js:
```bash
nvm install 24
```
Verify the Node.js version:
```bash
node -v # Should print "v24.16.0".
```
Verify npm version:
```bash
npm -v # Should print "11.13.0".
```

> The above works on WSL and macOS (even though it says `bash`). However, the version numbers above may become outdated; refer to the page below for the current version.
> 
> https://nodejs.org/en/download

## Creating a Project: `npm init`

We're not quite getting into projects yet, but when you start a new project, you initialize it with NPM:

```bash
mkdir my-project
cd my-project
npm init
```

NPM asks questions about your project (name, description, author, etc.). Answer them or press Enter to accept defaults — or skip the questions entirely with `npm init -y`. Either way, this creates **`package.json`** — the most important file in your project.

When you're done, enter the following to open the project in VS Code:
```bash
code .
```

## Understanding package.json

`package.json` is the contract for your project. It tells others (and future you):
- What your project is
- What dependencies it needs
- What scripts it can run
- What version it is

Example:
```json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "My awesome project",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "build": "echo Building...",
    "test": "echo Running tests..."
  },
  "dependencies": {
    "express": "^4.18.0",
    "axios": "^1.4.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }
}
```

**Key sections:**
- **`scripts`** — Commands you can run (`npm start`, `npm run build`)
- **`dependencies`** — Packages your project needs to run
- **`devDependencies`** — Packages you only need during development (testing, build tools, etc.)

## Installing Packages

Install a package with:
```bash
npm install express
```

This:
1. Downloads `express` from NPM Registry
2. Adds it to `dependencies` in `package.json`
3. Creates `node_modules/` folder (contains the actual code)
4. Creates `package-lock.json` (locks exact versions for reproducibility)

Install a development-only package:
```bash
npm install --save-dev nodemon
```

This adds it to `devDependencies` instead.

## Understanding node_modules

When you install packages, NPM creates a `node_modules/` folder. This folder contains:
- The package you installed
- All of its dependencies
- All of *their* dependencies
- And so on...

It can get HUGE (hundreds of MB).
* Always commit `package.json` and `package-lock.json` to Git.
* Never commit `node_modules/` — it's too large, so it should be in your `.gitignore` (we'll learn about Git in a future entry in the series).
* When someone clones your project, they run `npm install` and it rebuilds `node_modules` from `package.json`.

## Updating Packages

Check for outdated packages:
```bash
npm outdated
```

Update packages to their latest versions (respecting semver rules):
```bash
npm update
```

Update a specific package:
```bash
npm install express@latest
```

**Caution:** Updating can introduce breaking changes. Always test after updating, and commit your work first so you can revert if needed.

## Running Scripts

You define scripts in `package.json`:

```json
"scripts": {
  "start": "node index.js",
  "dev": "nodemon index.js",
  "build": "webpack",
  "test": "jest"
}
```

Run them with:
```bash
npm start
npm run dev
npm run build
npm test
```

Scripts are shortcuts. `npm start` is the same as running the command specified. This is why they're powerful—you can hide complex commands behind simple names.

## How Can I Audit My Packages for Security/Bugs?

Security vulnerabilities in packages are inevitable. The good news: tools exist to help you manage them.

**Manual audits with npm CLI:**

When you're working in your project locally, you can run `npm audit` to check for known vulnerabilities in your packages. It scans against a database of known issues and suggests fixes. This is a manual check you do when you remember to do it.

**Continuous monitoring (future):**

When you later learn about version control with GitHub, you'll discover a tool called **Dependabot** that works alongside your package manager. Here's the idea:

- Your package manager (NPM) handles installation and updates
- Your code hosting platform (GitHub) can monitor your packages continuously
- Dependabot automatically scans for vulnerabilities, notifies you of issues, and suggests updates
- It never sleeps—it's checking your dependencies while you work on other things

This is an example of how tools in the ecosystem work together: one tool for packages, another for monitoring. You'll see this pattern throughout development—specialized tools doing specific jobs, all integrated together.

**For now:** Just know that security monitoring exists and is important. When you start working with version control and GitHub, you'll see how these tools connect.

**Auditing Linux system packages:**

APT doesn't have a direct equivalent to `npm audit`, but you can check what's pending before pulling it in:
```bash
apt list --upgradable
```
On Ubuntu, this gives a security-focused summary:
```bash
ubuntu-security-status
```
The main defense is simply staying current — run `sudo apt update && sudo apt upgrade` regularly.

## Tools Worth Knowing About

**nvm** — Node Version Manager
```bash
nvm install 18
nvm use 18
```
Manage multiple Node.js versions. Useful when different projects need different versions.

**npx** — Run packages without installing globally
```bash
npx create-react-app my-app
```
Downloads and runs a package once, without installing it permanently. Great for one-off tools and generators.

**Yarn** — Alternative to NPM
```bash
yarn install
yarn add express
```
Different package manager with similar features. Some developers prefer it. For now, stick with NPM—they work the same way conceptually.

---

## Registries: A Pattern You'll See Everywhere

Here's the crucial connection:

**APT** is a registry of **Linux system packages** (you've already used it).

**NPM Registry** is a registry of **packages** (JavaScript code).

**Docker Hub** is a registry of **images** (containerized applications).

**ClawHub** is a registry of **AI skills** for OpenClaw.

The pattern is identical:
1. Someone creates something useful
2. They publish it to a registry with metadata and versioning
3. You install it with a command
4. You use it in your work

You now understand:
- What packages are and why they matter
- How registries work as central libraries
- The risks and how to manage them
- How to use NPM and manage dependencies
- That this pattern repeats everywhere

This pattern — publish, version, install — is one of the most important mental models in modern development. You'll keep running into it. Next we'll get into AI.

---

> **Sources / additional material:**
>
> https://docs.npmjs.com/
>
> https://nodejs.org/en/docs/
>
> https://docs.npmjs.com/cli/v9/configuring-npm/package-json
>
> https://semver.org/ — Semantic Versioning specification
>
> https://docs.npmjs.com/downloading-and-installing-packages-locally

_This article was generated with AI for the purpose of providing practical information. I have reviewed it and edited it appropriately._