GitHub - yowainwright/codependence: Stop wrestling with code dependencies. Use Codependence! 🤼‍♀️ (original) (raw)

npm version npm downloads TypeScript CI OpenSSF Scorecard codecov GitHub stars

Enforce dependency version policy wherever your project needs it.

Codependence is a CLI and Node API for checking, reporting, and updating dependency versions from a project-defined policy. Use it when versions need to be consistent across package manifests, monorepos, local development, or CI jobs.


Main Use Case

Keep important versions intentional

Codependence checks package.json dependencies against a codependencies policy. It can either keep only listed packages current, or pin listed packages while updating everything else.

The difference from {npm,pnpm} update or yarn upgrade is that Codependence gives you an explicit policy surface: these versions matter, these packages may move, and CI should fail when the repo drifts.

The difference from hosted update bots is scope. Dependabot and Renovate are strong choices for scheduled dependency pull requests. Codependence is useful when dependency policy needs to run locally, in a script, in any CI provider, or across multiple manifests without depending on a hosted bot workflow.

*yes, dependencies can be pinned to ~ or ^ versions in package.json files!

Read more about Codependence and why you might want to use it below.


Usage

Codependence can be used as a standalone CLI, in npm scripts or, secondarily, as a Node utility.

Install

npm install codependence --save-dev

Quick setup

Check and update only specific packages:

codependence --codependencies 'react' 'lodash' --update

Or use it with a config in the root package.json file

{ "codependence": { "codependencies": ["react", "lodash"] }, "scripts": { "update-codependencies": "codependence --update", "prepare": "npm run update-codependencies" } }

By default, a codependencies list keeps the 0.x behavior: only those listed dependencies are checked and updated. To pin specific packages while updating everything else, opt into policy/permissive mode:

codependence --permissive --codependencies 'react' 'lodash' --update

Or run a policy check without writing files:

codependence --permissive --codependencies 'react' 'lodash' --dryRun

Initialize Codependence

Quickly set up Codependence in your project with the interactive init command:

Interactive setup with permissive mode by default - recommended!

codependence init

Create .codependencerc with all dependencies pinned (legacy mode)

codependence init rc

Add configuration to package.json with all dependencies pinned (legacy mode)

codependence init package

The init command will:

Testing

Unit Tests:

bun test # Run all unit tests bun test --coverage # Run with coverage report

E2E Tests:

./tests/e2e/test-multilang.sh all # Run all e2e tests (Node.js, Python, Go)


Codependence as a CLI

Codependence is built as a CLI-first policy tool.

It is recommended to install and set up Codependence as a devDependency within your root package.json and use a codependence.codependencies array to define dependencies you need to keep updated or pinned to a specific version.

Furthermore, you can add a codependence.codependencies array to child packages' package.json in your monorepo to ensure specific dependencies are pinned to specific versions within your monorepo packages.

Usage: codependence [command] [options]

Commands: init [type] Initialize codependence configuration Types: rc, package, default

Options: -f, --files [files...] File glob pattern -u, --update Update dependencies based on check -r, --rootDir Root directory to start search -i, --ignore [ignore...] Ignore glob pattern --debug Enable debugging --silent Enable mainly silent logging -v, --verbose Enable verbose logging (shows debug info) -q, --quiet Suppress all output except errors -cds, --codependencies [deps...] Dependencies to check -c, --config Path to a config file -s, --searchPath Path to do a config file search -y, --yarnConfig Enable yarn config support --level Update level: patch, minor, or major (default: major) -m, --mode verbose: only listed packages; precise: all except listed -l, --language Target language (nodejs, go, python) (experimental) -h, --help Show this help message --dryRun Show what would change without modifying files --interactive Choose which packages to update interactively --watch Watch for changes and re-check continuously --noCache Disable version caching for fresh results --format Output format: json, markdown, or table (default: table) --outputFile Write output to file instead of stdout

Codependence in Node

Although Codependence is built primarily as a CLI utility, it can be used as a Node utility.

import { checkFiles, codependence } from "codependence";

const checkForOutdated = async () => { try { await checkFiles({ codependencies: ["fs-extra", "lodash"] }); console.log("All dependencies are up-to-date"); } catch (err) { console.error("Dependencies are out of date:", (err as Error).message); } };

const updateAllExceptSpecific = async () => { await codependence({ codependencies: ["react", "lodash"], permissive: true, update: true, }); };

checkForOutdated();

Configuration Options

Codependence options can be used via CLI options, a config file read from the CLI, or with node by passing them into exported Codependence functions. Read more below!


codependencies: Array<string | Record<string, string>

A required option or *config array! Codependencies are required via being passed in an array as a cli option **or as within a codependence.codependencies array.


*Config Array Detail

The Codependence codependencies array supports latest out-of-the-box.

So having this ["fs-extra", "lodash"] will return the latest versions of the packages within the array. It will also match a specified version, like so [{ "foo": "1.0.0" }] and [{ "foo": "^1.0.0" }] or [{ "foo": "~1.0.0" }]. You can also include a * at the end of a name you would like to match. For example, @foo/* will match all packages with @foo/ in the name and return their latest versions. This will also work with foo-*, etc.

Codependence is built in to give you more capability to control your dependencies!


Using the codependence.codependencies array in Monorepo child packages

You can add a codependence.codependencies array to child packages in your monorepo to ensure specific dependencies are pinned to a specific different versions within your monorepo packages.

For example

You can have a package.json file in a @foo/bar package with following:

{ "name": "@foo/bar", "dependencies": { "fs-extra": "^9.0.0", }, "codependence": { "codependencies": [{ "fs-extra": "^9.0.0" }] } }

And another package.json file in a @foo/baz package with following:

{ "name": "@foo/baz", "dependencies": { "fs-extra": "^11.1.0", }, "codependence": { "codependencies": [{ "fs-extra": "^11.1.0" }] } }

Codependencies will install the right dependency version for each package in your monorepo!

Note: Codependencies can and will still install the expected version defined at the monorepo's root for packages that don't specify differences in their package.json files!


files: Array<string>

An optional array of strings to check for package.json files to update.


update: boolean

An optional boolean which defines whether Codependence should update dependencies in package.json's or not.


rootDir: string

An optional string which can used to specify the root directory to run checks from;


ignore: Array<string>

An optional array of strings used to specify directories to ignore


debug: boolean

An optional boolean value used to enable debugging output


silent: boolean

An optional boolean value used to enable a more silent developer experience


config: string

An optional string containing a package to file which contains codependence config.


searchPath: string

An optional string containing a search path for location config files.

yarnConfig: boolean

An optional boolean value used to enable * yarn config checking


permissive: boolean

Controls whether all dependencies are updated to latest except those listed in codependencies.


level: "patch" | "minor" | "major"

An optional string constraining how far updates are allowed to reach.


mode: "verbose" | "precise"

An optional string controlling which packages are checked.


dryRun: boolean

An optional boolean that previews what would change without modifying any files.


interactive: boolean

An optional boolean that prompts you to select which packages to update when combined with --update.


watch: boolean

An optional boolean that enables continuous checking, re-running every 30 seconds.


noCache: boolean

An optional boolean that bypasses the version cache for fresh registry results.


format: "json" | "markdown" | "table"

An optional string specifying the output format. When set, disables the spinner and outputs structured data instead.


outputFile: string

An optional path to write formatted output to a file instead of stdout. Requires format to be set.


Multi-language support (experimental)

Codependence includes experimental support for Python and Go dependency manifests via the --language flag:

codependence --language python # Check requirements.txt / pyproject.toml codependence --language go # Check go.mod dependencies

This feature is under active development. For stable usage, omit --language (defaults to Node.js).


Recipes

Listed below are some common patterns (recipes) for using Codependence.

Don't want a config? No problem!

Starting out, you may not want a config object. Have no fear, Codependence can be used as a CLI utility ONLY!

codependence --codependencies 'lodash' '{ "fs-extra": "10.0.1" }'

Want to grab all dependencies which match a <name>* (name star) pattern to return the latest version of them? Sure!

codependence --codependencies '@foo/*' --update

Want to update all dependencies to latest except specific ones?

Use permissive mode and list what you want to pin:

codependence --permissive --codependencies 'react' 'lodash' --update


Synopsis

Codependence is a JavaScript utility CLI and Node tool that compares a codependencies policy against package.json dependencies, devDependencies, peerDependencies, and optionalDependencies.

For each dependency included in the codependencies array, Codependence will either a) check that versions are at latest or b) check that a specified version is matched within manifest files. Codependence can either a) return a pass/fail result or b) update dependency versions in manifest file(s).


Codependence is useful for ensuring important dependency versions are intentional: up-to-date where they should move, pinned where they should not, and consistent across a repo or monorepo.

This utility is built to work alongside dependency automation tools like Dependabot and Renovate. Use those tools for hosted dependency PR automation. Use Codependence for local checks, CI gates, scripted updates, and repo-specific version policy.


Policy Surface

Codependence currently focuses on package manifests and dependency sections. The same policy model can expand to other version surfaces over time.

Surface Status Purpose
package.json dependencies Supported Enforce dependency policy in Node.js projects and monorepos
Python and Go manifests Experimental Apply the same check/update workflow outside Node.js
Local repository scans Roadmap Report drift across a directory of projects, such as ~/code
Toolchain files Roadmap Keep .nvmrc, .node-version, .tool-versions, and .mise.toml aligned
Docker and compose files Roadmap Check base image and service image versions
CI workflow YAML Roadmap Check action, image, and runtime versions in pipeline files

*Codependencies are project dependencies which must be up-to-date or set to a specific version!

For example, if your repository requires the latest version and latest can't be specified as the dependency version within your package.json, Codependence will ensure your package.json has the actual latest semver version set in your package.json. It can do the same if an exact version is specified.


Why use Codependence?

Codependence is focused on one job: enforcing dependency version policy where your code actually runs.


Why not use Codependence?

Codependence isn't for everybody or every repository. Here are some reasons why it might not be for you!


Demos

Check out Codependence in Action!


Codependence Debugging

private packages

If there is a .npmrc file, there is no issue with Codependence monitoring private packages. However, if a yarn config is used, Codependence must be instructed to run version checks differently.


Fixes


Development Environment

This project uses:

We use mise to manage tool versions. If you have mise installed, it will automatically use the correct versions of Node.js and bun.

Setup with mise

Install mise if you don't have it

curl https://mise.run | sh

Clone the repository

git clone https://github.com/yowainwright/codependence.git cd codependence

mise will automatically use the correct versions from .mise.toml

mise install

Install dependencies

bun install

Setup without mise

Install Node.js 24

nvm install 24

Install pinned bun

curl -fsSL https://bun.sh/install | bash -s "bun-v1.3.14"

Install dependencies

bun install

Release Strategy

Git tags must match package.json versions. Stable tags like v1.0.0 publish to npm latest. Supported prerelease tags use alpha, beta, or rc, such asv1.0.0-beta.1, and publish to the matching npm dist-tag.

Local release helpers keep the release commit and the publish trigger composable:

bun run release:dry bun run release:alpha:dry bun run release:beta:dry bun run release:rc:dry bun run release bun run release:tag

The release helper creates the release commit locally, pushes only the version tag, and restores local main to its starting commit. The tag triggers the publish workflow, which packs the npm tarball, attests it, publishes it with npm provenance, and uploads the tarball plus attestation to the GitHub release. Use bun run release:tag when package.json already has the version you want to publish.

Publishing follows the same posture as Pastoralist: GitHub Actions publishes through npm Trusted Publishing/OIDC, not a long-lived npm token. Configure thecodependence package on npm with a trusted publisher foryowainwright/codependence, workflow file publish.yml, environmentnpm-publish, and allowed action npm publish. After the trusted publisher is working, npm package settings should require 2FA and disallow token publishing.

Contributing

Contributing is straightforward.

Issues

Pull Requests

Thank you!


Roadmap


Shoutouts

Thanks to Dev Wells and Steve Cox for the aligned code leading to this project. Thanks Navid for some great insights to improve the api!


Made by @yowainwright, MIT 2022-present