Initialize Nix overlay repository with blueprint, goose-cli, and docs
Add the complete overlay structure using numtide/blueprint with: - Two overlay strategies (default and shared-nixpkgs) - goose-cli package with custom librusty_v8 fetcher - Interactive package launcher via fzf - Flake input caching utility - Comprehensive README and AGENTS.md documentation
This commit is contained in:
273
AGENTS.md
Normal file
273
AGENTS.md
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
# AGENTS.md - Instructions for AI Agents
|
||||||
|
|
||||||
|
This file provides guidance to AI agents (such as Claude, GPT, Goose, etc.) when working with this Nix overlay repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
This is a **Nix flake overlay** repository that provides additional packages for Nix/NixOS users. It uses [numtide/blueprint](https://github.com/numtide/blueprint) as its foundation, which simplifies flake development by providing sensible defaults and automatic package discovery.
|
||||||
|
|
||||||
|
**Repository URL**: `git+https://git.millerson.name/alex/millerson-overlay.nix.git`
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
### Blueprint Framework
|
||||||
|
|
||||||
|
This project uses `numtide/blueprint` which:
|
||||||
|
- Automatically discovers packages in the `packages/` directory
|
||||||
|
- Provides `perSystem` outputs for multi-system builds
|
||||||
|
- Handles formatting, checking, and devShell generation
|
||||||
|
- Exposes `mkPackagesFor` function to build packages against any nixpkgs instance
|
||||||
|
|
||||||
|
### Two Overlay Strategies
|
||||||
|
|
||||||
|
1. **`overlays.default`** - Binary-cache-friendly
|
||||||
|
- Uses packages built against this flake's nixpkgs revision
|
||||||
|
- Better for binary cache hits when using the same nixpkgs
|
||||||
|
|
||||||
|
2. **`overlays.shared-nixpkgs`** - Dependency-sharing
|
||||||
|
- Builds packages against the consumer's nixpkgs (`final`)
|
||||||
|
- Shares dependencies with the rest of the system
|
||||||
|
- No second nixpkgs evaluation
|
||||||
|
- Trade-off: binary cache only hits when consumer's nixpkgs matches ours
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
nix-overlay/
|
||||||
|
├── flake.nix # Main flake definition with inputs and outputs
|
||||||
|
├── overlays/
|
||||||
|
│ ├── default.nix # Overlay using pre-built packages (binary cache friendly)
|
||||||
|
│ └── shared-nixpkgs.nix # Overlay building against consumer's nixpkgs
|
||||||
|
├── packages/
|
||||||
|
│ ├── default/ # Meta-package listing all visible packages
|
||||||
|
│ │ ├── default.nix
|
||||||
|
│ │ └── package.nix
|
||||||
|
│ ├── goose-cli/ # Example package: Goose AI agent CLI
|
||||||
|
│ │ ├── default.nix
|
||||||
|
│ │ ├── package.nix # Main package definition
|
||||||
|
│ │ ├── fetchers.nix # Custom fetchers (if needed)
|
||||||
|
│ │ ├── librusty_v8.nix # V8 library pre-built binary
|
||||||
|
│ │ └── update.py # Update script for version bumps
|
||||||
|
│ └── flake-inputs/ # Utility to cache all flake inputs
|
||||||
|
│ └── default.nix
|
||||||
|
├── README.md # User-facing documentation
|
||||||
|
├── AGENTS.md # This file - AI agent instructions
|
||||||
|
├── LICENSE
|
||||||
|
└── flake.lock
|
||||||
|
```
|
||||||
|
|
||||||
|
## Package Definition Pattern
|
||||||
|
|
||||||
|
### Standard Package Structure
|
||||||
|
|
||||||
|
Each package should follow this structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
packages/<package-name>/
|
||||||
|
├── default.nix # Wrapper that receives blueprint args (pkgs, perSystem, etc.)
|
||||||
|
└── package.nix # Actual package definition using pkgs.callPackage pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
### `default.nix` Pattern
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
perSystem,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
pkgs.callPackage ./package.nix {
|
||||||
|
# Pass any extra arguments here
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `package.nix` Pattern
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
# ... package-specific dependencies
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "my-package";
|
||||||
|
version = "1.0.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "user";
|
||||||
|
repo = "repo";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-...";
|
||||||
|
};
|
||||||
|
|
||||||
|
# ... build instructions
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Brief description";
|
||||||
|
homepage = "https://...";
|
||||||
|
license = licenses.mit;
|
||||||
|
maintainers = with maintainers; [ ];
|
||||||
|
platforms = platforms.all;
|
||||||
|
mainProgram = "program-name";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rust Packages
|
||||||
|
|
||||||
|
For Rust packages, use `rustPlatform.buildRustPackage`:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
rustPlatform,
|
||||||
|
fetchFromGitHub,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
|
||||||
|
rustPlatform.buildRustPackage rec {
|
||||||
|
pname = "my-rust-app";
|
||||||
|
version = "1.0.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub { ... };
|
||||||
|
|
||||||
|
cargoHash = "sha256-...";
|
||||||
|
|
||||||
|
# ... build instructions
|
||||||
|
|
||||||
|
meta = { ... };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding a New Package
|
||||||
|
|
||||||
|
When adding a new package:
|
||||||
|
|
||||||
|
1. **Create the directory**: `mkdir -p packages/<package-name>`
|
||||||
|
|
||||||
|
2. **Create `package.nix`** with the actual derivation
|
||||||
|
|
||||||
|
3. **Create `default.nix`** as a wrapper:
|
||||||
|
```nix
|
||||||
|
{ pkgs, ... }:
|
||||||
|
pkgs.callPackage ./package.nix { }
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Test the package**:
|
||||||
|
```bash
|
||||||
|
nix build .#<package-name>
|
||||||
|
nix run .#<package-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Update README.md** to document the new package in the Available Packages table
|
||||||
|
|
||||||
|
6. **Set appropriate metadata**:
|
||||||
|
- `meta.description` - Required, shown in package listings
|
||||||
|
- `meta.mainProgram` - Set for packages providing a CLI executable
|
||||||
|
- `meta.passthru.category` - Optional, used for organization (e.g., "AI Coding Agents")
|
||||||
|
- `meta.passthru.hideFromDocs` - Set to `true` to exclude from documentation
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Updating a Package Version
|
||||||
|
|
||||||
|
1. Update `version` in `package.nix`
|
||||||
|
2. Update `src.hash` (use `nix-prefetch-github` or let Nix tell you the correct hash)
|
||||||
|
3. Update `cargoHash` for Rust packages (build will fail and tell you the correct hash)
|
||||||
|
4. Test: `nix build .#<package-name>`
|
||||||
|
5. Update README if needed
|
||||||
|
|
||||||
|
### Testing Changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build specific package
|
||||||
|
nix build .#goose-cli
|
||||||
|
|
||||||
|
# Build all packages for current system
|
||||||
|
nix build .#packages
|
||||||
|
|
||||||
|
# Enter dev shell
|
||||||
|
nix develop
|
||||||
|
|
||||||
|
# Check formatting
|
||||||
|
nix flake check
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with Overlays
|
||||||
|
|
||||||
|
When modifying overlay behavior:
|
||||||
|
|
||||||
|
- **`overlays/default.nix`**: Receives `packages` from blueprint outputs, maps them to `final.stdenv.hostPlatform.system`
|
||||||
|
- **`overlays/shared-nixpkgs.nix`**: Receives `mkPackagesFor`, uses it to build against consumer's `final`
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
### Do's
|
||||||
|
|
||||||
|
- ✅ Use `pkgs.callPackage` pattern for package definitions
|
||||||
|
- ✅ Set proper `meta` attributes (description, license, homepage)
|
||||||
|
- ✅ Test packages with `nix build` before committing
|
||||||
|
- ✅ Use `passthru.category` for organizational grouping
|
||||||
|
- ✅ Follow Nixpkgs conventions for package naming and structure
|
||||||
|
|
||||||
|
### Don'ts
|
||||||
|
|
||||||
|
- ❌ Don't modify `flake.lock` manually - use `nix flake update`
|
||||||
|
- ❌ Don't hardcode system-specific paths or assumptions
|
||||||
|
- ❌ Don't forget to set `meta.mainProgram` for CLI tools
|
||||||
|
- ❌ Don't use `with pkgs;` at top level (can cause scope issues)
|
||||||
|
- ❌ Don't commit packages that don't build
|
||||||
|
|
||||||
|
## Debugging Tips
|
||||||
|
|
||||||
|
### Package Doesn't Build
|
||||||
|
|
||||||
|
1. Check the error message carefully
|
||||||
|
2. Verify all dependencies are listed
|
||||||
|
3. Check if the source hash is correct
|
||||||
|
4. For Rust packages, verify `cargoHash` matches
|
||||||
|
|
||||||
|
### Overlay Not Working
|
||||||
|
|
||||||
|
1. Verify the overlay is correctly imported
|
||||||
|
2. Check if the package exists in `packages` output
|
||||||
|
3. For `shared-nixpkgs`, ensure `mkPackagesFor` is available
|
||||||
|
|
||||||
|
### Binary Cache Issues
|
||||||
|
|
||||||
|
- The `default` overlay is more likely to get cache hits
|
||||||
|
- The `shared-nixpkgs` overlay builds from source unless nixpkgs revisions match
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Nixpkgs Manual](https://nixos.org/manual/nixpkgs/stable/)
|
||||||
|
- [Blueprint Documentation](https://github.com/numtide/blueprint)
|
||||||
|
- [Nix Flake Patterns](https://github.com/NixOS/flake-patterns)
|
||||||
|
- [Rust in Nixpkgs](https://nixos.org/manual/nixpkgs/stable/#rust)
|
||||||
|
|
||||||
|
## Example Workflow: Adding a New Package
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Create package directory
|
||||||
|
mkdir -p packages/my-tool
|
||||||
|
|
||||||
|
# 2. Create package.nix (use appropriate template above)
|
||||||
|
|
||||||
|
# 3. Create default.nix wrapper
|
||||||
|
cat > packages/my-tool/default.nix << 'EOF'
|
||||||
|
{ pkgs, ... }:
|
||||||
|
pkgs.callPackage ./package.nix { }
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 4. Test build
|
||||||
|
nix build .#my-tool
|
||||||
|
|
||||||
|
# 5. If build fails, fix issues, then retry
|
||||||
|
|
||||||
|
# 6. Update README.md with new package info
|
||||||
|
|
||||||
|
# 7. Commit changes
|
||||||
|
git add packages/my-tool README.md
|
||||||
|
git commit -m "Add my-tool package"
|
||||||
|
```
|
||||||
127
README.md
127
README.md
@@ -1,2 +1,127 @@
|
|||||||
# nix-overlay
|
# millerson.name Nix Overlay
|
||||||
|
|
||||||
|
A custom Nix overlay and flake providing additional packages not found in upstream nixpkgs, built using [numtide/blueprint](https://github.com/numtide/blueprint) for streamlined flake development.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Custom packages** - Additional software packaged for Nix
|
||||||
|
- **Two overlay strategies** - Choose between binary-cache-friendly or dependency-sharing overlays
|
||||||
|
- **Blueprint-based** - Uses modern Nix flake patterns with `numtide/blueprint`
|
||||||
|
|
||||||
|
## Available Packages
|
||||||
|
|
||||||
|
| Package | Description | Category |
|
||||||
|
|---------|-------------|----------|
|
||||||
|
| `goose-cli` | CLI for Goose - a local, extensible, open source AI agent that automates engineering tasks | AI Coding Agents |
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### As a Flake
|
||||||
|
|
||||||
|
Add to your `flake.nix` inputs:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
inputs.millerson-nix-overlay.url = "git+https://git.millerson.name/alex/millerson-overlay.nix.git";
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use in your outputs:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
outputs = { nixpkgs, millerson-nix-overlay, ... }: {
|
||||||
|
nixosConfigurations.your-host = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
modules = [
|
||||||
|
millerson-nix-overlay.nixosModules.default
|
||||||
|
# ... your other modules
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### As an Overlay
|
||||||
|
|
||||||
|
#### Option 1: Default Overlay (Binary Cache Friendly)
|
||||||
|
|
||||||
|
Uses the packages built against this flake's nixpkgs revision. Binary cache hits work best when using the same nixpkgs revision.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
nixpkgs.overlays = [ millerson-nix-overlay.overlays.default ];
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: Shared Nixpkgs Overlay (Dependency Sharing)
|
||||||
|
|
||||||
|
Builds packages against your system's nixpkgs, sharing dependencies with the rest of your system. No second nixpkgs evaluation, but binary cache only hits when your nixpkgs revision matches ours.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
nixpkgs.overlays = [ millerson-nix-overlay.overlays.shared-nixpkgs ];
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installing Packages
|
||||||
|
|
||||||
|
With flakes enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Try a package
|
||||||
|
nix run git+https://git.millerson.name/alex/millerson-overlay.nix.git#goose-cli
|
||||||
|
|
||||||
|
# Install permanently
|
||||||
|
nix profile install git+https://git.millerson.name/alex/millerson-overlay.nix.git#goose-cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Nix with flakes enabled
|
||||||
|
- [treefmt-nix](https://github.com/numtide/treefmt-nix) for formatting (optional)
|
||||||
|
|
||||||
|
### Building Packages
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build all packages for current system
|
||||||
|
nix build .#packages
|
||||||
|
|
||||||
|
# Build specific package
|
||||||
|
nix build .#goose-cli
|
||||||
|
|
||||||
|
# Enter development shell
|
||||||
|
nix develop
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
nix-overlay/
|
||||||
|
├── flake.nix # Flake definition
|
||||||
|
├── overlays/ # Overlay implementations
|
||||||
|
│ ├── default.nix # Binary-cache-friendly overlay
|
||||||
|
│ └── shared-nixpkgs.nix # Dependency-sharing overlay
|
||||||
|
├── packages/ # Package definitions
|
||||||
|
│ ├── default/ # Meta-package listing all packages
|
||||||
|
│ ├── goose-cli/ # Goose CLI package
|
||||||
|
│ └── flake-inputs/ # Utility for caching flake inputs
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding New Packages
|
||||||
|
|
||||||
|
1. Create a new directory under `packages/<package-name>/`
|
||||||
|
2. Add a `package.nix` with the package definition
|
||||||
|
3. Create a `default.nix` that imports `package.nix` with proper arguments
|
||||||
|
4. The package will be automatically picked up by blueprint
|
||||||
|
|
||||||
|
Example structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
packages/my-package/
|
||||||
|
├── default.nix # Import wrapper
|
||||||
|
└── package.nix # Actual package definition
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
See [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|||||||
140
flake.lock
generated
Normal file
140
flake.lock
generated
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"blueprint": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1776249299,
|
||||||
|
"narHash": "sha256-Dt9t1TGRmJFc0xVYhttNBD6QsAgHOHCArqGa0AyjrJY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "blueprint",
|
||||||
|
"rev": "56131e8628f173d24a27f6d27c0215eff57e40dd",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "blueprint",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bun2nix": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": [
|
||||||
|
"flake-parts"
|
||||||
|
],
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
],
|
||||||
|
"systems": [
|
||||||
|
"systems"
|
||||||
|
],
|
||||||
|
"treefmt-nix": [
|
||||||
|
"treefmt-nix"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1777369708,
|
||||||
|
"narHash": "sha256-1xW7cRZNsFNPQD+cE0fwnLVStnDth0HSoASEIFeT7uI=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "bun2nix",
|
||||||
|
"rev": "e659e1cc4b8e1b21d0aa85f1c481f9db61ecfa98",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"ref": "staging-2.1.0",
|
||||||
|
"repo": "bun2nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1775087534,
|
||||||
|
"narHash": "sha256-91qqW8lhL7TLwgQWijoGBbiD4t7/q75KTi8NxjVmSmA=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "3107b77cd68437b9a76194f0f7f9c55f2329ca5b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1777270315,
|
||||||
|
"narHash": "sha256-yKB4G6cKsQsWN7M6rZGk6gkJPDNPIzT05y4qzRyCDlI=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "6368eda62c9775c38ef7f714b2555a741c20c72d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"blueprint": "blueprint",
|
||||||
|
"bun2nix": "bun2nix",
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"systems": "systems",
|
||||||
|
"treefmt-nix": "treefmt-nix"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"treefmt-nix": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1775636079,
|
||||||
|
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "treefmt-nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
51
flake.nix
Normal file
51
flake.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
description = "Various packages for Nix";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
blueprint = {
|
||||||
|
url = "github:numtide/blueprint";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
|
};
|
||||||
|
treefmt-nix = {
|
||||||
|
url = "github:numtide/treefmt-nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
flake-parts = {
|
||||||
|
url = "github:hercules-ci/flake-parts";
|
||||||
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
bun2nix = {
|
||||||
|
# TODO(#4001): drop the branch pin once catalog support
|
||||||
|
# (nix-community/bun2nix#86) reaches the default branch.
|
||||||
|
url = "github:nix-community/bun2nix/staging-2.1.0";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
inputs.systems.follows = "systems";
|
||||||
|
inputs.treefmt-nix.follows = "treefmt-nix";
|
||||||
|
inputs.flake-parts.follows = "flake-parts";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
inputs:
|
||||||
|
let
|
||||||
|
blueprintOutputs = inputs.blueprint {
|
||||||
|
inherit inputs;
|
||||||
|
nixpkgs.config.allowUnfree = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
blueprintOutputs
|
||||||
|
// {
|
||||||
|
overlays = {
|
||||||
|
default = import ./overlays {
|
||||||
|
inherit (blueprintOutputs) packages;
|
||||||
|
};
|
||||||
|
shared-nixpkgs = import ./overlays/shared-nixpkgs.nix {
|
||||||
|
inherit (blueprintOutputs) mkPackagesFor;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
6
overlays/default.nix
Normal file
6
overlays/default.nix
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
packages,
|
||||||
|
}:
|
||||||
|
final: _prev: {
|
||||||
|
millerson-nix-overlay = packages.${final.stdenv.hostPlatform.system} or { };
|
||||||
|
}
|
||||||
10
overlays/shared-nixpkgs.nix
Normal file
10
overlays/shared-nixpkgs.nix
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
mkPackagesFor,
|
||||||
|
}:
|
||||||
|
# Builds the packages/ tree against the consumer's `final`, so deps are
|
||||||
|
# shared with the rest of their system and no second nixpkgs is
|
||||||
|
# evaluated. Trade-off vs overlays.default: the binary cache only hits
|
||||||
|
# when the consumer's nixpkgs revision matches ours.
|
||||||
|
final: _prev: {
|
||||||
|
millerson-nix-overlay = mkPackagesFor final;
|
||||||
|
}
|
||||||
19
packages/default/default.nix
Normal file
19
packages/default/default.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
perSystem,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
allPackages = perSystem.self;
|
||||||
|
|
||||||
|
# Filter to visible, runnable packages
|
||||||
|
visibleNames = builtins.filter (
|
||||||
|
name: name != "default" && !(allPackages.${name}.passthru.hideFromDocs or false)
|
||||||
|
) (builtins.attrNames allPackages);
|
||||||
|
|
||||||
|
# Build "name\tdescription" lines
|
||||||
|
packageLines = map (name: "${name}\t${allPackages.${name}.meta.description or ""}") visibleNames;
|
||||||
|
|
||||||
|
packageList = builtins.concatStringsSep "\n" packageLines;
|
||||||
|
in
|
||||||
|
pkgs.callPackage ./package.nix { inherit packageList; }
|
||||||
60
packages/default/package.nix
Normal file
60
packages/default/package.nix
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
writeShellApplication,
|
||||||
|
fzf,
|
||||||
|
nix,
|
||||||
|
util-linux,
|
||||||
|
packageList,
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
packageListFile = builtins.toFile "millerson-overlay-packages.tsv" packageList;
|
||||||
|
in
|
||||||
|
writeShellApplication {
|
||||||
|
name = "millerson-overlay-launcher";
|
||||||
|
|
||||||
|
runtimeInputs = [
|
||||||
|
fzf
|
||||||
|
nix
|
||||||
|
util-linux # column
|
||||||
|
];
|
||||||
|
|
||||||
|
text = ''
|
||||||
|
# Format for fzf: "name description" (tab-aligned)
|
||||||
|
entries=$(column -t -s $'\t' < "${packageListFile}")
|
||||||
|
|
||||||
|
if [[ -z $entries ]]; then
|
||||||
|
echo "No packages found" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Let user pick with fzf
|
||||||
|
selected=$(echo "$entries" | fzf \
|
||||||
|
--header="Select an pkg to run (ESC to cancel)" \
|
||||||
|
--preview-window=hidden \
|
||||||
|
--no-multi \
|
||||||
|
--height=~40% \
|
||||||
|
--layout=reverse) || exit 0
|
||||||
|
|
||||||
|
# Extract package name (first word)
|
||||||
|
pkg_name=$(echo "$selected" | awk '{print $1}')
|
||||||
|
|
||||||
|
if [[ -z $pkg_name ]]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "→ Running: nix run git.millerson.name/alex/nix-overlay.git#$pkg_name"
|
||||||
|
exec nix run "git.millerson.name/alex/nix-overlay.git#$pkg_name"
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Interactive fzf launcher for millerson-overlay.nix packages";
|
||||||
|
license = licenses.mit;
|
||||||
|
mainProgram = "millerson-overlay-launcher";
|
||||||
|
platforms = platforms.all;
|
||||||
|
};
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
hideFromDocs = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
12
packages/flake-inputs/default.nix
Normal file
12
packages/flake-inputs/default.nix
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
inputs,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
# A derivation that references all flake inputs to ensure they get cached
|
||||||
|
pkgs.runCommand "flake-inputs" { } ''
|
||||||
|
echo ${pkgs.lib.concatMapStringsSep " " (name: inputs.${name}) (builtins.attrNames inputs)} > $out
|
||||||
|
''
|
||||||
|
// {
|
||||||
|
passthru.hideFromDocs = true;
|
||||||
|
}
|
||||||
9
packages/goose-cli/default.nix
Normal file
9
packages/goose-cli/default.nix
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
pkgs.callPackage ./package.nix {
|
||||||
|
librusty_v8 = pkgs.callPackage ./librusty_v8.nix {
|
||||||
|
inherit (pkgs.callPackage ./fetchers.nix { }) fetchLibrustyV8;
|
||||||
|
};
|
||||||
|
}
|
||||||
21
packages/goose-cli/fetchers.nix
Normal file
21
packages/goose-cli/fetchers.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Fetchers for goose-cli pre-built dependencies
|
||||||
|
# Based on deno's approach for handling rusty_v8
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
fetchurl,
|
||||||
|
}:
|
||||||
|
|
||||||
|
{
|
||||||
|
fetchLibrustyV8 =
|
||||||
|
args:
|
||||||
|
fetchurl {
|
||||||
|
name = "librusty_v8-${args.version}";
|
||||||
|
url = "https://github.com/denoland/rusty_v8/releases/download/v${args.version}/librusty_v8_release_${stdenv.hostPlatform.rust.rustcTarget}.a.gz";
|
||||||
|
sha256 = args.shas.${stdenv.hostPlatform.system};
|
||||||
|
meta = {
|
||||||
|
inherit (args) version;
|
||||||
|
sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
packages/goose-cli/librusty_v8.nix
Normal file
13
packages/goose-cli/librusty_v8.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Pre-built librusty_v8 library for goose-cli
|
||||||
|
# This file specifies the rusty_v8 version and hashes for all supported platforms
|
||||||
|
{ fetchLibrustyV8 }:
|
||||||
|
|
||||||
|
fetchLibrustyV8 {
|
||||||
|
version = "145.0.0";
|
||||||
|
shas = {
|
||||||
|
x86_64-linux = "sha256-chV1PAx40UH3Ute5k3lLrgfhih39Rm3KqE+mTna6ysE=";
|
||||||
|
aarch64-linux = "sha256-4IivYskhUSsMLZY97+g23UtUYh4p5jk7CzhMbMyqXyY=";
|
||||||
|
x86_64-darwin = "sha256-1jUuC+z7saQfPYILNyRJanD4+zOOhXU2ac/LFoytwho=";
|
||||||
|
aarch64-darwin = "sha256-yHa1eydVCrfYGgrZANbzgmmf25p7ui1VMas2A7BhG6k=";
|
||||||
|
};
|
||||||
|
}
|
||||||
71
packages/goose-cli/package.nix
Normal file
71
packages/goose-cli/package.nix
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
fetchFromGitHub,
|
||||||
|
rustPlatform,
|
||||||
|
pkg-config,
|
||||||
|
openssl,
|
||||||
|
libxcb,
|
||||||
|
dbus,
|
||||||
|
versionCheckHook,
|
||||||
|
librusty_v8,
|
||||||
|
}:
|
||||||
|
|
||||||
|
rustPlatform.buildRustPackage rec {
|
||||||
|
pname = "goose-cli";
|
||||||
|
version = "1.33.1";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "block";
|
||||||
|
repo = "goose";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-FBICGOfVs2jbOdLWSInqfTYBdnCcbcGWHwqY/b6v8eg=";
|
||||||
|
};
|
||||||
|
|
||||||
|
cargoHash = "sha256-fN0FKDYFkZrQQPWdUlemOaGzIAZhqFyskz9TEmG+X4o=";
|
||||||
|
|
||||||
|
nativeBuildInputs = [ pkg-config ];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
openssl
|
||||||
|
libxcb
|
||||||
|
dbus
|
||||||
|
];
|
||||||
|
|
||||||
|
# The v8 package will try to download a `librusty_v8.a` release at build time to our read-only filesystem
|
||||||
|
# To avoid this we pre-download the file and export it via RUSTY_V8_ARCHIVE
|
||||||
|
env.RUSTY_V8_ARCHIVE = librusty_v8;
|
||||||
|
|
||||||
|
# Build only the CLI package
|
||||||
|
cargoBuildFlags = [
|
||||||
|
"--package"
|
||||||
|
"goose-cli"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Enable tests with proper environment
|
||||||
|
doCheck = true;
|
||||||
|
checkPhase = ''
|
||||||
|
export HOME=$(mktemp -d)
|
||||||
|
export XDG_CONFIG_HOME=$HOME/.config
|
||||||
|
export XDG_DATA_HOME=$HOME/.local/share
|
||||||
|
export XDG_STATE_HOME=$HOME/.local/state
|
||||||
|
export XDG_CACHE_HOME=$HOME/.cache
|
||||||
|
mkdir -p $XDG_CONFIG_HOME $XDG_DATA_HOME $XDG_STATE_HOME $XDG_CACHE_HOME
|
||||||
|
|
||||||
|
# Run tests for goose-cli package only
|
||||||
|
cargo test --package goose-cli --release
|
||||||
|
'';
|
||||||
|
|
||||||
|
doInstallCheck = true;
|
||||||
|
nativeInstallCheckInputs = [ versionCheckHook ];
|
||||||
|
|
||||||
|
passthru.category = "AI Coding Agents";
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "CLI for Goose - a local, extensible, open source AI agent that automates engineering tasks";
|
||||||
|
homepage = "https://github.com/block/goose";
|
||||||
|
changelog = "https://github.com/block/goose/releases/tag/v${version}";
|
||||||
|
license = licenses.asl20;
|
||||||
|
sourceProvenance = with sourceTypes; [ fromSource ];
|
||||||
|
mainProgram = "goose";
|
||||||
|
};
|
||||||
|
}
|
||||||
107
packages/goose-cli/update.py
Executable file
107
packages/goose-cli/update.py
Executable file
@@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env nix
|
||||||
|
#! nix shell --inputs-from .# nixpkgs#python3 --command python3
|
||||||
|
|
||||||
|
"""Update script for goose-cli package.
|
||||||
|
|
||||||
|
This script updates both the goose-cli version and the librusty_v8 hashes.
|
||||||
|
The v8 version is extracted from the Cargo.lock file of the goose repository.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "scripts"))
|
||||||
|
|
||||||
|
from updater import (
|
||||||
|
calculate_platform_hashes,
|
||||||
|
fetch_text,
|
||||||
|
load_hashes,
|
||||||
|
save_hashes,
|
||||||
|
)
|
||||||
|
|
||||||
|
HASHES_FILE = Path(__file__).parent / "librusty_v8_hashes.json"
|
||||||
|
|
||||||
|
PLATFORMS = {
|
||||||
|
"x86_64-linux": "x86_64-unknown-linux-gnu",
|
||||||
|
"aarch64-linux": "aarch64-unknown-linux-gnu",
|
||||||
|
"x86_64-darwin": "x86_64-apple-darwin",
|
||||||
|
"aarch64-darwin": "aarch64-apple-darwin",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_v8_version_from_cargo_lock(goose_version: str) -> str:
|
||||||
|
"""Extract the v8 version from goose's Cargo.lock file."""
|
||||||
|
url = f"https://raw.githubusercontent.com/block/goose/v{goose_version}/Cargo.lock"
|
||||||
|
cargo_lock = fetch_text(url)
|
||||||
|
|
||||||
|
# Parse the Cargo.lock to find v8 version
|
||||||
|
lines = cargo_lock.split("\n")
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.strip() == 'name = "v8"':
|
||||||
|
# Look for version in the next few lines
|
||||||
|
for j in range(i + 1, min(i + 10, len(lines))):
|
||||||
|
if "version = " in lines[j]:
|
||||||
|
return lines[j].split('"')[1]
|
||||||
|
|
||||||
|
msg = "Could not find v8 version in Cargo.lock"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Update the librusty_v8 hashes for goose-cli."""
|
||||||
|
# Read the current goose-cli version from package.nix
|
||||||
|
package_nix = (Path(__file__).parent / "package.nix").read_text()
|
||||||
|
for line in package_nix.split("\n"):
|
||||||
|
if "version = " in line and '"' in line:
|
||||||
|
goose_version = line.split('"')[1]
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
msg = "Could not find version in package.nix"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
print(f"Goose version: {goose_version}")
|
||||||
|
|
||||||
|
# Get the v8 version from Cargo.lock
|
||||||
|
v8_version = fetch_v8_version_from_cargo_lock(goose_version)
|
||||||
|
print(f"V8 version: {v8_version}")
|
||||||
|
|
||||||
|
# Check if we need to update
|
||||||
|
try:
|
||||||
|
data = load_hashes(HASHES_FILE)
|
||||||
|
current_v8 = data.get("version", "")
|
||||||
|
if current_v8 == v8_version:
|
||||||
|
print(f"V8 hashes already up to date ({v8_version})")
|
||||||
|
return
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("No existing hashes file, creating new one")
|
||||||
|
|
||||||
|
# Calculate hashes for all platforms
|
||||||
|
url_template = f"https://github.com/denoland/rusty_v8/releases/download/v{v8_version}/librusty_v8_release_{{platform}}.a.gz"
|
||||||
|
hashes = calculate_platform_hashes(url_template, PLATFORMS)
|
||||||
|
|
||||||
|
# Save the hashes
|
||||||
|
save_hashes(HASHES_FILE, {"version": v8_version, "hashes": hashes})
|
||||||
|
|
||||||
|
# Update librusty_v8.nix
|
||||||
|
librusty_v8_nix = Path(__file__).parent / "librusty_v8.nix"
|
||||||
|
content = f"""# Pre-built librusty_v8 library for goose-cli
|
||||||
|
# This file specifies the rusty_v8 version and hashes for all supported platforms
|
||||||
|
{{ fetchLibrustyV8 }}:
|
||||||
|
|
||||||
|
fetchLibrustyV8 {{
|
||||||
|
version = "{v8_version}";
|
||||||
|
shas = {{
|
||||||
|
x86_64-linux = "{hashes["x86_64-linux"]}";
|
||||||
|
aarch64-linux = "{hashes["aarch64-linux"]}";
|
||||||
|
x86_64-darwin = "{hashes["x86_64-darwin"]}";
|
||||||
|
aarch64-darwin = "{hashes["aarch64-darwin"]}";
|
||||||
|
}};
|
||||||
|
}}
|
||||||
|
"""
|
||||||
|
librusty_v8_nix.write_text(content)
|
||||||
|
|
||||||
|
print(f"Updated librusty_v8 to {v8_version}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user