Package and capability management for Forge Kernel.
Package manager for Forge capability modules with registry support and integrity verification. Think of it like a trusted supplier system — you explicitly trust sources (like trusting a specific store). You control where things come from. Not a central marketplace you can't control.
The package manager isn't trying to compete with or replace Composer. It's a choice. You can use it, or you can use your own thing. See Still Use Your Own Thing for more on this.
Why it exists:
What you get:
Use Composer if you want: Central package registry, dependency resolution, semantic versioning constraints, that ecosystem.
Use Forge's package manager if you want: Control over your sources, Linux package manager-like behavior, trusted sources philosophy, freedom to choose where your capabilities come from, units instead of source code, simple folder-based distribution.
Both can coexist. This is about choice, not competition. You can still use Composer, Git submodules, manual installation, or whatever works for you. The package manager is there if you want it — see Still Use Your Own Thing.
Forge capabilities are shipped as complete, self-contained ZIP files — units, not source code. This fundamental design decision shapes how the package manager works and why it's different from traditional package managers.
Each capability version is a single ZIP file containing everything needed to run it. No compilation, no build steps, no processing required. Download the ZIP, extract it, and it's ready to use.
Think of it like this: Instead of getting ingredients and a recipe (source code + build instructions), you get a finished meal (complete ZIP file). Just extract and serve.
Each capability ZIP file contains the complete module structure:
forge-auth-0.2.4.zip
└── forge-auth/
├── forge.json # Module metadata
├── src/ # Source code
│ ├── Controllers/
│ ├── Services/
│ ├── Middlewares/
│ └── ...
├── config/ # Configuration files
├── resources/ # Views, assets, etc.
└── tests/ # Test files
The package manager works like old school software mirrors. Remember when you'd navigate through folders on an FTP server to find the file you needed? That's exactly how this works — simple, transparent, and human-readable.
Capabilities are organized in a simple folder structure. To find a capability, you navigate through folders:
modules/
└── forge-auth/ # Navigate to the capability
└── 0.2.4/ # Navigate to the version
└── 0.2.4.zip # There's your file!
The package manager automates this navigation. When you run package:install-module --module=forge-auth@0.2.4, it:
modules.json to find the capabilityurl fieldmodules/forge-auth/0.2.4/0.2.4.zipmodules/ directoryBecause it's just folders and files, you can manually browse any registry. If you're using a Git-based registry, you can browse it on GitHub. If it's an HTTP registry, you can navigate the folders in your browser. If it's SFTP, you can use any FTP client. The structure is always the same, always human-readable.
Transparency: There's no magic. You can see exactly where capabilities come from, what versions are available, and download them manually if you want. The package manager just makes it convenient.
Every registry follows the same simple structure. Here's how it's organized:
registry-root/
├── modules.json # Manifest with all capabilities and versions
└── modules/
└── forge-auth/
├── 0.2.4/
│ └── 0.2.4.zip
├── 0.2.3/
│ └── 0.2.3.zip
├── 0.2.2/
│ └── 0.2.2.zip
└── ...
The modules.json file is the index. It lists all available capabilities, their versions, and where to find them:
{
"forge-auth": {
"latest": "0.2.4",
"versions": {
"0.2.4": {
"description": "Version 0.2.4 of forge-auth",
"url": "forge-auth/0.2.4",
"integrity": "33bd70eead56a2855e97147e870858bf20bd8416a92cb516066aa31020a09367"
},
"0.2.3": {
"description": "Version 0.2.3 of forge-auth",
"url": "forge-auth/0.2.3",
"integrity": "3a0b1747f2b8d4f3f604e6e070872fd13ebb78aad93b2838a830e8978ad9b6f6"
}
}
}
}
modules/. For example, "forge-auth/0.2.4" means modules/forge-auth/0.2.4/
The ZIP file is named after the version number. In the folder modules/forge-auth/0.2.4/, you'll find 0.2.4.zip. Simple and predictable.
The unit-based approach is perfect for small businesses that want control without complexity.
You don't need expensive hosting or complex infrastructure. Host capabilities on:
You don't need CI/CD pipelines, build servers, or complex tooling. Just:
modules.jsonThat's it. No build steps, no compilation, no special tools required.
You control:
Managing a registry is as simple as managing files. No databases, no special services, no complex APIs. Just folders and files.
Enterprise organizations need control, compliance, and security. The unit-based approach delivers all three.
Keep capabilities completely internal:
You control the entire distribution chain:
Every capability has an integrity hash. You can:
No need for special services or new infrastructure. Works with:
Perfect for organizations with strict compliance requirements:
You can mirror or cache capabilities locally for:
The package manager supports multiple source types. Choose what works for you, or use multiple sources at once.
GitHub, GitLab, Bitbucket, or any Git repository
Perfect for version control and collaboration
Secure file transfer protocol
Secure, encrypted file transfers
File transfer protocol (with optional SSL)
Works with standard FTP servers
Direct download from URLs
Simple web server hosting
Local file system
For development or air-gapped environments
Network file shares
For enterprise network environments
Configure your trusted sources in config/source_list.php:
[
// Official Forge registry (GitHub)
[
'name' => 'forge-engine-modules',
'type' => 'git',
'url' => 'https://github.com/forge-engine/modules',
'branch' => 'main',
'private' => false
],
// Your company's private registry (SFTP)
[
'name' => 'company-modules',
'type' => 'sftp',
'host' => 'sftp.company.com',
'username' => env('SFTP_USER'),
'password' => env('SFTP_PASS'),
'path' => '/modules'
],
// Internal network share
[
'name' => 'internal-modules',
'type' => 'network',
'path' => '\\\\fileserver\\modules'
]
]
];
Each source is a trusted source you explicitly add. You decide:
The package manager is a choice, not a requirement. You have complete freedom to use whatever tools and methods work for you.
You can still use Composer for dependencies. The package manager doesn't replace Composer — it's an alternative for managing Forge capabilities. Use both, use one, or use neither. Your choice.
You can manually download and install capabilities:
modules/ directoryforge.json if neededThe package manager just automates this process. You can do it manually if you prefer.
You can use Git submodules to include capabilities directly from their source repositories. The package manager doesn't prevent this — it's just another option.
Write your own installation scripts. Use deployment tools. Use whatever works for your workflow. The package manager is there if you want it, but you're not locked into it.
Freedom: The package manager is a tool, not a constraint. Use it when it helps, ignore it when it doesn't. You're in control.
Connect to multiple registries including official Forge registry and custom private registries.
Every module download is verified using SHA-256 integrity hashes to ensure security.
Sophisticated version resolution with support for semantic versioning and constraints.
Generate and use lock files for reproducible module installations across environments.
Pre-installed with Forge Kernel. Manual installation options available.
# Install ForgePackageManager capability (with wizard)
php forge.php package:install-module
# Install specific module (skip wizard)
php forge.php package:install-module --module=ForgePackageManager
# Install specific version (skip wizard)
php forge.php package:install-module --module=ForgePackageManager@1.0.0
# Verify installation
php forge.php package:list-modules | grep ForgePackageManager
Pre-installed: ForgePackageManager is included by default in new Forge installations.
Configure through config/source_list.php file. This is where you define your trusted sources — like configuring apt sources on Debian or yum repositories on RHEL.
Similar to Linux package managers (apt, yum, pacman), you explicitly define and trust your capability sources. You control where your capabilities come from. This gives you freedom and control over your dependencies.
[
// Official Forge registry (included by default)
[
'name' => 'forge-engine-modules',
'type' => 'git',
'url' => 'https://github.com/forge-engine/modules',
'branch' => 'main',
'private' => false,
'description' => 'Forge Kernel Official Modules', // Optional: shown in wizard
'personal_token' => env('GITHUB_TOKEN') // Only needed for private repos
],
// Custom private registry example
[
'name' => 'my-company-modules',
'type' => 'git',
'url' => 'https://github.com/mycompany/private-modules',
'branch' => 'main',
'private' => true,
'description' => 'Company Internal Modules', // Optional: shown in wizard
'personal_token' => env('GITHUB_TOKEN')
],
],
'cache_ttl' => 3600, // Cache time-to-live in seconds
];
Registry Descriptions: You can add an optional description field to each registry entry. This description will be displayed in the interactive wizard when selecting registries, helping users identify the purpose of each registry (e.g., "Forge Kernel Official Modules", "Company Internal Modules").
The package manager supports multiple source types:
See the ForgePackageManager documentation for detailed configuration of each source type.
Use environment variables for sensitive configuration:
# .env file
GITHUB_TOKEN=ghp_your_github_personal_access_token
PRIVATE_REGISTRY_TOKEN=your_private_registry_token
CACHE_TTL=7200
Enable developer mode to unlock registry management commands. Set FORGE_DEVELOPER_MODE=true in your .env file.
Once developer mode is enabled, you can use dev:registry:init to initialize a new registry. The command uses a wizard that asks:
framework or modules (defaults to modules if not specified)main)yes or no (defaults to no)# Initialize with wizard (interactive)
php forge.php dev:registry:init
# Initialize modules registry (skip wizard)
php forge.php dev:registry:init --type=modules
# Initialize framework registry (skip wizard)
php forge.php dev:registry:init --type=framework
You can still manage your registry manually if you prefer. Create the directory structure, add your modules, and update modules.json manually. However, developer mode commands make it easier and ensure proper structure.
Note: Developer mode commands are only available when FORGE_DEVELOPER_MODE=true is set in your .env file. This prevents accidental use of development commands in production environments.
The package:install-module command features an interactive wizard that guides you through the installation process. Use the --module= parameter to skip the wizard and specify the module directly.
You can install multiple modules at once by providing module names as positional arguments. If no version is specified, the latest version will be installed automatically.
# Install multiple modules (latest versions)
php forge.php package:install-module module-one module-two module-three
# Install multiple modules with mixed versions
php forge.php package:install-module module-one module-two@1.0.0 module-three
# Install multiple modules with force flag
php forge.php package:install-module module-one module-two --force
When you run package:install-module without arguments, an interactive wizard starts:
forge-welcome@1.0.0)# Install with wizard (interactive)
php forge.php package:install-module
# Install latest version (skip wizard)
php forge.php package:install-module --module=forge-auth
# Install specific version (skip wizard)
php forge.php package:install-module --module=forge-auth@1.2.0
# Install multiple modules (skip wizard)
php forge.php package:install-module forge-auth forge-storage forge-logger
# Install multiple modules with versions (skip wizard)
php forge.php package:install-module forge-auth@1.2.0 forge-storage forge-logger@0.1.0
# Force download bypassing cache (skip wizard)
php forge.php package:install-module --module=forge-auth --force
# Install all capabilities from lock file and scaffold app structure
php forge.php package:install-project
Version Selection: When browsing modules from git-based registries, version options display commit messages (truncated to 80 characters) to help you understand what changed in each version, similar to dev:modules:list.
The package:remove-module command features an interactive wizard that displays all installed modules with their descriptions, making it easy to select which module(s) to remove.
You can remove multiple modules at once by providing module names as positional arguments. Each module will prompt for confirmation if it has migrations, seeders, or assets.
# Remove multiple modules
php forge.php package:remove-module module-one module-two module-three
# Remove multiple modules with force flag (skip confirmations)
php forge.php package:remove-module module-one module-two --force
When you run package:remove-module without arguments:
# Remove with wizard (interactive - shows installed modules with descriptions)
php forge.php package:remove-module
# Remove a capability (skip wizard)
php forge.php package:remove-module --module=forge-auth
# Remove multiple modules (skip wizard)
php forge.php package:remove-module forge-auth forge-storage forge-logger
# Skip confirmation prompts (skip wizard)
php forge.php package:remove-module --module=forge-auth --force
# Remove multiple modules with force flag (skip wizard)
php forge.php package:remove-module forge-auth forge-storage --force
# List all available capabilities
php forge.php package:list-modules
ForgePackageManager supports custom registries for private capabilities and enterprise
deployments. Configure your trusted sources in config/source_list.php.
// config/source_list.php
return [
'registry' => [
// Private GitHub repository
[
'name' => 'acidlake-modules',
'url' => 'https://github.com/acidlake/acidlake-modules',
'branch' => 'main',
'private' => true,
'personal_token' => env('GITHUB_TOKEN', 'your-secret-token'),
],
// Private GitLab repository
[
'name' => 'company-gitlab-modules',
'url' => 'https://gitlab.company.com/forge-modules',
'branch' => 'main',
'private' => true,
'personal_token' => env('GITLAB_TOKEN'),
],
// Public custom registry
[
'name' => 'community-modules',
'url' => 'https://github.com/forge-community/modules',
'branch' => 'main',
'private' => false,
],
],
'cache_ttl' => 3600
];
Your custom registry should follow the Forge module registry structure:
your-registry-repo/
├── modules/
│ ├── YourModule1/
│ │ ├── forge.json
│ │ └── src/
│ ├── YourModule2/
│ │ ├── forge.json
│ │ └── src/
│ └── modules.json
└── README.md
Here are more examples of different registry configurations you can add:
// config/source_list.php
return [
'registry' => [
// Enterprise GitHub with organization
[
'name' => 'company-enterprise-modules',
'url' => 'https://github.company.com/org/forge-modules',
'branch' => 'main',
'private' => true,
'personal_token' => env('GITHUB_ENTERPRISE_TOKEN'),
],
// GitLab with specific group
[
'name' => 'gitlab-group-modules',
'url' => 'https://gitlab.com/my-group/forge-modules',
'branch' => 'develop',
'private' => true,
'personal_token' => env('GITLAB_ACCESS_TOKEN'),
],
// Bitbucket private repository
[
'name' => 'bitbucket-modules',
'url' => 'https://bitbucket.org/team/forge-modules',
'branch' => 'master',
'private' => true,
'personal_token' => env('BITBUCKET_APP_PASSWORD'),
],
// Azure DevOps repository
[
'name' => 'azure-devops-modules',
'url' => 'https://dev.azure.com/organization/project/_git/forge-modules',
'branch' => 'main',
'private' => true,
'personal_token' => env('AZURE_DEVOPS_TOKEN'),
],
// Self-hosted Git server
[
'name' => 'self-hosted-modules',
'url' => 'https://git.company.com/forge/modules',
'branch' => 'stable',
'private' => true,
'personal_token' => env('SELF_HOSTED_TOKEN'),
],
// Public community registry (no token needed)
[
'name' => 'community-contrib',
'url' => 'https://github.com/forge-community/contrib-modules',
'branch' => 'main',
'private' => false,
],
],
'cache_ttl' => 3600
];
Pro Tip: Use environment variables for tokens to keep sensitive
information out of your codebase. Add them to your .env file.
Private Registries: Ensure your personal access tokens have appropriate permissions for repository access.
package:install-module
Install a module from the configured registries. Features an interactive wizard that allows you to browse registries, select modules (single or multiple), choose versions (with commit messages for git-based registries), and configure installation options. Supports installing multiple modules via command-line arguments or multi-select wizard.
php forge.php package:install-module [--module=<module-name[@version]>] [module-name[@version] ...] [--force]
php forge.php package:install-module (interactive wizard)php forge.php package:install-module --module=forge-authphp forge.php package:install-module --module=forge-auth@1.2.0php forge.php package:install-module forge-auth forge-storage (multiple modules, latest versions)php forge.php package:install-module forge-auth@1.2.0 forge-storage (mixed versions)php forge.php package:install-module --module=forge-auth --forcepackage:remove-module
Remove an installed module from your application. Features an interactive wizard that displays all installed modules with their descriptions, making it easy to identify and select the module(s) to remove. Supports removing multiple modules via command-line arguments or multi-select wizard. Use --module= to skip the wizard.
php forge.php package:remove-module [--module=<module-name>] [module-name ...] [--force]
forge.json) when availablephp forge.php package:remove-module (interactive wizard)php forge.php package:remove-module --module=forge-authphp forge.php package:remove-module forge-auth forge-storage (multiple modules)php forge.php package:remove-module --module=forge-auth --forcephp forge.php package:remove-module forge-auth forge-storage --force (multiple with force)package:list-modules
List available or installed modules.
php forge.php package:list-modules
The lock file ensures reproducible installations by locking module versions and integrity hashes.
{
"modules": {
"ForgeAuth": {
"version": "1.2.0",
"url": "https://github.com/forge-engine/modules/archive/main/modules/ForgeAuth.zip",
"integrity": "sha256-abc123def456...",
"registry": "forge-engine-modules"
},
"ForgeUI": {
"version": "2.1.0",
"url": "https://github.com/forge-engine/modules/archive/main/modules/ForgeUI.zip",
"integrity": "sha256-def456ghi789...",
"registry": "forge-engine-modules"
},
"CustomModule": {
"version": "1.0.0",
"url": "https://github.com/mycompany/modules/archive/main/modules/CustomModule.zip",
"integrity": "sha256-ghi789jkl012...",
"registry": "my-company-modules"
}
},
"registries": {
"forge-engine-modules": {
"url": "https://github.com/forge-engine/modules",
"branch": "main"
},
"my-company-modules": {
"url": "https://github.com/mycompany/modules",
"branch": "main"
}
}
}
The forge-lock.json file is automatically generated when you install modules. It records:
You don't need to manually generate or manage the lock file — it's created and updated automatically during installation. To install from an existing lock file, use:
# Install all modules from forge-lock.json and scaffold app structure
php forge.php package:install-project
Best Practice: Commit your forge-lock.json file to
version control for consistent deployments across environments.
These are just suggestions based on what tends to work well. You do you. Build however makes sense for your project.
forge-lock.json to version control ensures consistencyA few things to keep in mind regarding security: