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
61 changes: 61 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# AGENTS.md — layer-nodejs

Standalone candy repo for the `nodejs` layer — the Node.js runtime with the `npm`
and `pnpm` package managers. The candy lives in `charly.yml` at the repo root:
the env vars, the per-distro NodeSource repo arms, the pnpm download step, the
`check:` assertions, and the embedded `skill:` entity projected into the
marketplace corpus as `/charly-coder:nodejs`.

Canonical files:

- `charly.yml` — the `nodejs:` candy entity and the `nodejs-skill:` skill entity.
- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge.
- `README.md` — user overview only; never agent guidance.

## Load these skills first (R0)

- `/charly-coder:nodejs` — the owning skill. The Node.js runtime, the npm global
prefix, the NodeSource upgrade, and the standalone pnpm binary. Load before
editing or troubleshooting the layer.
- `/charly-image:layer` — the candy authoring reference (`charly.yml` schema,
`plan:` step verbs incl. `command:`/`check:`, per-distro `distro:` arms,
package/repo sections, and service declarations). Load before editing any
entity field or plan step.

## Build / validate / test

- The merge gate is the **org-wide** `charly/pr-validator` (required check
`validate / validate`, defined in `opencharly/.github`); this repo has **no
per-repo candy gate** and ships only `.github/workflows/tag-on-merge.yml`.
- The candy's `plan:` `check:` steps are the functional evidence; they must stay
valid on every distro arm they run on. Scope a distro-specific check in the
command itself — the check runner does not honour runner-level
`exclude-distro` fields.
- Two check-step gotchas are load-bearing and documented inline: a `check:`
command goes through charly variable substitution, so `${...}` (e.g.
`${HOME:-default}`) is read as an unresolvable variable and the step is
SKIPPED — use `$( )` and `env HOME=…` instead. And `pnpm` hard-requires a
homedir, so its version check derives `HOME` from passwd.

## Modify this repo

- Edit the `nodejs:` candy entity AND the `nodejs-skill:` skill entity in
`charly.yml` together. The skill is the projected usage source, so a version or
behaviour change not mirrored in the skill leaves the corpus stale.
- `pnpm` is installed as a standalone binary to `/usr/local/bin/pnpm`, NOT as a
`package.json` dependency — adding a `package.json` would trigger the npm
multi-stage builder on this candy and break its builder-image consumers.
- The pinned `PNPM_VERSION` and the `check:` assertions must stay in sync.
- New behaviour claims belong in the `plan:` as an observable `check:` step, and
in the skill body.

## Landing

- PR-only. Every change lands through a pull request; the org-required
`charly/pr-validator` validates the diff and body and arms native auto-merge
on PASS. Direct pushes to `main` are blocked.
- History lives in `CHANGELOG/` (written by `tag-on-merge` at merge time); the
PR body IS the changelog.
- The authoritative rulebook is the umbrella `AGENTS.md` in
`opencharly/opencharly` and `charly/AGENTS.md` in the charly repo. Do not
restate its rules here.
61 changes: 57 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,59 @@
# layer-nodejs

The `layer-nodejs` candy of the [opencharly/charly](https://github.com/opencharly/charly)
candy library, as a standalone repo (the candy de-submodule cutover, kind-prefixed
naming). The candy manifest lives at the repo root; the charly resolver fetches
this repo at the pinned tag.
A Node.js runtime with the `npm` and `pnpm` package managers on the default
`PATH`, as a standalone OpenCharly layer repo.

The candy installs the distro `nodejs` package (NodeSource node 22.x on Ubuntu
and Debian so the in-box CLIs that require node >=22 work — the deepseek-harness
`dsh` floor), the matching `npm` CLI, and a self-contained `pnpm` standalone
binary at `/usr/local/bin/pnpm`. Every artifact is a real file at a known path
with a working `--version`, so the runtime is directly verifiable.

## What it provides

| Property | Value |
|---|---|
| Layer / candy | `nodejs` |
| Binaries | `/usr/bin/node`, `/usr/bin/npm`, `/usr/local/bin/pnpm` |
| Pinned pnpm | `PNPM_VERSION` `10.33.4` |
| Env | `NPM_CONFIG_PREFIX=~/.npm-global`; `~/.npm-global/bin` on `PATH` |
| Service / port | none |

On Ubuntu/Debian the `nodejs` package comes from NodeSource (node 22.x) and
bundles `npm`; the separate apt `npm` is deliberately dropped because installing
it alongside pulls conflicting `node-*` deps. Fedora/Arch keep their
`dnf`/`pacman` `npm` (their base node is already >=22).

## How to use it

Compose the layer as a nested `candy:` list inside a named box body:

```yaml
my-node-box:
candy:
base: fedora
candy:
- '@github.com/opencharly/layer-nodejs:v2026.239.1624'
```

`pnpm` is installed as a standalone binary — deliberately **not** a
`package.json` dependency — because a `package.json` would trigger the npm
multi-stage builder on this candy, and the builder images that compose nodejs
cannot self-provide the npm builder.

## Layout

- `charly.yml` — the `nodejs:` candy entity (the env vars, the NodeSource repo
arms, the pnpm download step, the `check:` assertions, and the embedded
`nodejs-skill:` skill entity).
- `.github/workflows/tag-on-merge.yml` — CalVer tag + `CHANGELOG/` on merge.
- `README.md` — this user overview.

## Related

- Owning skill: `/charly-coder:nodejs` — the Node.js runtime, the npm global
prefix, and the standalone pnpm binary.
- `/charly-coder:pre-commit` — depends on nodejs.
- `/charly-image:layer` — candy authoring reference.
- [`opencharly/charly`](https://github.com/opencharly/charly) — the charly CLI and image builder
- [`opencharly/opencharly`](https://github.com/opencharly/opencharly) — the umbrella
Loading