A package manager for the Hemlock programming language. hpm uses GitHub as its package registry, where packages are identified by their GitHub repository path (e.g., hemlang/sprout).
For comprehensive documentation, see the docs/ directory:
-
Getting Started
- Quick Start - Get up and running in 5 minutes
- Installation - Detailed installation guide
- Project Setup - Project structure and configuration
-
User Guide
- Command Reference - All commands and options
- Configuration - Environment variables and config files
- Troubleshooting - Common issues and solutions
-
Package Development
- Creating Packages - Publish your own packages
- Package Specification - package.json format
- Versioning - Semantic versioning guide
-
Reference
- Exit Codes - CLI exit codes
- Architecture - Internal design (for contributors)
Install the latest release with a single command:
curl -fsSL https://raw.githubusercontent.com/hemlang/hpm/main/install.sh | shThis automatically detects your OS and architecture, downloads the appropriate binary, and installs to /usr/local/bin.
Options:
# Install to a custom location
curl -fsSL https://raw.githubusercontent.com/hemlang/hpm/main/install.sh | sh -s -- --prefix ~/.local
# Install a specific version
curl -fsSL https://raw.githubusercontent.com/hemlang/hpm/main/install.sh | sh -s -- --version 1.0.5If you prefer to build from source, hpm requires Hemlock to be installed first.
# Clone the repository
git clone https://github.com/hemlang/hpm.git
cd hpm
# Install to /usr/local/bin (requires sudo on most systems)
sudo make install
# Or install to a custom location
make install PREFIX=$HOME/.localAfter installation, you can run hpm from anywhere:
hpm --helpIf you prefer not to use make install, you can run hpm directly:
# Run from the hpm directory
./hpm --help
# Or run via hemlock
hemlock /path/to/hpm/src/main.hml --help# Initialize a new project
hpm init
# Install a package
hpm install hemlang/sprout
# Install a specific version
hpm install hemlang/sprout@^1.0.0
# Install as dev dependency
hpm install --dev hemlang/test-utils
# List installed packages
hpm list
# Run a script
hpm run testCreate a new package.json interactively.
hpm init # Interactive mode
hpm init --yes # Use all defaultsInstall all dependencies from package.json, or add a new dependency.
hpm install # Install all dependencies
hpm install hemlang/sprout # Add and install a package
hpm install hemlang/sprout@^1.0.0 # Add with version constraint
hpm install hemlang/test-utils --dev # Add as dev dependencyFlags:
--dev, -D- Add to devDependencies--verbose- Show detailed output--dry-run- Show what would be installed without installing
Remove a package.
hpm uninstall hemlang/sproutUpdate dependencies to latest versions within constraints.
hpm update # Update all packages
hpm update hemlang/sprout # Update specific packageShow installed packages.
hpm list # Show full dependency tree
hpm list --depth=0 # Show only direct dependenciesShow packages with newer versions available.
hpm outdatedRun a script from package.json.
hpm run test
hpm run buildShorthand for hpm run test.
Explain why a package is installed (show dependency chain).
hpm why hemlang/routerManage the global cache.
hpm cache list # List cached packages
hpm cache clean # Clear cachePackages are identified by their GitHub owner/repo path:
hemlang/sprout
alice/http-client
bob/json-utils
hpm uses Semantic Versioning 2.0.0:
| Syntax | Meaning |
|---|---|
1.0.0 |
Exact version |
^1.2.3 |
Compatible with 1.x.x (≥1.2.3 and <2.0.0) |
~1.2.3 |
Patch updates only (≥1.2.3 and <1.3.0) |
>=1.0.0 |
Greater than or equal |
<2.0.0 |
Less than |
>=1.0.0 <2.0.0 |
Range |
* |
Any version |
{
"name": "owner/repo",
"version": "1.0.0",
"description": "Package description",
"author": "Name <email@example.com>",
"license": "MIT",
"repository": "https://github.com/owner/repo",
"main": "src/index.hml",
"dependencies": {
"owner/package": "^1.0.0"
},
"devDependencies": {
"owner/test-lib": "^1.0.0"
},
"scripts": {
"test": "hemlock test/run.hml",
"build": "hemlock compile src/main.hml"
}
}Once installed, packages can be imported using their GitHub path:
// Import from package root (uses "main" from package.json)
import { app, router } from "hemlang/sprout";
// Import from subpath
import { middleware } from "hemlang/sprout/middleware";
import { utils } from "alice/http-client/internal/utils";
// Standard library (built into Hemlock)
import { HashMap } from "@stdlib/collections";
For import { x } from "owner/repo/path":
- Check
hem_modules/owner/repo/path.hml - Check
hem_modules/owner/repo/path/index.hml - Check
hem_modules/owner/repo/src/path.hml - Check
hem_modules/owner/repo/src/path/index.hml
For import { x } from "owner/repo" (no subpath):
- Read
mainfield fromhem_modules/owner/repo/package.json - Default to
src/index.hmlif not specified
my-project/
├── package.json
├── package-lock.json
├── src/
│ └── main.hml
├── test/
│ └── test.hml
└── hem_modules/
└── hemlang/
└── sprout/
├── package.json
└── src/
Downloaded packages are cached at ~/.hpm/cache/ to avoid re-downloading.
For higher rate limits and private repository access, set a GitHub token:
export GITHUB_TOKEN=ghp_xxxxxxxxxxxxOr create ~/.hpm/config.json:
{
"github_token": "ghp_xxxxxxxxxxxx"
}Publishing is just git:
# Ensure package.json is valid
hpm init
# Commit and tag
git add .
git commit -m "Release v1.0.0"
git tag v1.0.0
git push origin main --tagsUsers install with:
hpm install yourname/your-package@1.0.0| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Dependency conflict |
| 2 | Package not found |
| 3 | Version not found |
| 4 | Network error |
| 5 | Invalid package.json |
| 6 | Integrity check failed |
| 7 | GitHub rate limit exceeded |
| 8 | Circular dependency |
MIT