diff --git a/CLAUDE.md b/CLAUDE.md index 34e5c349..7a5adfd2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -119,6 +119,20 @@ var v = a[] // pop: v is 3, a is [1, 2] - `packages/` — core packages - `Makefile` — build system (`make` to rebuild, `make bootstrap` for first build) +## Package Management (Shop CLI) + +When running locally with `./cell --dev`, these commands manage packages: + +``` +./cell --dev add # add a package (local path or remote) +./cell --dev remove # remove a package (cleans lock, symlink, dylibs) +./cell --dev build # build C modules for a package +./cell --dev test package # run tests for a package +./cell --dev list # list installed packages +``` + +Local paths are symlinked into `.cell/packages/`. The build step compiles C files to `.cell/lib//.dylib`. C files in `src/` are support files linked into module dylibs, not standalone modules. + ## Testing After any C runtime changes, run all three test suites before considering the work done: diff --git a/docs/cli.md b/docs/cli.md index 7391cc98..dc69033d 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -44,12 +44,20 @@ pit update # update specific package ### pit remove -Remove a package from the shop. +Remove a package from the shop. Removes the lock entry, the package directory (or symlink), and any built dylibs. ```bash pit remove gitea.pockle.world/john/oldpackage +pit remove /Users/john/work/mylib # local path +pit remove . # current directory +pit remove mypackage --dry-run # show what would be removed +pit remove mypackage --prune # also remove orphaned dependencies ``` +Options: +- `--prune` — also remove packages that are no longer needed by any remaining root +- `--dry-run` — show what would be removed without removing anything + ### pit list List installed packages. @@ -70,11 +78,18 @@ pit ls # list files in specified package ### pit build -Build the current package. Compiles C files into per-file dynamic libraries and installs them to `~/.pit/lib//.dylib`. +Build C modules for a package. Compiles each C file into a per-file dynamic library and installs them to `~/.pit/lib//.dylib`. C files in `src/` directories are compiled as support objects and linked into the module dylibs. ```bash -pit build # build current package -pit build # build specific package +pit build # build all packages +pit build # build specific package +pit build /Users/john/work/mylib # build local package +pit build . # build current directory +pit build -t macos_arm64 # cross-compile for target +pit build -b debug # build type: release (default), debug, minsize +pit build --list-targets # list available targets +pit build --force # force rebuild +pit build --dry-run # show what would be built ``` ### pit test @@ -82,10 +97,13 @@ pit build # build specific package Run tests. See [Testing](/docs/testing/) for the full guide. ```bash -pit test # run tests in current package -pit test all # run all tests -pit test # run tests in specific package -pit test suite --verify --diff # with IR verification and differential testing +pit test # run tests in current package +pit test suite # run specific test file +pit test all # run all tests in current package +pit test package # run tests in a named package +pit test package /Users/john/work/mylib # run tests for a local package +pit test package all # run tests from all packages +pit test suite --verify --diff # with IR verification and differential testing ``` ### pit link @@ -125,13 +143,18 @@ pit clean ### pit add -Add a dependency to the current package. Updates `cell.toml` and installs the package to the shop. +Add a dependency to the current package. Installs the package to the shop, builds any C modules, and updates `cell.toml`. ```bash -pit add gitea.pockle.world/john/prosperon # default alias -pit add gitea.pockle.world/john/prosperon myalias # custom alias +pit add gitea.pockle.world/john/prosperon # remote, default alias +pit add gitea.pockle.world/john/prosperon myalias # remote, custom alias +pit add /Users/john/work/mylib # local path (symlinked) +pit add . # current directory +pit add ../sibling-package # relative path ``` +For local paths, the package is symlinked into the shop rather than copied. Changes to the source directory are immediately visible. + ### pit clone Clone a package to a local path and link it for development. diff --git a/internal/shop.cm b/internal/shop.cm index 761ba76d..7517c6d5 100644 --- a/internal/shop.cm +++ b/internal/shop.cm @@ -1313,6 +1313,20 @@ Shop.remove = function(pkg) { Shop.save_lock(lock) } + // Remove package symlink/directory + var pkg_dir = get_packages_dir() + '/' + safe_package_path(pkg) + if (fd.is_link(pkg_dir)) { + fd.unlink(pkg_dir) + } else if (fd.is_dir(pkg_dir)) { + fd.rmdir(pkg_dir, 1) + } + + // Remove built dylibs + var lib_dir = global_shop_path + '/lib/' + safe_package_path(pkg) + if (fd.is_dir(lib_dir)) { + fd.rmdir(lib_dir, 1) + } + log.console("Removed " + pkg) return true }