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
6 changes: 6 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,9 @@ run = "mise run install && bun scripts/render-winget-manifest.ts"

[tasks.docker-smoke]
run = "mise run build -- --targets=linux-x64-musl,linux-arm64-musl && docker build --platform=linux/amd64 -t skillet:local . && docker run --rm --platform=linux/amd64 skillet:local --help"

[tasks.build-npm]
run = "mise run install && bun scripts/build-npm-cli.ts"

[tasks.npm-smoke]
run = "mise run build-npm && npm pack >/tmp/skillet-npm-pack.log && PACKAGE=$(tail -n 1 /tmp/skillet-npm-pack.log) && npx --yes --package \"./$PACKAGE\" skillet --help && REPO_DIR=\"$PWD\" && TMP_DIR=$(mktemp -d) && (cd \"$TMP_DIR\" && bun init -y >/dev/null 2>&1 && bun add \"$REPO_DIR/$PACKAGE\" >/dev/null && bunx --bun skillet --help) && rm -rf \"$TMP_DIR\" \"$PACKAGE\""
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Skillet installs, discovers, and updates `SKILL.md`-based skills across supporte
| Homebrew | `brew install skillet` | Configured |
| Chocolatey | `choco install skillet` | Configured |
| winget | `winget install skillet` | Configured |
| npm / npx | `npx skillet ...` | Planned |
| npm / npx | `npx skillet ...` | Configured |
| Docker | `docker run ... skillet ...` | Configured |
| Local dev | `mise run dev -- --help` | Available |

Expand Down Expand Up @@ -145,3 +145,4 @@ Distribution docs:
- Chocolatey: `docs/distribution/chocolatey.md`
- winget: `docs/distribution/winget.md`
- Docker: `docs/distribution/docker.md`
- npm: `docs/distribution/npm.md`
27 changes: 27 additions & 0 deletions docs/distribution/npm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# npm Distribution

Skillet publishes an npm package so users can run:

- `npx skillet ...`
- `bunx skillet ...`

## Packaging Model

- `src/cli.ts` is bundled to `dist/npm/cli.js` targeting Node.
- `package.json` `bin.skillet` points to `dist/npm/cli.js`.
- `prepack` rebuilds the npm CLI bundle automatically.

## Local Validation

```bash
mise run build-npm
npm pack
npx --yes --package ./skillet-<version>.tgz skillet --help
bunx --bun --package ./skillet-<version>.tgz skillet --help
```

## Publish

```bash
npm publish --access public
```
15 changes: 12 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
{
"name": "skillet",
"version": "0.0.0",
"private": true,
"private": false,
"type": "module",
"publishConfig": {
"access": "public"
},
"files": [
"dist/npm",
"README.md"
],
"bin": {
"skillet": "src/cli.ts"
"skillet": "dist/npm/cli.js"
},
"scripts": {
"dev": "bun src/cli.ts",
"test": "vitest run",
"build": "bun scripts/build-release.ts",
"build:npm": "bun scripts/build-npm-cli.ts",
"render:homebrew": "bun scripts/render-homebrew-formula.ts",
"render:choco": "bun scripts/render-chocolatey-package.ts",
"render:winget": "bun scripts/render-winget-manifest.ts",
"docker:smoke": "mise run docker-smoke"
"docker:smoke": "mise run docker-smoke",
"prepack": "bun scripts/build-npm-cli.ts"
},
"dependencies": {
"cac": "^6.7.14",
Expand Down
25 changes: 25 additions & 0 deletions scripts/build-npm-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import fs from "node:fs";
import path from "node:path";
import { execFileSync } from "node:child_process";

function main(): void {
const repoRoot = process.cwd();
const outputPath = path.join(repoRoot, "dist", "npm", "cli.js");
fs.mkdirSync(path.dirname(outputPath), { recursive: true });

execFileSync(
"bun",
["build", "src/cli.ts", "--bundle", "--target=node", `--outfile=${outputPath}`],
{ cwd: repoRoot, stdio: ["ignore", "inherit", "inherit"] },
);

const output = fs.readFileSync(outputPath, "utf8");
if (!output.startsWith("#!/usr/bin/env node")) {
fs.writeFileSync(outputPath, `#!/usr/bin/env node\n${output}`);
}

fs.chmodSync(outputPath, 0o755);
console.log(`Wrote npm CLI bundle to ${outputPath}`);
}

main();
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env bun
#!/usr/bin/env node
import { cac } from "cac";
import { BUILD_INFO, buildMetadataString } from "./build-info";
import { runAddCommand } from "./commands/add";
Expand Down
22 changes: 22 additions & 0 deletions tests/distribution/npm-package.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { execFileSync, spawnSync } from "node:child_process";
import path from "node:path";
import { describe, expect, it } from "vitest";

describe("npm package bundle", () => {
it("builds a node-compatible cli bundle", () => {
execFileSync("bun", ["scripts/build-npm-cli.ts"], {
cwd: process.cwd(),
stdio: ["ignore", "pipe", "pipe"],
});

const bundledCli = path.resolve(process.cwd(), "dist/npm/cli.js");
const result = spawnSync("node", [bundledCli, "--help"], {
cwd: process.cwd(),
encoding: "utf8",
});

expect(result.status).toBe(0);
expect(result.stdout).toContain("Usage:");
expect(result.stdout).toContain("$ skillet <command> [options]");
});
});