{"id":13531753,"url":"https://github.com/purescript/spago","last_synced_at":"2026-02-01T03:03:31.499Z","repository":{"id":37837956,"uuid":"149850277","full_name":"purescript/spago","owner":"purescript","description":"🍝 PureScript package manager and build tool","archived":false,"fork":false,"pushed_at":"2026-01-26T13:34:14.000Z","size":3979,"stargazers_count":821,"open_issues_count":46,"forks_count":133,"subscribers_count":12,"default_branch":"master","last_synced_at":"2026-01-26T22:28:55.639Z","etag":null,"topics":["build-tool","package-manager","package-sets","purescript"],"latest_commit_sha":null,"homepage":"","language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purescript.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-09-22T06:02:07.000Z","updated_at":"2026-01-26T13:44:16.000Z","dependencies_parsed_at":"2023-09-26T21:03:35.591Z","dependency_job_id":"68b4d21e-2f8f-45cc-9e94-2f9f1d247627","html_url":"https://github.com/purescript/spago","commit_stats":{"total_commits":950,"total_committers":106,"mean_commits":8.962264150943396,"dds":0.5052631578947369,"last_synced_commit":"1dba7dc969dd30d8c398f759dd4a9e5eafc3aef5"},"previous_names":["spacchetti/spago"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/purescript/spago","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript%2Fspago","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript%2Fspago/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript%2Fspago/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript%2Fspago/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purescript","download_url":"https://codeload.github.com/purescript/spago/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purescript%2Fspago/sbom","scorecard":{"id":749991,"data":{"date":"2025-08-11","repo":{"name":"github.com/purescript/spago","commit":"4f084378ca6c2e06f988ad0826d2311c4af38ad9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.3,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":5,"reason":"2 commit(s) and 4 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":6,"reason":"Found 17/28 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/nix-flake.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nix-flake.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/nix-flake.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nix-flake.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/nix-flake.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/nix-flake.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/nix-flake.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:127: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:128: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:64: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:98: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:113: update your workflow using https://app.stepsecurity.io/secureworkflow/purescript/spago/release.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/build.yml:60","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   1 out of   2 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 0.21.0 not signed: https://api.github.com/repos/purescript/spago/releases/101907967","Warn: release artifact 0.20.9 not signed: https://api.github.com/repos/purescript/spago/releases/65940278","Warn: release artifact 0.20.8 not signed: https://api.github.com/repos/purescript/spago/releases/65460873","Warn: release artifact 0.20.7 not signed: https://api.github.com/repos/purescript/spago/releases/59407926","Warn: release artifact 0.20.6 not signed: https://api.github.com/repos/purescript/spago/releases/59110888","Warn: release artifact 0.21.0 does not have provenance: https://api.github.com/repos/purescript/spago/releases/101907967","Warn: release artifact 0.20.9 does not have provenance: https://api.github.com/repos/purescript/spago/releases/65940278","Warn: release artifact 0.20.8 does not have provenance: https://api.github.com/repos/purescript/spago/releases/65460873","Warn: release artifact 0.20.7 does not have provenance: https://api.github.com/repos/purescript/spago/releases/59407926","Warn: release artifact 0.20.6 does not have provenance: https://api.github.com/repos/purescript/spago/releases/59110888"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 23 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T20:01:37.685Z","repository_id":37837956,"created_at":"2025-08-22T20:01:37.685Z","updated_at":"2025-08-22T20:01:37.685Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28799824,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-27T01:07:07.743Z","status":"online","status_checked_at":"2026-01-27T02:00:07.755Z","response_time":168,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["build-tool","package-manager","package-sets","purescript"],"created_at":"2024-08-01T07:01:05.359Z","updated_at":"2026-02-01T03:03:31.491Z","avatar_url":"https://github.com/purescript.png","language":"PureScript","readme":"# spago\n\n[![NPM Version](https://img.shields.io/npm/v/spago)](https://www.npmjs.com/package/spago)\n[![License](https://img.shields.io/github/license/purescript/spago)](https://github.com/purescript/spago/blob/master/LICENSE)\n[![build](https://github.com/purescript/spago/actions/workflows/build.yml/badge.svg)](https://github.com/purescript/spago/actions/workflows/build.yml)\n[![nix-flake](https://github.com/purescript/spago/actions/workflows/nix-flake.yml/badge.svg)](https://github.com/purescript/spago/actions/workflows/nix-flake.yml)\n[![Maintainer: f-f](https://img.shields.io/badge/maintainer-f%2d-f-teal.svg)](http://github.com/f-f)\n\n_(IPA: /ˈspaɡo/)_\n\nPureScript package manager and build tool.\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"./logo.png\" height=\"500px\" alt=\"Spago logo - a 3d box containing a blob of spaghetti\"\u003e\n\u003c/p\u003e\n\n## Installation\n\n\u003e [!IMPORTANT]\\\n\u003e This documentation concerns the new PureScript rewrite of Spago. If you are looking for the Haskell codebase (versions up to 0.21.x), please head over to the [spago-legacy] repo.\n\nThe recommended installation method for Windows, Linux and macOS is `npm` (see the latest releases on npm\n[here][spago-npm]):\n\n```\nnpm install -g spago\n```\n\nOther installation methods available:\n\n- With Nix, using [purescript-overlay]\n\n**General notes:**\n\n- The assumption is that you already installed the [PureScript compiler][purescript].\n  If not, get it with `npm install -g purescript`, or the recommended method for your OS.\n\n## Super quick tutorial\n\nLet's set up a new project!\n\n```console\n$ mkdir purescript-pasta\n$ cd purescript-pasta\n$ spago init\n```\n\nThis last command will create a few files:\n\n```\n.\n├── spago.yaml\n├── src\n│   └── Main.purs\n└── test\n    └── Test\n        └── Main.purs\n```\n\nIf you have a look at the `spago.yaml` file, you'll see that it contains two sections:\n\n- [the `workspace` section](#the-workspace), which details the configuration for the _dependencies_ of the project as a whole (which can be a monorepo, and contain more than one package), and other general configuration settings.\n  In this sample project, the only configuration needed is the [package set](#whats-a-package-set) version from which all the dependencies will be chosen. See [here](#querying-package-sets) for more info about how to query the package sets.\n- [the `package` section](#whats-a-package), that is about the configuration of the package at hand, such as its name, dependencies, and so on.\n\nFor more info about all the various configuration settings, visit the section about [the configuration format](#the-configuration-file).\n\nTo build and run your project, use:\n\n```console\n$ spago run\n```\n\nThis will:\n\n- download and compile the necessary dependencies (equivalent to `spago install`)\n- compile this sample project in the `output/` directory (equivalent to `spago build`).\\\n  You can take a look at the content of `output/Main/index.js` to see what kind of JavaScript has been generated from your new `Main.purs` file\n- run the generated JS, which is roughly equivalent to running\n  ```console\n  $ node -e \"import('./output/Main/index').then(m =\u003e m.main())\"\n  ```\n  The above code imports the JS file you just looked at, and runs its `main` with Node.\n\nYou can also bundle the project in a single file with an entry point, so it can be run directly (useful for CLI apps):\n\n```console\n$ spago bundle --bundle-type app --platform node\n$ node .\n```\n\nGreat! If you read unitl here you should be set to go write some PureScript without worrying too much about the build 😊\n\nWhere to go from here? There are a few places you should check out:\n\n- see [the \"How to achieve X\"](#how-do-i) section for practical advice without too much explanation\n- see instead the [Concepts and Explanations](#concepts-and-explanations) section for more in-depth explanations about the concepts that power Spago, such as [package sets](#whats-a-package-set), or [the Workspace](#the-workspace).\n\n## Table of contents\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n\n- [Design goals and reasons](#design-goals-and-reasons)\n- [Developing and contributing](#developing-and-contributing)\n- [How do I...](#how-do-i)\n  - [Migrate from `spago.dhall` to `spago.yaml`](#migrate-from-spagodhall-to-spagoyaml)\n  - [Migrate from `bower`](#migrate-from-bower)\n  - [See what commands and flags are supported](#see-what-commands-and-flags-are-supported)\n  - [Setup a new project using a specific package set](#setup-a-new-project-using-a-specific-package-set)\n  - [Setup a new project using the solver](#setup-a-new-project-using-the-solver)\n  - [Install a direct dependency](#install-a-direct-dependency)\n  - [Download my dependencies locally](#download-my-dependencies-locally)\n  - [Build and run my project](#build-and-run-my-project)\n  - [Test my project](#test-my-project)\n  - [Run a repl](#run-a-repl)\n  - [Run a standalone PureScript file as a script](#run-a-standalone-purescript-file-as-a-script)\n  - [List available packages](#list-available-packages)\n  - [Install all the packages in the set](#install-all-the-packages-in-the-set)\n  - [Override a package in the package set with a local one](#override-a-package-in-the-package-set-with-a-local-one)\n  - [Override a package in the package set with a remote one](#override-a-package-in-the-package-set-with-a-remote-one)\n  - [Add a package to the package set](#add-a-package-to-the-package-set)\n  - [Querying package sets](#querying-package-sets)\n  - [Upgrading packages and the package set](#upgrading-packages-and-the-package-set)\n  - [Custom package sets](#custom-package-sets)\n  - [Graph the project modules and dependencies](#graph-the-project-modules-and-dependencies)\n  - [Monorepo support](#monorepo-support)\n  - [Polyrepo support](#polyrepo-support)\n  - [Test dependencies](#test-dependencies)\n  - [Bundle a project into a single JS file](#bundle-a-project-into-a-single-js-file)\n  - [Enable source maps](#enable-source-maps)\n    - [Node](#node)\n    - [Browsers](#browsers)\n  - [Skipping the \"build\" step](#skipping-the-build-step)\n  - [Generated build info/metadata](#generated-build-infometadata)\n  - [Generate documentation for my project](#generate-documentation-for-my-project)\n  - [Alternate backends](#alternate-backends)\n  - [Publish my library](#publish-my-library)\n    - [Publish many packages together](#publish-many-packages-together)\n  - [Authenticated commands](#authenticated-commands)\n    - [Transfer my package to a new owner](#transfer-my-package-to-a-new-owner)\n  - [Know which `purs` commands are run under the hood](#know-which-purs-commands-are-run-under-the-hood)\n  - [Force a registry refresh](#force-a-registry-refresh)\n  - [Install autocompletions for `bash`](#install-autocompletions-for-bash)\n  - [Install autocompletions for `zsh`](#install-autocompletions-for-zsh)\n- [Concepts and explanations](#concepts-and-explanations)\n  - [What's a \"package\"?](#whats-a-package)\n  - [What's a \"package set\"?](#whats-a-package-set)\n  - [The workspace](#the-workspace)\n  - [The configuration file](#the-configuration-file)\n  - [The lock file](#the-lock-file)\n  - [File System Paths used in Spago](#file-system-paths-used-in-spago)\n- [FAQ](#faq)\n  - [Why can't `spago` also install my npm dependencies?](#why-cant-spago-also-install-my-npm-dependencies)\n  - [Differences from legacy spago](#differences-from-legacy-spago)\n    - [Watch mode](#watch-mode)\n    - [`sources` in the configuration file](#sources-in-the-configuration-file)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Design goals and reasons\n\nOur main design goals are:\n\n- **Great UX**: a good build system just does what's most expected and gets out of the way so you can focus on actually thinking about the software itself, instead of spending your time configuring the build.\n- **Minimal dependencies**: users should not be expected to install a myriad of tools on their system to support various workflows. Spago only expects `git` and `purs` to be installed.\n- **Reproducible builds**: we exploit [package sets](#whats-a-package-set) and [lock files](#the-lock-file) to make your build reproducible, so that if your project builds today it will also build tomorrow and every day after that.\n\nSome tools that inspired `spago` are: [Rust's Cargo][cargo], [Haskell's Stack][stack],\n[`psc-package`][psc-package], [`pulp`][pulp] and [`bazel`][bazel].\n\n## Developing and contributing\n\nWe'd love your help, and welcome PRs and contributions!\n\nSome ideas for getting started:\n\n- [Build and run `spago`](CONTRIBUTING.md#developing-spago)\n- [Help us fix bugs and build features](https://github.com/purescript/spago/issues?utf8=%E2%9C%93\u0026q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+label%3A%22defect%22)\n- Help us improve our documentation\n- Help us [log bugs and open issues][new-issue]\n\nFor more details see the [`CONTRIBUTING.md`][contributing]\n\n## How do I...\n\nThis section contains a collection of mini-recipes you might want to follow in order to get things done with Spago.\n\n### Migrate from `spago.dhall` to `spago.yaml`\n\nYou'll need to use [spago-legacy] for this.\n\n```bash\n# Install spago-legacy\nnpm install -g spago-legacy\n# You can then create a `spago.yaml` file with `migrate`\nspago-legacy migrate\n\n# Ready to remove the dhall files and move to the new spago\nnpm install -g spago\nrm spago.dhall packages.dhall\n```\n\n\u003e [!NOTE]\\\n\u003e The `spago-legacy` NPM package has exactly the same content as the `spago@0.21.0` release, which is the last one released from the legacy codebase, and the only release to contain the `migrate` command. The new codebase's releases start from `spago@0.93.0`.\n\nSome packages might not be found or have the wrong version, in which case\nyou'll have to carefully:\n\n- try to run `spago install some-package` for packages found in the package set (see [how to query the set](#querying-package-sets))\n- [add the packages that are missing from the set](#add-a-package-to-the-package-set)\n\nIn **all** cases, you'll want to switch to the new Registry package sets, so replace something like this:\n\n```yaml\nworkspace:\n  packageSet:\n    url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.10-20230919/packages.json\n```\n\n...with this:\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n```\n\nThis is because the legacy package set format - while being supported - is pointing at git repositories, so Spago will fetch them using git, which can get quite slow and error-prone.\n\nThe new package sets are instead pointing at the Registry, and can fetch compressed archives from our CDN, which is much faster and more reliable.\n\nTo figure out what package set you're supposed to be using, see the section about [querying package sets](#querying-package-sets).\n\nYou might also want to check out the section about [differences from legacy spago](#differences-from-legacy-spago).\n\n### Migrate from `bower`\n\nSame as above, but with an additional `spago init` command just after you install [spago-legacy], so that the `bower.json` file is converted into a `spago.dhall` file.\n\n### See what commands and flags are supported\n\nFor an overview of the available commands, run:\n\n```console\n$ spago --help\n```\n\nYou will see several subcommands (e.g. `build`, `test`); you can ask for help\nabout them by invoking the command with `--help`, e.g.:\n\n```console\n$ spago build --help\n```\n\nThis will give a detailed view of the command, and list any flags you can use with that command.\n\n### Setup a new project using a specific package set\n\nSince `spago init` does not necessarily use the latest package set. Fortunately, you can specify which package set to use via the `--package-set` flag:\n\n```console\n$ spago init --package-set 41.2.0\n```\n\nSee [here](#querying-package-sets) for how to ask Spago which sets are available for use.\n\n### Setup a new project using the solver\n\nPackage sets are the default experience to ensure that you always get a buildable project out of the box, but one does not necessarily have to use them.\n\nIf you'd like to set up a project that uses the Registry solver to figure out a build plan, you can use:\n\n```console\n$ spago init --use-solver\n```\n\nWhen using the solver (and when [publishing a package](#publish-my-library)), it's important to specify the version bounds for your dependencies, so that the solver can figure out a build plan.\n\nYou can ask Spago to come up with a good set of bounds for you by running:\n\n```console\n$ spago install --ensure-ranges\n```\n\nYou can specify your version ranges manually in the `spago.yaml` configuration file too:\n\n```yaml\npackage:\n  dependencies:\n    - lists: \"\u003e=7.0.0 \u003c8.0.0\"\n```\n\n### Install a direct dependency\n\nTo add a dependency to your project you can run:\n\n```console\n# E.g. installing Halogen\n$ spago install halogen\n\n# This also supports multiple packages\n$ spago install foreign aff\n```\n\nIf you are using the Registry solver then the package must be available in the Registry, while if you\nare using package sets it needs to be contained in the set. See [here](#add-a-package-to-the-package-set) to know more about adding more packages to the local set.\n\n### Download my dependencies locally\n\n```console\n$ spago install\n```\n\nThis will download and compile all the transitive dependencies of your project (i.e. the direct dependencies,\ni.e. the ones listed in the `dependencies` key of `spago.yaml`, plus all their dependencies,\nrecursively) to the local `.spago` folder.\n\nHowever, running this directly is usually **not necessary**, as all commands that need the dependencies\nto be installed will run this for you.\n\nRunning `spago fetch` is equivalent, but skips the compilation step.\n\n### Build and run my project\n\nYou can build the project and its dependencies by running:\n\n```console\n$ spago build\n```\n\nThis is mostly just a thin layer above the PureScript compiler command `purs compile`.\n\n_Note_: by default the `build` command will try to install any dependencies that haven't been\nfetched yet - if you wish to disable this behaviour, you can pass the `--no-install` flag.\n\nThe build will produce very many JavaScript files in the `output/` folder. These\nare ES modules, and you can just `import` them e.g. on Node.\n\n\u003e [!NOTE]\\\n\u003e The wrapper on the compiler is so thin that you can pass options to `purs`.\n\u003e E.g. if you wish to ask `purs` to emit errors in JSON format, you can run\n\u003e\n\u003e ```console\n\u003e $ spago build --purs-args \"--json-errors\"\n\u003e ```\n\u003e\n\u003e However, some `purs` flags are covered by Spago ones, e.g. to change the location of the `output` folder:\n\u003e\n\u003e ```console\n\u003e $ spago build --output myOutput\n\u003e ```\n\nIf you want to run the program, just use `run`:\n\n```console\n$ spago run -p package-name -m Module.Containing.Main\n\n# We can pass arguments through to `purs compile`\n$ spago run -p package-name  -m Module.Containing.Main --purs-args \"--verbose-errors\"\n\n# We can pass arguments through to the program being run\n$ spago run -p package-name  -m Module.Containing.Main -- arg1 arg2\n```\n\nOof! That's a lot of typing. Fortunately it's possible to configure most of these parameters in the `package.run` section of your configuration file, so you don't have to supply them at the command line.\n\nSee [here](#the-configuration-file) for more info about this, but it allows us to instead write:\n\n```console\n# The main module can be defined in the configuration file, but\n# purs flags still need to be supplied at the command line\nspago run -p package-name --purs-args \"--verbose-errors\"\n\n# It's possible to even pass arguments from the config, which would look like this:\n#\n# package:\n#   run:\n#       main: Main\n#       execArgs:\n#         - \"arg1\"\n#         - \"arg2\"\n$ spago run -p package-name\n```\n\nLastly, if you only have a single package defined in the workspace with these parameters defined in the config file, you can just run\n\n```console\nspago run\n```\n\n### Test my project\n\nYou can also test your project with `spago`:\n\n```console\n# Test.Main is the default here, but you can override it as usual\n$ spago test --main Test.Main\nBuild succeeded.\nYou should add some tests.\nTests succeeded.\n```\n\nIf you are using [the `spec-node` test runner](https://purescript-spec.github.io/purescript-spec/running/#running-under-node),\nyou can use its command-line options to select a subset of tests with\n`--example` or rerun previously failed tests with `--only-failures`:\n\n```console\n$ spago test -- --example \"some test\"\n$ spago test -- --only-failures\n```\n\nNote that you have to separate test runner options with a double dash `--` to distinguish them from Spago's own options.\nIf you're on PowerShell (Windows), you will also need to quote the double dash:\n\n```console\n\u003e spago test '--' --example \"some test\"\n\u003e spago test '--' --only-failures\n```\n\nThis has to do with an unfortunate interaction between Node bootstrapping mechanism and the way PowerShell handles parameters.\n\nSee [the docs](https://purescript-spec.github.io/purescript-spec/running/#running-under-node)\nfor more useful options.\n\nAs with the `run` command, it's possible to configure the tests using the `spago.yaml` - most importantly to separate test dependencies from the dependencies of your application/library.\n\nPlease see [the section about the configuration format](#the-configuration-file) for more info, but in the meantime note that it's possible to install test dependencies by running:\n\n```console\n$ spago install --test-deps spec spec-node\n```\n\n### Run a repl\n\nYou can start a repl with the following command:\n\n```console\n$ spago repl\n```\n\n### Run a standalone PureScript file as a script\n\nYou can run a standalone PureScript file as a script via `spago script`.\nNote: The module name must be `Main`, and it must export a function `main :: Effect Unit`.\n\nBy default, the following dependencies are installed: `effect`, `console`, `prelude`.\n\nYou can run a script via the following, optionally specifying a package set to use, and additional dependencies to pull from there:\n\n```console\n$ spago script --package-set 41.2.0 -d node-fs path/to/script.purs\n```\n\n### List available packages\n\nIt is sometimes useful to know which packages are contained in our package set\n(e.g. to see which version we're using, or to search for packages).\n\nYou can get a complete list of the packages provided by your `workspace` (together with their versions, locations, and license) by running:\n\n```console\n$ spago ls packages\n```\n\nBy using the `ls deps` command instead you can restrict the list to direct or transitive dependencies:\n\n```console\n# Direct dependencies, i.e. only the ones listed in spago.dhall\n$ spago ls deps\n\n# Transitive dependencies, i.e. all the dependencies of your dependencies\n$ spago ls deps --transitive\n```\n\nYou can provide the `--json` flag for a more machine-friendly output.\n\n### Install all the packages in the set\n\nThere might be cases where you'd like your project to depend on all the packages\nthat are contained in the package set (this is sometimes called\n[\"acme build\"][acme]).\n\nIf you have [`jq`][jq] installed, you can accomplish this in relatively few characters:\n\n```console\n$ spago ls packages --json | jq -r 'keys[]' | xargs spago install\n```\n\n### Override a package in the package set with a local one\n\nLet's say I'm a user of the popular `aff` package. Now, let's say I stumble upon a bug\nin there, but thankfully I figure how to fix it. So I clone it locally and add my fix.\n\nNow if I want to test this version in my current project, how can I tell `spago` to do it?\n\nThere's a section of the `spago.yaml` file just for that, called `extraPackages`.\n\nIn this case we override the package with its local copy, which should have a `spago.yaml` - our `workspace` will look something like this:\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    aff:\n      path: ../my-purescript-aff\n```\n\nNow if we run `spago ls packages`, we'll see that it is now included as a local package:\n\n```console\n$ spago ls packages\n+----------------------------------+------------------------------------------+------------------------------------------------+\n| Package                          | Version                                  | Location                                       |\n+----------------------------------+------------------------------------------+------------------------------------------------+\n| abc-parser                       | 2.0.0                                    | -                                              |\n| ace                              | 9.1.0                                    | -                                              |\n| aff                              | local                                    | ../my-purescript-aff                           |\n| aff-bus                          | 6.0.0                                    | -                                              |\n| aff-coroutines                   | 9.0.0                                    | -                                              |\n| aff-promise                      | 4.0.0                                    | -                                              |\n...\n```\n\n### Override a package in the package set with a remote one\n\nLet's now say that we test that our fix from above works, and we are ready to Pull Request the fix.\n\nSo we push our fork and open the PR, but we want to already use the fix in our build, while we wait for it to land upstream and then on the next package set.\n\nIn this case, we can just change the override to point to some commit of our fork, like this:\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    aff:\n      git: https://github.com/my-user/purescript-aff.git\n      ref: aaa0aca7a77af368caa221a2a06d6be2079d32da\n```\n\n\u003e [!WARNING]\\\n\u003e You can use a \"branch\", a \"tag\" or a \"commit hash\" as a `version`.\n\u003e It's **strongly** recommended to avoid using branches, because if you push new commits to a branch, `spago` won't pick them up unless you delete the `.spago/packages/aff/your-branch` folder.\n\n### Add a package to the package set\n\n\u003e [!IMPORTANT]\\\n\u003e You still need to `spago install my-new-package` after adding it to the package set, or Spago will not know that you want to use it as a dependency!\n\nIf a package is not in the upstream package set you can make it available in your build by adding it to `extraPackages`.\n\nThere are a few possible scenarios - the most straightforward is when a package is already in the registry, then you just need to specify its version:\n\n```\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    some-package-from-the-registry: 4.0.0\n```\n\nAnother possibility is that the package is not in the registry (maybe it's your own fork?), but it's a git repo somewhere - e.g. if we'd like to add the `facebook` package:\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    facebook:\n      git: https://github.com/Unisay/purescript-facebook.git\n      ref: v0.3.0 # branch, tag, or commit hash\n```\n\n\u003e [!NOTE]\\\n\u003e If the upstream library that you are adding has a `spago.yaml` file, then Spago will just pick up the dependencies from there.\n\u003e If that's not the case, then you'll have the provide the dependencies yourself, adding a `dependencies` field.\n\nThe last possible case is the one picking up a local folder as a package (note: you'll need a `spago.yaml` file in there):\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    facebook:\n      path: ../my-purescript-facebook\n```\n\n### Querying package sets\n\nSince the versioning scheme for package sets does not tell anything about the compiler version or when they were published, you might want\nto have a look at the list of all the available ones. You can do that with:\n\n```console\n$ spago registry package-sets\n```\n\nThis will print a list of all the package sets ever releases, which could be overwhelming, as you'd likely only be interested in the latest one.\n\nThis is how you would ask for the latest package sets for each compiler version:\n\n```console\n$ spago registry package-sets --latest\n+---------+------------+----------+\n| VERSION | DATE       | COMPILER |\n+---------+------------+----------+\n| 10.0.0  | 2023-01-05 | 0.15.4   |\n| 20.0.3  | 2023-04-08 | 0.15.7   |\n| 27.2.0  | 2023-06-17 | 0.15.8   |\n| 29.1.0  | 2023-07-18 | 0.15.9   |\n| 42.1.0  | 2023-09-26 | 0.15.10  |\n+---------+------------+----------+\n```\n\n### Upgrading packages and the package set\n\nIf your project is using the Registry solver (i.e. no package set and only version bounds), then running `spago upgrade`\nwill try to put together a new build plan with the latest package versions published on the Registry, given that they are still compatible with your current compiler.\n\nIf instead you are using package sets, then `spago upgrade` will bump your package set version to the latest package set available for your compiler version.\n\nYou can pass the `--package-set` flag if you'd rather upgrade to a specific package set version.\nYou can of course just edit the `workspace.packageSet` field in the `spago.yaml` file.\n\n### Custom package sets\n\nSpago supports fetching custom package sets from URLs and paths, so you can build your own package set if you'd like - this is useful for example if you want to put together a custom package set for your company, or if you are using an [alternate backend](#alternate-backends).\n\nSpago will be happy to use a package set from a local path:\n\n```yaml\nworkspace:\n  packageSet:\n    path: ../my-custom-package-set.json\n```\n\nOtherwise you can point Spago to any URL on the internet:\n\n```yaml\nworkspace:\n  packageSet:\n    url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230207/packages.json\n```\n\n...and it will try to fetch the content, parse it as JSON and conform it to one of the possible package set schemas.\n\nThe first one is what Spago calls a `RemotePackageSet`, which contains some metadata, and a map of packages in the shapes (2), (3) and (4) described for `extraPackages` in the [configuration format section](#the-configuration-file).\n\nThis package set could look something like this:\n\n```js\n{\n  \"compiler\": \"0.15.10\",\n  \"version\": \"0.0.1\",\n  \"packages\": {\n    \"some-registry-package\": \"1.0.2\",\n    \"some-package-from-git-with-a-spago-yaml\": {\n      \"git\": \"https://github.com/purescript/registry-dev.git\",\n      \"ref\": \"68dddd9351f256980454bc2c1d0aea20e4d53fa9\"\n    },\n    \"legacy-package-style\": {\n      \"repo\": \"https://github.com/purescript/purescript-prelude.git\",\n      \"version\": \"v6.0.1\",\n      \"dependencies\": [\"prelude\", \"effect\", \"console\"]\n    }\n  }\n}\n```\n\nThe second format possible is what Spago calls a `LegacyPackageSet`, and it's simply a map from package names to the location of the package, described as the (4) option for how to specify `extraPackages` in the [configuration format section](#the-configuration-file).\n\nSomething like this:\n\n```js\n{\n  \"legacy-package-style\": {\n    \"repo\": \"https://github.com/purescript/purescript-prelude.git\",\n    \"version\": \"v6.0.1\",\n    \"dependencies\": [\"prelude\", \"effect\", \"console\"]\n  },\n  \"metadata\": {\n    \"repo\": \"https://github.com/purescript/metadata.git\",\n    \"version\": \"v0.15.10\",\n    \"dependencies\": []\n  }\n}\n```\n\nThis is supported to allow for just using legacy package sets, and be able to automatically migrate `spago.dhall` files to `spago.yaml` files.\n\nIt is not recommended to craft your own package set in the legacy format - please use the `RemotePackageSet` format instead - but if you do just be aware that you'll need to include a package called `metadata` that has a version that matches the compiler version that the set is supposed to support.\n\n### Graph the project modules and dependencies\n\nYou can use the `graph` command to generate a graph of the modules and their dependencies:\n\n```console\n$ spago graph modules\n```\n\nThe same goes for packages:\n\n```console\n$ spago graph packages\n```\n\nThe command accepts the `--json` and `--dot` flags to output the graph in JSON or DOT format respectively.\n\nThis means that you can pipe the output to other tools, such as [`graphviz`][graphviz] to generate a visual representation of the graph:\n\n```console\n$ spago graph packages --dot | dot -Tpng \u003e graph.png\n```\n\n...which will generate something like this:\n\n![packages-graph](./test-fixtures/graph.png)\n\nFinally, the `graph` command is also able to return a topological sorting of the modules or packages, with the `--topo` flag:\n\n```console\n$ spago graph modules --topo\n```\n\n### Monorepo support\n\nSpago supports [\"monorepos\"][luu-monorepo] (see [here][monorepo-tools] as well for more monorepo goodness), allowing you to split a pile of code\ninto different \"compilation units\" that might have different dependencies, deliverables, etc, but still compile together.\n\nThe vast majority of Spago projects will contain only one package, defined in the `package` section of the same `spago.yaml` that contains its `workspace`.\nIt is however possible to define multiple packages in the same repository!\n\nThe basic rules are:\n\n- [a package](#whats-a-package) is defined by a `spago.yaml` file containing a `package` section.\n- there can be only one `workspace` section in the whole repository, which defines the \"root\" of the current [Spago Workspace](#the-workspace). This defines your package set/build plan.\n- Spago will autodetect all the packages inside the workspace\n- ...except for `spago.yaml` files with a `workspace` section, which will be ignored (together with their subfolders, as they establish a the boundary of another \"workspace\")\n\nFor more info about the concept of Spago Workspaces, see [the dedicated section](#the-workspace).\n\nSince this might sound a little abstract, let's try to picture the case where you might want to have the packages `lib1`, `lib2` and `app1`.\n\nThen your file tree might look like this:\n\n```\n.\n├── app1\n│   ├── spago.yaml\n│   ├── src\n│   │   └── Main.purs\n│   └── test\n│       └── Test\n│           └── Main.purs\n├── lib1\n│   ├── spago.yaml\n│   └── src\n│       └── Main.purs\n├── lib2\n│   ├── spago.yaml\n│   ├── src\n│   │   └── Main.purs\n│   └── test\n│       └── Test\n│           └── Main.purs\n└── spago.yaml\n```\n\nWhere:\n\n- the top level `spago.yaml` could look like this:\n\n  ```yaml\n  workspace:\n    packageSet:\n      registry: 41.2.0\n  ```\n\n- and the `lib1/spago.yaml` would look something like this:\n\n  ```yaml\n  package:\n    name: lib1\n    dependencies:\n      - effect\n      - console\n      - prelude\n  ```\n\n- then, assuming `lib2` depends on `lib1`, `lib2/spago.yaml` might look like this:\n\n  ```yaml\n  package:\n    name: lib2\n    dependencies:\n      - effect\n      - console\n      - prelude\n      - lib1 # \u003c------ Note the dependency here\n    test:\n      main: Test.Lib2.Main\n      dependencies:\n        - spec\n  ```\n\n- and then `app1/spago.yaml` would look something like this:\n\n  ```yaml\n  package:\n    name: app1\n    # Note that the app does not include all the dependencies that the lib included\n    dependencies:\n      - prelude\n      - aff # This dep was not used by the library\n      - lib2 # And we have `lib2` as a dependency\n  ```\n\nGiven this setup, Spago will figure out that there are three separate packages in the repository.\n\nYou can _select_ a package to perform operations on it by using the `--package` flag, e.g. the follow will install the `maybe` package in the `lib1/spago.yaml`:\n\n```console\nspago install -p lib1 maybe\n```\n\nThe `--package` flag is also available for many more commands, such as `build`, `run`, `test`, `bundle` and so on.\n\nAn important property of this \"monorepo setup\" is that the `output` folder will be shared between all the packages: they will share the same build package set (or build plan when using the solver) and they will be all build together.\n\n\u003e [!NOTE]\\\n\u003e Remember that you can't have multiple modules with the same name in a single project. This usually happens with the `Main` module being defined multiple times. Rename these modules to something unique.\n\n### Polyrepo support\n\nThere might be cases where you want to have multiple loosely-connected codebases in the same repository that do _not_ necessarily build together all the time. This is sometimes called [a \"polyrepo\"][monorepo-tools].\n\nOne such example of this could be a project that has a frontend and a backend, and they are both written in PureScript, but run on different backends: the frontend runs in the browser (so in JavaScript), and the backend runs on Erlang.\n\nLet's say you might also want to share some code between the two (that was the point of using the same language, no?), so you might have a `common` package that is used by both.\n\nYou can achieve all of this with Spago, by having multiple workspaces - let's try to visualise this.\n\nThe file tree might look like this:\n\n```\n.\n├── client\n│   ├── spago.yaml\n│   ├── src\n│   │   └── Main.purs\n│   └── test\n│       └── Test\n│           └── Main.purs\n├── common\n│   ├── spago.yaml\n│   ├── src\n│   │   └── Main.purs\n│   └── test\n│       └── Test\n│           └── Main.purs\n└── server\n    ├── spago.yaml\n    ├── src\n    │   └── Main.purs\n    └── test\n        └── Test\n            └── Main.purs\n```\n\nWhere the `common/spago.yaml` is just a package with no workspace defined, as it's going to support both the JS and the Erlang backend:\n\n```yaml\npackage:\n  name: common\n  dependencies:\n    - effect\n    - console\n    - prelude\n```\n\nThen the `client/spago.yaml` might look like this:\n\n```yaml\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    common:\n      path: ../common\npackage:\n  name: client\n  dependencies:\n    - prelude\n    - common\n    - halogen\n```\n\nAnd the `server/spago.yaml` might look like this:\n\n```yaml\nworkspace:\n  packageSet:\n    url: https://raw.githubusercontent.com/purerl/package-sets/erl-0.15.3-20220629/packages.json\n  backend:\n    cmd: purerl\n  extraPackages:\n    common:\n      path: ../common\npackage:\n  name: server\n  dependencies:\n    - prelude\n    - common\n    - erl-process\n```\n\nThis all means that:\n\n- there is a [Spago Workspace](#the-workspace) in the `client` folder, another one in the `server` folder, but none in the `common` folder\n- the `common` package is shared between the two workspaces, note that it's included as a local package in both\n- the `client` workspace uses the default JS package set, and the `server` workspace uses a Purerl package set\n- to use each workspace you would need to `cd` into its folder, so that Spago can detect the workspace\n\n### Test dependencies\n\nLike this:\n\n```yaml\npackage:\n  name: mypackage\n  dependencies:\n    - effect\n    - console\n    - prelude\n  test:\n    main: Test.Main\n    dependencies:\n      - spec\n```\n\nYou can add more with `spago install --test-deps some-new-package`.\n\n### Bundle a project into a single JS file\n\nUse `spago bundle`.\n\nThis is a good-defaults wrapper into `esbuild`, and it's meant to be used for bundling small projects. Once your project grows in size, you might want to look into configuring `esbuild` (or `parcel`, or `webpack`) directly.\n\nSee the [`esbuild` getting started][install-esbuild] for installation instructions.\n\nThis command supports a few options, and the most important ones are:\n\n- the `--bundle-type` flag, which can be either `app` or `module`\n- the `--platform` flag, which can be either `browser` or `node`\n\nSee the help message for more flags, and [the configuration format section](#the-configuration-file) for how to configure these options in the `spago.yaml` file.\n\nWhen bundling an `app`, the output will be a single executable file:\n\n```console\n$ spago bundle --outfile index.js --bundle-type app --platform node\n\n# It is then possible to run it with node:\n$ node index.js\n```\n\n\u003e [!NOTE]\\\n\u003e Spago will bundle your project in the [esbuild bundle format](https://esbuild.github.io/api/#format) [IIFE](https://esbuild.github.io/api/#format-iife).\n\nWhen bundling a `module` instead, the output will be a single JS module that you can `import` from JavaScript:\n\n```console\n# You can specify the main module and the target file, or these defaults will be used\n$ spago bundle --bundle-type module --module Main --outfile index.js\n```\n\nCan now import it in your Node project:\n\n```console\n$ node -e \"import('./index.js').then(m =\u003e console.log(m.main))\"\n[Function]\n```\n\nSpago does not wrap the entirety of the bundler's API (esbuild for JS builds), so it's possible to pass arguments through to it. E.g. to exclude an NPM package from the bundle you can pass the `--external` flag to esbuild:\n- either through the command line, with the `--bundler-args` flag, i.e. `--bundler-args \"--external:better-sqlite3\"`.\n- or by adding it to the configuration file:\n  ```yaml\n  package:\n    bundle:\n      extra_args:\n        - \"--external:better-sqlite3\"\n### Enable source maps\n\nWhen bundling, you can include `--source-maps` to generate a final source map for your bundle.\n\nExample:\n\n```console\nspago bundle -p my-project --source-maps --minify --outfile=bundle.js\n```\n\nwill generate a minified bundle: `bundle.js`, and a source map: `bundle.js.map`.\n\n#### Node\n\nIf your target platform is node, then you need to ensure your node version is \u003e= 12.2.0 and [enable source maps](https://nodejs.org/dist/latest-v20.x/docs/api/cli.html#--enable-source-maps) when executing your script:\n\n```console\nspago bundle -p my-project --platform node --source-maps --minify --outfile=bundle.js\nnode --enable-source-maps bundle.js\n```\n\n#### Browsers\n\nIf you are targeting browsers, then you will need to ensure your server is configured to serve the source map from the same directory as your bundle.\n\nSo for example if your server is configured to serve files from `public/`, you might run:\n\n```console\nspago bundle -p my-project --platform browser --source-maps --minify --outfile=public/bundle.js\n```\n\n### Skipping the \"build\" step\n\nWhen running `spago bundle`, Spago will first try to `build` your project, since bundling requires the project to be compiled first.\n\nIf you already compiled your project and want to skip this step you can pass the `--no-build` flag.\n\n### Generated build info/metadata\n\nSpago will include some metadata in the build, such as the version of the compiler used, the version of Spago, and the versions of the package itself.\n\nThis is so that you can access all these things from your application, e.g. to power a `--version` command in your CLI app.\n\nThis info will be available in the `Spago.Generated.BuildInfo` module, which you can import in your project.\n\nThe file itself is stored in the `.spago` folder if you'd like to have a look at it.\n\n### Generate documentation for my project\n\nTo build documentation for your project and its dependencies (i.e. a \"project-local\n[Pursuit][pursuit]\"), you can use the `docs` command:\n\n```console\n$ spago docs\n```\n\nThis will generate all the documentation in the `./generated-docs` folder of your project.\nYou might then want to open the `index.html` file in there.\n\nIf you wish for the documentation to be opened in browser when generated, you can pass an `open` flag:\n\n```console\n$ spago docs --open\n```\n\nYou can customize the output to other formats beyond html. Supported formats include ctags, etags, and markdown.\nFor example to generate ctags for use in your editor:\n\n```console\n$ spago docs --format ctags\n```\n\nSometimes you'd like to pull up docs for dependencies even when you have compilation errors in your project. This is a good use case for the --deps-only flag:\n\n```console\n$ spago docs --deps-only`\n```\n\n### Alternate backends\n\nSpago supports compiling with alternate purescript backends, such as [purerl].\n\nTo use an alternate backend, include the `workspace.backend` section in your workspace's `spago.yaml`. See the [configuration format section](#the-configuration-file) for more info.\n\n### Publish my library\n\nTo publish your library to the [PureScript Registry][registry], you can run:\n\n```console\n$ spago publish\n```\n\n...and follow the instructions 🙂\n\n#### Publish many packages together\n\nLibrary authors will often build \"ecosystems\" of small interdependent packages that build on each other - if that's your situation, and you'd like to publish them all together (following some big refactoring, as it goes!), then you might wonder how to include the new version in the build plan of the next package to publish.\n\nIf you're using the registry solver then this is not an issue, but if your project is based on a package set, then that will not contain your newly published package, since well, you just published it!\n\nYou should be able to add the newly released version to your build plan by adding it to the `extraPackages` section ([see here](https://github.com/purescript/spago/issues/1215)):\n```yaml\npackage:\n  name: next-library-to-publish\n  dependencies:\n    - newly-published-library: \"\u003e=0.0.1 \u003c0.2.0\"\n\nworkspace:\n  packageSet:\n    registry: 41.2.0\n  extraPackages:\n    newly-published-library: 0.1.0\n```\n\u003e [!NOTE]\\\n\u003e This only works when the package you add to `extraPackages` has been published to the registry. Adding a git dependency will produce an error, as publishing to the Registry only admits build plans that only contain packages coming from the Registry.\n\n### Authenticated commands\n\nThe Registry does not need authentication when publishing new versions of a package, but it does need it when issuing\noperations that modify existing packages, [such as location transfer or unpublishing](registry-dev-auth).\n\nThis authentication happens through SSH keys: by having your public key in a published version, the Registry can then\nauthenticate requests that are signed with your private key.\n\nAuthentication and operations that use it are automated by Spago, through the `spago auth` command: if you'd like to\nbe able to perform authenticated operations you need a SSH keypair, and run `spago auth` passing those keys in.\nThis will populate the `package.publish.owners` field in the `spago.yaml` - commit that and publish a new version,\nand from that moment you'll be able to perform authenticated operations on this package.\n\n#### Transfer my package to a new owner\n\nIf you are the owner of a package and you want to transfer it to another user, you'd need to inform the Registry\nabout the new location of the repository, so that the new owner will be able to publish new versions of the package.\n\nThe transfer procedure is automated by Spago commands, and goes as follows:\n* Add your (or the new owner's) SSH public key to the `spago.yaml` through `spago auth` if they are not there already (see previous section)\n* Transfer the repository to the new owner using the hosting platform's transfer mechanism (e.g. GitHub's transfer feature)\n* Depending on whose key is present in the `owners` field, either you or the new owner will update the `publish.location` field in the `spago.yaml`, and call `spago registry transfer` to initiate the transfer. If all goes well you'll now be able to publish a new version from the new location.\n\n### Know which `purs` commands are run under the hood\n\nThe `-v` flag will print out all the `purs` commands that `spago` invokes during its operations,\nplus a lot of diagnostic info, so you might want to use it to troubleshoot weird behaviours and/or crashes.\n\n### Force a registry refresh\n\nSpago caches the Registry Index for 15 minutes. If you need a package that was just published, you can force a refresh:\n\n```console\n$ spago install --refresh some-new-package\n```\n\nThe `--refresh` flag works with any command that accesses the Registry (`install`, `build`, `fetch`, etc.).\n\n### Install autocompletions for `bash`\n\nYou can just add this to your `.bashrc`:\n\n```bash\nsource \u003c(spago --bash-completion-script `which spago`)\n```\n\nor alternatively if you don't want to edit your `~/.bashrc`:\n\n```bash\nspago --bash-completion-script $(which spago) \u003e\u003e ~/.bash_completion\n```\n\n\u003e [!NOTE]\\\n\u003e If you installed Spago not with NPM, but with PNPM or some other package manager, this package manager might have bundled your installation and your package name in the script may end up being incorrect.\n\u003e For example, when installed with PNPM, the resulting script will reference incorrect package `bundle.js` instead of `spago`.\n\u003e If you're using something other than NPM, verify the referenced package name in the completions script.\n\n### Install autocompletions for `zsh`\n\nAutocompletions for `zsh` need to be somewhere in the `fpath` - you can see the folders\nincluded in your by running `echo $fpath`.\n\nYou can also make a new folder - e.g. `~/.my-completions` - and add it to the `fpath`\nby just adding this to your `~/.zshrc`:\n\n```bash\nfpath=(~/.my-completions $fpath)\n```\n\nThen you can obtain the completion definition for zsh and put it in a file called\n`_spago` [(yes it needs to be called like that)](https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org#telling-zsh-which-function-to-use-for-completing-a-command):\n\n```bash\nspago --zsh-completion-script $(which spago) \u003e ~/.my-completions/_spago\n```\n\nThen, reload completions with:\n\n```bash\ncompinit\n```\n\n\u003e [!NOTE]\\\n\u003e You might need to call this multiple times for it to work.\n\n\u003e [!NOTE]\\\n\u003e See the note in the Bash section above when installing Spago with a package manager other than NPM.\n\n## Concepts and explanations\n\nThis section details some of the concepts that are useful to know when using Spago. You don't have to read through this all at once, it's meant to be a reference for when you need it.\n\n### What's a \"package\"?\n\nSpago considers a \"package\" any folder that contains:\n\n- a `spago.yaml` file with a valid `package` section\n- a `src` subfolder with PureScript source files\n\nThat's all there is to it! You can have many of these in your repository if you'd like, and build them all together. See [the monorepo section](#monorepo-support) for more details.\n\nThe above holds for \"workspace packages\", i.e. the packages for which you have the source locally, and inside your repository. These are the packages \"in your project\".\n\nPackages on which your project depends on can come from a few different sources:\n\n- [the Registry][registry]\n- local packages - i.e. packages that are on your filesystem but external to your repository\n- remote packages - i.e. packages that are not on your filesystem, but somewhere on the internet\n\nThe bulk of the packages in your build will come from the Registry (often via a package set), but you are able to add local and remote packages to your build as well, by adding them to the `workspace.extraPackages` section of your `spago.yaml` file.\n\nSee [here](#add-a-package-to-the-package-set) and [here](#the-configuration-file) for more info about how to add these \"extra packages\".\n\nPackages have \"dependencies\", which are other packages that are required for them to build. These dependencies are listed in the `dependencies` field of the `package` section of the `spago.yaml` file. See [here](#the-configuration-file) for more info about the structure of a `package` configuration.\n\n### What's a \"package set\"?\n\nThe most generic way of defining a \"package set\" is \"a collection of package versions that are known to build together\". The point of a package set is to provide a \"stable\" set of packages that you can use to build your project, without worrying about version conflicts.\n\nIn practice, it looks something like [this][sample-package-set]:\n\n```json\n{\n  \"version\": \"41.2.0\",\n  \"compiler\": \"0.15.10\",\n  \"published\": \"2023-09-15\",\n  \"packages\": {\n    \"abc-parser\": \"2.0.1\",\n    \"ace\": \"9.1.0\",\n    \"aff\": \"7.1.0\",\n    \"aff-bus\": \"6.0.0\",\n    \"aff-coroutines\": \"9.0.0\",\n    \"aff-promise\": \"4.0.0\",\n    \"aff-retry\": \"2.0.0\",\n    \"affjax\": \"13.0.0\",\n    \"affjax-node\": \"1.0.0\",\n    \"affjax-web\": \"1.0.0\",\n    \"ansi\": \"7.0.0\",\n    \"argonaut\": \"9.0.0\",\n    ...\n  }\n}\n```\n\nThe Registry maintains an \"official\" package set such as the above, which is used by default by Spago, and _only_ contains packages that are contained in the Registry.\n\nWhenever anyone publishes a new package version to the Registry, the pipeline will try to build this package together with the existing set, and if the build succeeds then the new version will be added to this official set.\n\nHowever, Spago also supports using custom package sets, which can contain packages that are not in the Registry, and can be used to override existing packages with local or remote versions. See [here](#custom-package-sets) for more info.\n\n### The workspace\n\nFor any software project, it's usually possible to find a clear line between \"the project\" and \"the dependencies of the project\": we \"own\" our sources, while the dependencies only establish some sort of substrate over which our project lives and thrives.\n\nFollowing this line of reasoning, Spago - taking inspiration from other tools such as [Bazel][bazel] - uses the concept of of a \"workspace\" to characterise the sum of all the project packages and their dependencies (including only \"potential\" ones).\n\nA very succint introduction to this idea can be found [in Bazel's documentation][bazel-workspace]:\n\n\u003e A workspace is a directory tree on your filesystem that contains the source files for the software you want to build.\\\n\u003e Each workspace has a text file named `WORKSPACE` which may be empty, or may contain references to external dependencies required to build the outputs.\\\n\u003e Directories containing a file called `WORKSPACE` are considered the root of a workspace.\\\n\u003e Therefore, Bazel ignores any directory trees in a workspace rooted at a subdirectory containing a `WORKSPACE` file, as they form another workspace.\n\nSpago goes by these same rules, with the difference that we do not use a separate `WORKSPACE` file, but instead use the `workspace` section of the `spago.yaml` file to define what the set of our external dependencies are, and where they come from.\n\nThis can be as simple as:\n\n```yaml\nworkspace: {}\n```\n\n...which means that \"this is now a workspace, and all the dependencies are going to be fetched from the Registry\".\n\nOr it can be more complex, e.g.:\n\n```yaml\nworkspace:\n  packageSet:\n    url: https://raw.githubusercontent.com/some-user/custom-package-sets/some-release/packages.json\n  extraPackages:\n    aff:\n      path: ../my-purescript-aff\n```\n\n...which means that \"this is now a workspace, and all the dependencies are going to be fetched using instructions from this custom package set (which could point to the Registry packages or somewhere else), except for the `aff` package, which is going to be fetched from the local folder `../my-purescript-aff`\".\n\nAs described in the Bazel docs quoted above, the presence of a `workspace` section will denote the current folder as the root of a workspace, and Spago will recurse into its subfolders to find all the packages that are part of it - by looking for `spago.yaml` files with a `package` section - but ignore the subdirectory trees that are themselves workspaces - i.e. containing `spago.yaml` files with a `workspace` section.\n\n### The configuration file\n\nThis section documents all the possible fields that can be present in the `spago.yaml` file, and their meaning.\n\n```yaml\n# The workspace section is one of the two sections that can be present\n# at the top level. As described above, it defines where all of the\n# dependencies of the project come from.\n# It's optional, as it will be found only in the root of the project\n# (defining the workspace), and not in any sub-package configurations,\n# which will only contain the `package` section.\nworkspace:\n\n  # The packageSet field defines where to fetch the package set from.\n  # It's optional - not defining this field will make Spago use the\n  # Registry solver instead, to come up with a build plan.\n  packageSet:\n    # It could either be a pointer to the official registry sets that\n    # live at https://github.com/purescript/registry/tree/main/package-sets\n    registry: 11.10.0\n    # Or it could just point to a URL of a custom package set\n    # See the \"Custom package sets\" section for more info on making one.\n    url: https://raw.githubusercontent.com/purescript/package-sets/psc-0.15.7-20230207/packages.json\n    # It is also possible to point to a local package set instead:\n    path: ./my-custom-package-set.json\n\n  # This section defines any other packages that you'd like to include\n  # in the build. It's optional, in case you just want to use the ones\n  # coming from the Registry/package set.\n  extraPackages:\n    # Packages are always specified as a mapping from \"package name\" to\n    # \"where to find them\", and there are quite a few ways to define\n    # these locations:\n    # 1) local package - it's on your filesystem but not in the workspace\n    some-local-package:\n      path: ../some-local-package\n    # 2) remote package from the Registry\n    #    Just specify the version you want to use. You can run\n    #    `spago registry info` on a package to see its versions.\n    #    This is useful for packages that are not in the package set,\n    #    and useless when using the Registry solver.\n    some-registry-package: 1.0.2\n    # 3) remote package from Git\n    #    The `git` and `ref` fields are required (`ref` can be a branch,\n    #    a tag, or a commit hash).\n    #    The `subdir` field is optional and necessary if you'd like to use\n    #    a package that is not located in the root of the repo.\n    #    The `dependencies` field is optional and necessary if the package\n    #    does not have a `spago.yaml` file. In that case Spago will figure\n    #    out the dependencies automatically.\n    some-package-from-git:\n        git: https://github.com/purescript/registry-dev.git\n        ref: 68dddd9351f256980454bc2c1d0aea20e4d53fa9\n        subdir: lib\n        dependencies:\n          - foo\n    # 4) remote package from Git, legacy style (as the old package sets)\n    #    Works like the above, but all fields are mandatory.\n    legacy-package-style:\n        repo: \"https://github.com/purescript/purescript-prelude.git\"\n        version: \"v6.0.1\"\n        dependencies:\n          - prelude\n          - effect\n          - console\n\n  # This section is optional, and you should specify it only if you'd like\n  # to build with a custom backend, such as `purerl`.\n  # Please see the \"Alternate backends\" section for more info.\n  backend:\n    # The command to run to build with this backend - required.\n    cmd: \"node\"\n    # Optional list of arguments to pass to the backend when building.\n    args:\n      - \"arg1\"\n      - \"arg2\"\n      - \"arg3\"\n\n  # Optional setting to enable the \"lockfile\". Enabling it will generate\n  # a `spago.lock` file with a cache of the build plan.\n  # It's disabled by default when using package sets (because we already\n  # get a stable build plan from there) and enabled by default when using\n  # the Registry solver.\n  # See \"The lock file\" section for more details.\n  lock: false\n\n  # Optional section to further customise the build.\n  buildOpts:\n    # Directory for the compiler products - optional, defaults to `output`.\n    output: \"output\"\n    # Specify whether to censor warnings coming from the compiler\n    # for files in the `.spago` directory`.\n    # Optional and can be one of two possible values\n    censorLibraryWarnings:\n      # Value 1: \"all\" - All warnings are censored\n      all\n\n      # Value 2: `Array (Either String { byPrefix :: String })`\n      # - String values:\n      #      censor warnings if the code matches this code\n      # - { byPrefix } values:\n      #      censor warnings if the warning's message\n      #      starts with the given text.\n      - CodeName\n      # Note: when using `byPrefix`, use the `\u003e` for block-string:\n      # see https://yaml-multiline.info/\n      - byPrefix: \u003e\n          Data.Map's `Semigroup` instance\n\n    # Specify whether to censor warnings coming from the compiler\n    # for files in workspace project source\n    # Optional - takes the same values as censorLibraryWarnings above\n    censorProjectWarnings: all\n\n    # Specify whether to censor warnings coming from the compiler\n    # for files in workspace project tests\n    # Optional - takes the same values as censorLibraryWarnings above\n    censorTestWarnings: all\n\n    # Specify whether to show statistics at the end of the compilation,\n    # and how verbose they should be.\n    # Can be 'no-stats', 'compact-stats' (default), or 'verbose-stats',\n    # which breaks down the statistics by warning code.\n    statVerbosity: \"compact-stats\"\n\n# This is the only other section that can be present at the top level.\n# It specifies the configuration for a package in the current folder,\n# and it's optional, as one could just have a `workspace` section.\npackage:\n\n  # The package name and the `dependencies` fields are the only required\n  # ones, everything else is optional.\n  name: my-package-name\n  dependencies:\n    # Dependencies can be specified in a few ways:\n    # 1) just with a package name\n    #    Then Spago will use the version specified in the package set,\n    #    or assume the widest possible range if using the Registry solver.\n    - some-package\n    # 2) explicitly specify the widest range\n    #    Same as above, but explicit.\n    - package-with-star-range: *\n    # 3) specify a defined version range\n    #    The registry will then check if the package version is included\n    #    in this range.\n    - package-with-range: \"\u003e=1.1.1 \u003c2.0.0\"\n    # 4) specify an exact version\n    #    Shorthand for \"\u003e=1.2.3 \u003c1.2.4\", pinning to a specific patch version.\n    - package-with-exact-version: \"1.2.3\"\n\n  # Optional description for the package\n  description: \"a useful package\"\n\n  # Optional section to further customise the build for this package.\n  build:\n    # Fail the build if this package's `dependencies` field has redundant/underspecified packages.\n    # Optional boolean that defaults to `false`.\n    pedanticPackages: false\n\n    # Specify whether to censor warnings coming from the compiler\n    # for files from this package.\n    # Optional and can be one of two possible values\n    censorProjectWarnings:\n      # Value 1: \"all\" - All warnings are censored\n      all\n\n      # Value 2: `NonEmptyArray (Either String { byPrefix :: String })`\n      # - String values:\n      #      censor warnings if the code matches this code\n      # - { byPrefix } values:\n      #      censor warnings if the warning's message\n      #      starts with the given text.\n      - CodeName\n      # Note: when using `byPrefix`, use the `\u003e` for block-string:\n      # see https://yaml-multiline.info/\n      - byPrefix: \u003e\n          Data.Map's `Semigroup` instance\n    # Convert compiler warnings for files in this package's src code\n    # into errors that can fail the build.\n    # Optional and defaults to false\n    strict:\n      true\n\n  # Optional section to specify the configuration options for bundling\n  # The following options are all optional, and will default to the values\n  # shown below.\n  bundle:\n    minify: false\n    # Entrypoint for the bundle\n    module: Main\n    # The path of the bundle file\n    outfile: \"index.js\"\n    # Possible values are 'node' or 'browser'\n    platform: browser\n    # Possible values are 'app' or 'module'\n    type: \"app\"\n    # Any other flags that should be passed to the bundler.\n    # You can use this to e.g. pass `--external` flags to esbuild:\n    extra_args:\n      - \"--external:ssh2\"\n\n  # Optional section to configure the behaviour of `spago run`.\n  # All the fields are optional.\n  run:\n    # The entrypoint for the program\n    main: Main\n    # List of arguments to pass to the program\n    execArgs:\n      - \"--cli-arg\"\n      - \"foo\"\n\n  # Optional section to configure `spago test`\n  # The `main` and `dependencies` fields are required.\n  test:\n    main: Test.Main\n    # This works like `package.dependencies`\n    dependencies:\n    - foo\n    # Optional list of arguments to pass to the test program\n    execArgs:\n      - \"--cli-arg\"\n      - \"foo\"\n\n    # Fail the build if this package's test's `dependencies` field has redundant/underspecified packages.\n    # Optional boolean that defaults to `false`.\n    pedanticPackages: false\n\n    # Specify whether to censor warnings coming from the compiler\n    # for files from this package's test code.\n    # Optional and can be one of two possible values\n    censorTestWarnings:\n      # Value 1: \"all\" - All warnings are censored\n      all\n\n      # Value 2: `NonEmptyArray (Either String { byPrefix :: String })`\n      # - String values:\n      #      censor warnings if the code matches this code\n      # - { byPrefix } values:\n      #      censor warnings if the warning's message\n      #      starts with the given text.\n      - CodeName\n      # Note: when using `byPrefix`, use the `\u003e` for block-string:\n      # see https://yaml-multiline.info/\n      - byPrefix: \u003e\n          Data.Map's `Semigroup` instance\n    # Convert compiler warnings for files from this package's test code\n    # into errors that can fail the build.\n    # Optional and defaults to false\n    strict:\n      true\n\n  # Optional section for configuring the `spago publish` command.\n  # If you intend to publish your package, this section becomes mandatory.\n  publish:\n    # The version of your package. This follows semver rules, but with no\n    # prereleases - so only major.minor.patch.\n    version: 1.0.0\n    # The license for your source, in SPDX format: https://spdx.dev/\n    license: BSD-3-Clause\n    # Optional list of globs to include in the published archive, in\n    # addition to the list of files that the Registry includes by default:\n    # https://github.com/purescript/registry-dev/blob/master/SPEC.md#always-included-files\n    include:\n    - \"test/**/*.purs\"\n    # Optional list of globs to exclude from the published archive, in\n    # addition to the list of files that the Registry includes by default:\n    # https://github.com/purescript/registry-dev/blob/master/SPEC.md#always-excluded-files\n    # Note that the Registry will first apply the `include` list, then\n    # the `exclude` one, as detailed in the specification:\n    # https://github.com/purescript/registry-dev/blob/master/SPEC.md#33-manifest\n    exclude:\n    - \"test/graphs/**/*\"\n    # The place where the Registry will fetch the source from.\n    # This is optional since you might want to release the code without\n    # publishing to the Registry, which is what this is needed for.\n    location:\n      # There are a few supported locations:\n      # 1) Github: no URL needed, just username and the name of the repo\n      #    The `subdir` field is optional, and only necessary if your\n      #    package is not in the root of the repo.\n      githubOwner: owners-username\n      githubRepo: repo-name\n      subdir: lib\n      # 2) Git: any git server should work with this\n      #    The `subdir` is optional as above\n      url: git://someurl...\n      subdir: lib\n```\n\n### The lock file\n\nThe lock file is a file that Spago can generate to cache the build plan, so that it can be reused in subsequent builds.\n\nWhen using package sets it is disabled by default - since we already get a stable build plan from there - while it's enabled by default when using the Registry solver.\n\nYou can enable it manually by adding a `lock: true` field to the `workspace` section of your `spago.yaml` file, and that will keep it on regardless of which solving mode you're using.\n\n### File System Paths used in Spago\n\nRun `spago ls paths` to see all paths used by Spago. But in general, Spago utilizes two main directories for every project:\n- the local cache directory\n- the global cache directory\n\nThe local cache directory is located at `\u003cproject-directory\u003e/.spago` and its location cannot be changed.\n\nThe global cache directory's location depends on your OS. Its location can be changed by configuring the corresponding environment variable, if it is used:\n- Mac: `~/Library/Caches/spago-nodejs`. The location cannot be changed.\n- Linux: `${XDG_CACHE_HOME}/spago-nodejs`, or if `XDG_CACHE_HOME` is not set, `~/.cache/spago-nodejs`. See [`XDG_CACHE_HOME`](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).\n- Windows: `%LOCALAPPDATA%\\spago-nodejs\\Cache`, or if `$LOCALAPPDATA%` is not set, `C:\\Users\\USERNAME\\AppData\\Local\\spago-nodejs\\Cache`.\n- NixOS: `${XDG_RUNTIME_DIR}/spago-nodejs`. See [`XDG_RUNTIME_DIR`](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).\n\n\n## FAQ\n\n### Why can't `spago` also install my npm dependencies?\n\nA common scenario is that you'd like to use things like `react-basic`, or want to depend\non JS libraries like ThreeJS.\nIn any case, you end up depending on some NPM package.\n\nAnd it would be really nice if `spago` would take care of installing all of these\ndependencies, so we don't have to worry about running npm besides it, right?\n\nWhile these scenarios are common, they are also really hard to support.\nIn fact, it might be that a certain NPM package in your transitive dependencies\nwould only support the browser, or only node. Should `spago` warn about that?\nAnd if yes, where should we get all of this info?\n\nAnother big problem is that the JS backend is not the only backend around. For example,\nPureScript has an fairly active [Erlang backend][purerl] among the others.\n\nThese backends are going to use different package managers for their native dependencies,\nand while it's feasible for `spago` to support the backends themselves, also supporting\nall the possible native package managers (and doing things like building package-sets for their\ndependencies' versions) is not a scalable approach (though we might do this in the future if\nthere's enough demand).\n\nSo this is the reason why if you or one of your dependencies need to depend on some \"native\"\npackages, you should run the appropriate package-manager for that (e.g. npm).\n\n### Differences from legacy spago\n\n#### Watch mode\n\nSpago dropped support for the --watch flag in `spago build` and `spago test`.\n\nVSCode users are recommended to use the [Purescript IDE][ide-purescript] extension for seamless experiences with automatic rebuilds.\n\nUsers of other editors, e.g. vim, emacs, etc., can make use of the underlying [LSP plugin][purescript-language-server].\n\nIf you want a very simple drop in replacement for `spago test --watch`, you can use a general purpose tool such as [watchexec]:\n\n```console\nwatchexec -e purs,js,yaml -- spago test\n```\n\n#### `sources` in the configuration file\n\nThe `sources` field in the configuration file does not exist anymore.\n\nInstead, Spago will look for a `src` folder in the package root, and will use that as the source folder,\nand similarly for the `test` folder, using that for the test sources.\n\n[jq]: https://jqlang.github.io/jq/\n[acme]: https://hackage.haskell.org/package/acme-everything\n[pulp]: https://github.com/purescript-contrib/pulp\n[stack]: https://github.com/commercialhaskell/stack\n[bazel]: https://bazel.build/\n[cargo]: https://github.com/rust-lang/cargo\n[purerl]: https://github.com/purerl/purescript\n[pursuit]: https://pursuit.purescript.org/\n[registry]: https://github.com/purescript/registry\n[spago-npm]: https://www.npmjs.com/package/spago\n[new-issue]: https://github.com/purescript/spago/issues/new\n[purescript]: https://github.com/purescript/purescript\n[psc-package]: https://github.com/purescript/psc-package\n[luu-monorepo]: https://danluu.com/monorepo/\n[contributing]: CONTRIBUTING.md\n[spago-legacy]: https://github.com/purescript/spago-legacy\n[monorepo-tools]: https://monorepo.tools/\n[install-esbuild]: https://esbuild.github.io/getting-started/#install-esbuild\n[bazel-workspace]: https://bazel.build/concepts/build-ref\n[purescript-overlay]: https://github.com/thomashoneyman/purescript-overlay\n[sample-package-set]: https://github.com/purescript/registry/blob/main/package-sets/41.2.0.json\n[watchexec]: https://github.com/watchexec/watchexec#quick-start\n[purescript-language-server]: https://github.com/nwolverson/purescript-language-server\n[ide-purescript]: https://marketplace.visualstudio.com/items?itemName=nwolverson.ide-purescript\n[registry-dev-auth]: https://github.com/purescript/registry-dev/blob/master/SPEC.md#52-authentication\n","funding_links":[],"categories":["Projects","构建系统和依赖性管理工具","package-manager","PureScript","Libraries and Tools"],"sub_categories":["Other Useful Tools"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurescript%2Fspago","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurescript%2Fspago","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurescript%2Fspago/lists"}