Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,28 @@ jobs:
run: cargo test --all-targets --all-features
- name: Run Clippy
run: cargo clippy --all-targets --all-features
- name: Install AppStream tooling
run: sudo apt-get update && sudo apt-get install -y appstream
- name: Validate generated AppStream metadata
run: |
mkdir -p /tmp/appstream-ci/source/.npack
cat > /tmp/appstream-ci/source/.npack/manifest.json <<'EOF'
{
"publisher": "483440dfc4efeb8776ca27413c929653ea60484ca2d0e6b97678a0622c6bf413",
"name": "npack",
"version": "0.0.0",
"artifact": "ci.npk",
"sha256": "",
"app": {
"summary": "A Nostr-native package manager",
"description": "npack discovers, verifies, and installs signed release artifacts published on Nostr and stored on Blossom.",
"homepage": "https://github.com/imattau/npack",
"license": "MIT",
"categories": ["System"],
"release_date": "2026-01-01"
}
}
EOF
cargo run --quiet -- pack /tmp/appstream-ci/source --output /tmp/appstream-ci/ci.npk
cargo run --quiet -- appstream /tmp/appstream-ci/ci.npk --output /tmp/appstream-ci/ci.metainfo.xml
appstreamcli validate --no-net /tmp/appstream-ci/ci.metainfo.xml
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ npack is an independent package manager whose registry metadata will be publishe
npack pack <source-directory> --output <package.npk>
npack remove <publisher>/<name> [--user|--system] [--store <path>]
npack inspect <artifact>
npack appstream <artifact> [--output <metainfo.xml>]

## Conventions

Expand All @@ -43,3 +44,5 @@ npack is an independent package manager whose registry metadata will be publishe
- register-service is approved by the service-manager capability and installs a system or user systemd unit without enabling or starting it.
- `npack resolve` performs the same relay discovery, trust/semver/os-arch filtering, revocation check, and NIP-94 verification as `npack install-ref`, but stops before downloading the artifact or installing anything, printing the resolved metadata as JSON for declarative package managers (e.g. Nix) to consume. `--recursive` walks and resolves the full declared dependency closure in one call, printing a JSON array instead of a single object.
- `npack update --check` (alias of `install-ref --check`) reports available updates for one or all installed packages without downloading or installing anything, the `apt update` counterpart to `update`'s `apt upgrade`.
- A manifest's optional `app` object (`summary`, `description`, `homepage`, `license`, `categories`, `icon`, `screenshots`, `desktop_file`, `release_date`) carries desktop-store metadata; `icon` and `desktop_file` are package-relative paths validated to exist and, for `desktop_file`, to be a syntactically valid freedesktop.org Desktop Entry file with `Exec` required when `Type=Application`.
- `npack appstream` maps a manifest's `app` metadata to an AppStream `<component>` document per the freedesktop.org AppStream spec: `console-application` when there is no `desktop_file` (advertising `<provides><binary>`), `desktop-application` otherwise (advertising `<launchable type="desktop-id">`). Component IDs are namespaced `io.npack.<publisher>.<name>` since publishers are Nostr pubkeys, not domains.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ npack manifest ./myapp-1.0.0.npk --output ./myapp-1.0.0.manifest.json
npack hash ./myapp-1.0.0.npk
npack inspect ./myapp-1.0.0.npk

# Generate AppStream metadata from a manifest's `app` metadata (icons,
# categories, screenshots, homepage, licence, summary, description) for
# desktop application stores
npack appstream ./myapp-1.0.0.npk --output ./myapp.metainfo.xml

# Install and inspect local packages
# The package metadata is embedded in the .npk.
npack install ./myapp-1.0.0.npk --user
Expand Down
3 changes: 3 additions & 0 deletions docs/npack.1
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ Display metadata embedded in an .npk archive
npack\-manifest(1)
Extract the embedded manifest from an .npk archive
.TP
npack\-appstream(1)
Generate an AppStream component XML document from an .npk archive\*(Aqs manifest
.TP
npack\-help(1)
Print this message or the help of the given subcommand(s)
.SH VERSION
Expand Down
20 changes: 14 additions & 6 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,23 @@ milestone is Phases 1–5: metadata compatibility, a stable service layer,
security and privilege separation, a local catalogue, and a small reference
GUI.

## Phase 1: Package metadata compatibility
## Phase 1: Package metadata compatibility (done)

Add first-class AppStream support:

- Map `.npk` metadata to AppStream fields.
- Support icons, screenshots, categories, homepage, licence, summary, and description.
- Add desktop-file validation.
- Add `npack appstream <package>` output.
- Validate against AppStream tooling in CI.
- Map `.npk` metadata to AppStream fields via a manifest's optional `app`
object.
- Support icons, screenshots, categories, homepage, licence, summary, and
description.
- Add desktop-file validation: `npack pack` requires a declared
`app.desktop_file` to exist and satisfy the freedesktop.org Desktop Entry
spec (`Type`, `Name`, and `Exec` when `Type=Application`).
- Add `npack appstream <package>` output, rendering a `console-application` or
`desktop-application` AppStream `<component>` document depending on whether
`app.desktop_file` is set.
- Validate against AppStream tooling in CI: the `rust` CI job installs
`appstreamcli` and runs `appstreamcli validate --no-net` against a generated
sample document.

Goal: an npack package can describe itself in the language already understood
by Linux application stores.
Expand Down
54 changes: 54 additions & 0 deletions docs/using-npack.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ The important fields are:
| `runtime_requires` | Host capabilities needed by the package, such as ELF libraries. |
| `provides` | Capabilities supplied to other packages. |
| `post_install` | Declarative, capability-gated installation actions. |
| `app` | Optional desktop-store metadata: `summary`, `description`, `homepage`, `license`, `categories`, `icon`, `screenshots`, `desktop_file`, `release_date`. See [AppStream metadata](#appstream-metadata) below. |

An external publishing manifest must contain the final SHA-256:

Expand All @@ -194,6 +195,58 @@ npack manifest ./myapp-1.0.0.npk \
--output ./myapp-1.0.0.manifest.json
```

## AppStream metadata

A manifest's optional `app` object describes the package in the language
Linux application stores already understand:

```json
{
"publisher": "npub1...",
"name": "myapp",
"version": "1.0.0",
"artifact": "myapp-1.0.0.npk",
"sha256": "",
"app": {
"summary": "A friendly greeting",
"description": "Prints a friendly greeting to the terminal.",
"homepage": "https://example.com/myapp",
"license": "MIT",
"categories": ["Utility"],
"icon": "share/icons/myapp.png",
"screenshots": ["https://example.com/myapp/screenshot.png"],
"desktop_file": "myapp.desktop",
"release_date": "2026-01-15"
}
}
```

`icon` and `desktop_file` are package-relative paths to files included in the
`.npk`; `npack pack` checks both exist in the source directory, and validates
`desktop_file` as a syntactically correct freedesktop.org
[Desktop Entry](https://specifications.freedesktop.org/desktop-entry-spec/latest/)
file (a `[Desktop Entry]` group with `Type` and `Name`, plus `Exec` when
`Type=Application`).

Generate an [AppStream](https://www.freedesktop.org/software/appstream/docs/)
component document from a built archive:

```bash
npack appstream ./myapp-1.0.0.npk --output ./myapp.metainfo.xml
```

Packages without a `desktop_file` are rendered as a `console-application`
component advertising `<provides><binary>myapp</binary></provides>`; packages
with one are rendered as a `desktop-application` component advertising
`<launchable type="desktop-id">myapp.desktop</launchable>`. Component IDs are
namespaced `io.npack.<publisher>.<name>`, since npack publishers are Nostr
public keys rather than domains. Validate the generated document with
[`appstreamcli`](https://www.freedesktop.org/software/appstream/docs/man/appstreamcli.1.html):

```bash
appstreamcli validate --no-net ./myapp.metainfo.xml
```

## Dependencies and install order

Dependencies use package names and semantic version requirements:
Expand Down Expand Up @@ -642,4 +695,5 @@ npack list [--user|--system]
npack verify-installed [--user|--system]
npack remove <publisher>/<name> [--user|--system]
npack publish <manifest> --secret-key <key> [options]
npack appstream <file.npk> [--output <metainfo.xml>]
```
Loading
Loading