docs: update zellij-ps to reflect project switcher functionality
- Update package description and fix mainProgram typo - Rewrite documentation to describe project switching, not process viewing - Add PROJECT_FOLDERS configuration and usage examples - Update all references across docs (README, guides, module overviews)
This commit is contained in:
493
docs/guides/adding-packages.md
Normal file
493
docs/guides/adding-packages.md
Normal file
@@ -0,0 +1,493 @@
|
||||
# Adding Packages Guide
|
||||
|
||||
How to add new packages to m3ta-nixpkgs.
|
||||
|
||||
## Overview
|
||||
|
||||
Packages in m3ta-nixpkgs are organized using a `callPackage` registry pattern. Each package lives in its own directory and is registered centrally.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Templates
|
||||
|
||||
Use the package template for quick setup:
|
||||
|
||||
```bash
|
||||
nix flake init -t .#package my-new-package
|
||||
```
|
||||
|
||||
This creates a template structure in `templates/package/` that you can copy.
|
||||
|
||||
### Manual Setup
|
||||
|
||||
1. Create directory: `pkgs/your-package/`
|
||||
2. Write `default.nix` with package definition
|
||||
3. Register in `pkgs/default.nix`
|
||||
|
||||
## Package Structure
|
||||
|
||||
```
|
||||
pkgs/your-package/
|
||||
├── default.nix # Package definition (required)
|
||||
├── source.py # Optional: additional source files
|
||||
├── wrapper.sh # Optional: wrapper scripts
|
||||
└── README.md # Optional: package documentation
|
||||
```
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Rust Package
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
rustPlatform,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
rustPlatform.buildRustPackage rec {
|
||||
pname = "my-rust-app";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "author";
|
||||
repo = "my-rust-app";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
cargoLock.lockFile = src + "/Cargo.lock";
|
||||
|
||||
buildInputs = [openssl];
|
||||
|
||||
nativeBuildInputs = [pkg-config];
|
||||
|
||||
meta = with lib; {
|
||||
description = "My Rust application";
|
||||
homepage = "https://github.com/author/my-rust-app";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "my-rust-app";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Python Package
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
python3,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
python3.pkgs.buildPythonPackage rec {
|
||||
pname = "my-python-app";
|
||||
version = "1.0.0";
|
||||
pyproject = true;
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "author";
|
||||
repo = "my-python-app";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
build-system = with python3.pkgs; [setuptools];
|
||||
|
||||
dependencies = with python3.pkgs; [
|
||||
requests
|
||||
click
|
||||
];
|
||||
|
||||
optional-dependencies = with python3.pkgs; {
|
||||
extras = [pyyaml];
|
||||
};
|
||||
|
||||
doCheck = true;
|
||||
|
||||
pythonImportsCheck = ["myapp"];
|
||||
|
||||
meta = with lib; {
|
||||
description = "My Python application";
|
||||
homepage = "https://github.com/author/my-python-app";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "my-app";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Shell Script Package
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
writeShellScriptBin,
|
||||
}:
|
||||
writeShellScriptBin "my-script" ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "Hello from my script!"
|
||||
|
||||
# Your script logic here
|
||||
''
|
||||
|
||||
# If you need to add dependencies
|
||||
{
|
||||
lib,
|
||||
writeShellApplication,
|
||||
bash,
|
||||
curl,
|
||||
}:
|
||||
writeShellApplication {
|
||||
name = "my-script";
|
||||
runtimeInputs = [bash curl];
|
||||
text = ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
curl -s https://example.com
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
### AppImage Package
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
appimageTools,
|
||||
fetchurl,
|
||||
}:
|
||||
appimageTools.wrapType2 rec {
|
||||
name = "my-app";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchurl {
|
||||
url = "https://github.com/author/my-app/releases/download/v${version}/My-App-${version}.AppImage";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
meta = with lib; {
|
||||
description = "My AppImage application";
|
||||
homepage = "https://github.com/author/my-app";
|
||||
license = licenses.unfree;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = name;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Custom Source with Patch
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
fetchpatch,
|
||||
buildGoModule,
|
||||
}:
|
||||
buildGoModule rec {
|
||||
pname = "my-go-app";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "author";
|
||||
repo = "my-go-app";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Add local patch
|
||||
./fix-build.patch
|
||||
|
||||
# Add patch from URL
|
||||
(fetchpatch {
|
||||
url = "https://github.com/author/my-app/pull/123.patch";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
})
|
||||
];
|
||||
|
||||
vendorHash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
|
||||
|
||||
meta = with lib; {
|
||||
description = "My Go application";
|
||||
homepage = "https://github.com/author/my-go-app";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "my-app";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Package with Custom Installation
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
makeWrapper,
|
||||
}:
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "my-app";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "author";
|
||||
repo = "my-app";
|
||||
rev = "v${version}";
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [makeWrapper];
|
||||
|
||||
buildPhase = ''
|
||||
make build
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
install -Dm755 my-app $out/bin/my-app
|
||||
|
||||
# Wrap with runtime dependencies
|
||||
wrapProgram $out/bin/my-app \
|
||||
--prefix PATH : ${lib.makeBinPath [some-dep]}
|
||||
'';
|
||||
|
||||
meta = with lib; {
|
||||
description = "My custom application";
|
||||
homepage = "https://github.com/author/my-app";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "my-app";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Registration
|
||||
|
||||
### Register in `pkgs/default.nix`
|
||||
|
||||
Add your package to the registry:
|
||||
|
||||
```nix
|
||||
{
|
||||
inherit (pkgs) callPackage;
|
||||
} rec {
|
||||
# Existing packages
|
||||
code2prompt = callPackage ./code2prompt {};
|
||||
zellij-ps = callPackage ./zellij-ps {};
|
||||
|
||||
# Your new package
|
||||
my-new-package = callPackage ./my-new-package {};
|
||||
}
|
||||
```
|
||||
|
||||
### With Custom Arguments
|
||||
|
||||
If your package needs custom arguments:
|
||||
|
||||
```nix
|
||||
# pkgs/default.nix
|
||||
{
|
||||
inherit (pkgs) callPackage;
|
||||
} rec {
|
||||
my-new-package = callPackage ./my-new-package {
|
||||
customArg = "value";
|
||||
};
|
||||
}
|
||||
|
||||
# pkgs/my-new-package/default.nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
customArg, # This will be passed from the registry
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
## Getting Hashes
|
||||
|
||||
### Using `lib.fakeHash`
|
||||
|
||||
During development, use `lib.fakeHash` to get the real hash:
|
||||
|
||||
```nix
|
||||
src = fetchFromGitHub {
|
||||
owner = "author";
|
||||
repo = "my-app";
|
||||
rev = "v${version}";
|
||||
hash = lib.fakeHash; # Temporary placeholder
|
||||
};
|
||||
```
|
||||
|
||||
Build the package:
|
||||
|
||||
```bash
|
||||
nix build .#my-new-package
|
||||
```
|
||||
|
||||
Copy the actual hash from the error message and update the package:
|
||||
|
||||
```nix
|
||||
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Real hash
|
||||
```
|
||||
|
||||
**Important**: Never commit `lib.fakeHash` to the repository.
|
||||
|
||||
## Testing
|
||||
|
||||
### Build Package
|
||||
|
||||
```bash
|
||||
nix build .#my-new-package
|
||||
```
|
||||
|
||||
### Test Execution
|
||||
|
||||
```bash
|
||||
nix run .#my-new-package -- --help
|
||||
```
|
||||
|
||||
### Run in Shell
|
||||
|
||||
```bash
|
||||
nix shell .#my-new-package
|
||||
my-new-app --version
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
```bash
|
||||
nix develop
|
||||
statix check pkgs/my-new-package/
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Meta Fields
|
||||
|
||||
Always include complete `meta` information:
|
||||
|
||||
```nix
|
||||
meta = with lib; {
|
||||
description = "Short one-line description";
|
||||
longDescription = ''
|
||||
Longer description explaining what the package does,
|
||||
its features, and use cases.
|
||||
'';
|
||||
homepage = "https://github.com/author/repo";
|
||||
changelog = "https://github.com/author/repo/releases/tag/v${version}";
|
||||
license = licenses.mit;
|
||||
platforms = platforms.linux;
|
||||
mainProgram = "program-name";
|
||||
};
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
Explicitly declare all dependencies:
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
# Runtime dependencies
|
||||
openssl,
|
||||
curl,
|
||||
# Native build dependencies
|
||||
pkg-config,
|
||||
cmake,
|
||||
}:
|
||||
```
|
||||
|
||||
### Versioning
|
||||
|
||||
Use `rec` to reference `version` in multiple places:
|
||||
|
||||
```nix
|
||||
rec {
|
||||
pname = "my-app";
|
||||
version = "1.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
rev = "v${version}";
|
||||
# ...
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Platform Restrictions
|
||||
|
||||
If package is platform-specific:
|
||||
|
||||
```nix
|
||||
meta = with lib; {
|
||||
# Linux only
|
||||
platforms = platforms.linux;
|
||||
|
||||
# Or specific platforms
|
||||
platforms = ["x86_64-linux" "aarch64-linux"];
|
||||
|
||||
# Or exclude platforms
|
||||
broken = stdenv.isDarwin;
|
||||
};
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Hash Mismatch
|
||||
|
||||
Error: `got: sha256-AAAAAAAA... expected: sha256-BBBBBB...`
|
||||
|
||||
Solution: Copy `got` hash and update package definition.
|
||||
|
||||
### Dependency Not Found
|
||||
|
||||
Error: `error: undefined variable 'somedep'`
|
||||
|
||||
Solution: Add dependency to function arguments and build inputs:
|
||||
|
||||
```nix
|
||||
{
|
||||
lib,
|
||||
somedep, # Add here
|
||||
}:
|
||||
stdenv.mkDerivation {
|
||||
buildInputs = [somedep]; # Add here
|
||||
}
|
||||
```
|
||||
|
||||
### Import Check Failure
|
||||
|
||||
Error: `error: Python module 'mymodule' not found`
|
||||
|
||||
Solution: Disable or fix imports check:
|
||||
|
||||
```nix
|
||||
pythonImportsCheck = ["mymodule"]; # Check this is correct
|
||||
# Or if importing creates side effects:
|
||||
pythonImportsCheck = [];
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
See existing packages in the repository:
|
||||
|
||||
- `pkgs/code2prompt/` - Rust package
|
||||
- `pkgs/mem0/` - Python package
|
||||
- `pkgs/hyprpaper-random/` - Shell script
|
||||
- `pkgs/msty-studio/` - AppImage
|
||||
- `pkgs/zellij-ps/` - Fetch from Gitea
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Architecture](../ARCHITECTURE.md) - Understanding package organization
|
||||
- [Using Modules](./using-modules.md) - If you need to create modules
|
||||
- [Contributing](../CONTRIBUTING.md) - Code style and guidelines
|
||||
Reference in New Issue
Block a user