refactor: rename internal clawdhub package path (#1490)

* refactor: rename internal clawdhub package path

* fix: update workflow paths after clawhub dir rename

* fix: preserve old tag npm release compatibility

---------

Co-authored-by: Onur <onur@solmaz.io>
This commit is contained in:
Onur
2026-04-02 17:50:33 +02:00
committed by GitHub
co-authored by Onur
parent 78d0a637fa
commit 4ae0406948
90 changed files with 81 additions and 57 deletions
+2 -2
View File
@@ -32,13 +32,13 @@ jobs:
run: bun run coverage
- name: ClawHub CLI Verify
run: bun run --cwd packages/clawdhub verify
run: bun run --cwd packages/clawhub verify
- name: Typecheck
run: |
bunx tsc --noEmit
bunx tsc -p packages/schema/tsconfig.json --noEmit
bunx tsc -p packages/clawdhub/tsconfig.json --noEmit
bunx tsc -p packages/clawhub/tsconfig.json --noEmit
- name: Build
run: bun run build
+32 -8
View File
@@ -59,6 +59,18 @@ jobs:
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Resolve CLI package directory
run: |
set -euo pipefail
if [[ -d "packages/clawhub" ]]; then
echo "PACKAGE_DIR=packages/clawhub" >> "$GITHUB_ENV"
elif [[ -d "packages/clawdhub" ]]; then
echo "PACKAGE_DIR=packages/clawdhub" >> "$GITHUB_ENV"
else
echo "Unable to find clawhub CLI package directory." >&2
exit 1
fi
- name: Ensure version is not already published
env:
PREFLIGHT_ONLY: ${{ inputs.preflight_only }}
@@ -67,7 +79,7 @@ jobs:
PACKAGE_VERSION="$(node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("./packages/clawdhub/package.json", "utf8"));
const pkg = JSON.parse(readFileSync(`./${process.env.PACKAGE_DIR}/package.json`, "utf8"));
process.stdout.write(String(pkg.version ?? "").trim());
EOF
)"
@@ -95,7 +107,7 @@ jobs:
node scripts/clawhub-cli-npm-release-check.mjs
- name: Verify CLI package
run: bun run --cwd packages/clawdhub verify
run: bun run --cwd "$PACKAGE_DIR" verify
- name: Pack prepared npm tarball
id: packed_tarball
@@ -103,12 +115,12 @@ jobs:
RELEASE_TAG: ${{ inputs.tag }}
run: |
set -euo pipefail
pushd packages/clawdhub >/dev/null
pushd "$PACKAGE_DIR" >/dev/null
PACK_JSON="$(npm pack --json --ignore-scripts)"
echo "$PACK_JSON"
PACK_PATH="$(printf '%s\n' "$PACK_JSON" | node --input-type=module -e 'const chunks=[]; process.stdin.on("data", (chunk) => chunks.push(chunk)); process.stdin.on("end", () => { const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8")); const first = Array.isArray(parsed) ? parsed[0] : null; if (!first || typeof first.filename !== "string" || !first.filename) process.exit(1); process.stdout.write(first.filename); });')"
popd >/dev/null
if [[ -z "${PACK_PATH}" || ! -f "packages/clawdhub/${PACK_PATH}" ]]; then
if [[ -z "${PACK_PATH}" || ! -f "${PACKAGE_DIR}/${PACK_PATH}" ]]; then
echo "npm pack did not produce a tarball file." >&2
exit 1
fi
@@ -116,14 +128,14 @@ jobs:
PACKAGE_VERSION="$(node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("./packages/clawdhub/package.json", "utf8"));
const pkg = JSON.parse(readFileSync(`./${process.env.PACKAGE_DIR}/package.json`, "utf8"));
process.stdout.write(String(pkg.version ?? "").trim());
EOF
)"
ARTIFACT_DIR="$RUNNER_TEMP/clawhub-cli-npm-preflight"
rm -rf "$ARTIFACT_DIR"
mkdir -p "$ARTIFACT_DIR"
cp "packages/clawdhub/${PACK_PATH}" "$ARTIFACT_DIR/"
cp "${PACKAGE_DIR}/${PACK_PATH}" "$ARTIFACT_DIR/"
printf '%s\n' "$RELEASE_TAG" > "$ARTIFACT_DIR/release-tag.txt"
printf '%s\n' "$RELEASE_SHA" > "$ARTIFACT_DIR/release-sha.txt"
printf '%s\n' "$PACKAGE_VERSION" > "$ARTIFACT_DIR/package-version.txt"
@@ -184,13 +196,25 @@ jobs:
node-version: ${{ env.NODE_VERSION }}
registry-url: https://registry.npmjs.org
- name: Resolve CLI package directory
run: |
set -euo pipefail
if [[ -d "packages/clawhub" ]]; then
echo "PACKAGE_DIR=packages/clawhub" >> "$GITHUB_ENV"
elif [[ -d "packages/clawdhub" ]]; then
echo "PACKAGE_DIR=packages/clawdhub" >> "$GITHUB_ENV"
else
echo "Unable to find clawhub CLI package directory." >&2
exit 1
fi
- name: Ensure version is not already published
run: |
set -euo pipefail
PACKAGE_VERSION="$(node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("./packages/clawdhub/package.json", "utf8"));
const pkg = JSON.parse(readFileSync(`./${process.env.PACKAGE_DIR}/package.json`, "utf8"));
process.stdout.write(String(pkg.version ?? "").trim());
EOF
)"
@@ -240,7 +264,7 @@ jobs:
EXPECTED_PACKAGE_VERSION="$(node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("./packages/clawdhub/package.json", "utf8"));
const pkg = JSON.parse(readFileSync(`./${process.env.PACKAGE_DIR}/package.json`, "utf8"));
process.stdout.write(String(pkg.version ?? "").trim());
EOF
)"
+1 -1
View File
@@ -216,7 +216,7 @@ jobs:
cmd = [
"bun",
"clawhub-source/packages/clawdhub/src/cli.ts",
"clawhub-source/packages/clawhub/src/cli.ts",
"package",
"publish",
source,
+1 -1
View File
@@ -38,7 +38,7 @@
- Commit messages: Conventional Commits (`feat:`, `fix:`, `chore:`, `docs:`…).
- Keep changes scoped; avoid repo-wide search/replace.
- PRs: include summary + test commands run. Add screenshots for UI changes.
- Before merging any PR, verify TypeScript cleanly with `bunx tsc -p packages/schema/tsconfig.json --noEmit` and `bunx tsc -p packages/clawdhub/tsconfig.json --noEmit`; if Convex code changed, also run the repo typecheck path used by deploy so `bunx convex deploy` will not fail on `tsc`.
- Before merging any PR, verify TypeScript cleanly with `bunx tsc -p packages/schema/tsconfig.json --noEmit` and `bunx tsc -p packages/clawhub/tsconfig.json --noEmit`; if Convex code changed, also run the repo typecheck path used by deploy so `bunx convex deploy` will not fail on `tsc`.
- GitHub comments: for multiline `gh` comments/close messages, use `--body-file`, `--input`, or stdin/heredoc with real newlines; never pass literal `\\n` in shell strings.
- Reject PRs that add skills into source code/repo content directly (for example under `skills/` or seed-only additions intended as published skills). Skills must be uploaded/published via CLI.
+7 -7
View File
@@ -109,7 +109,7 @@ These features degrade gracefully without their keys:
## CLI Development
The CLI source lives in [`packages/clawdhub/`](packages/clawdhub/). Both `clawhub` and `clawdhub` are registered as bin aliases.
The CLI source lives in [`packages/clawhub/`](packages/clawhub/). Both `clawhub` and `clawdhub` are registered as bin aliases.
To test the CLI against your local instance:
@@ -120,13 +120,13 @@ CLAWHUB_REGISTRY=http://127.0.0.1:3210 CLAWHUB_SITE=http://localhost:3000 clawhu
Use the package-local verification contract when working on the CLI:
```bash
bun run --cwd packages/clawdhub test
bun run --cwd packages/clawdhub verify:build
bun run --cwd packages/clawdhub test:artifact
bun run --cwd packages/clawdhub verify
bun run --cwd packages/clawhub test
bun run --cwd packages/clawhub verify:build
bun run --cwd packages/clawhub test:artifact
bun run --cwd packages/clawhub verify
```
`bun test packages/clawdhub/` is not the supported workflow. Source tests and built-artifact smoke tests are intentionally split.
`bun test packages/clawhub/` is not the supported workflow. Source tests and built-artifact smoke tests are intentionally split.
Manual smoke tests are documented in [`docs/manual-testing.md`](docs/manual-testing.md).
@@ -148,7 +148,7 @@ clawhub publish <path-to-skill-directory>
bun run lint # oxlint
bun run test # Vitest (80% coverage threshold)
bun run build # Vite + Nitro
bun run --cwd packages/clawdhub verify
bun run --cwd packages/clawhub verify
```
These are the same checks that run in CI (`.github/workflows/ci.yml`).
+3 -3
View File
@@ -63,9 +63,9 @@
"vitest": "^4.1.0",
},
},
"packages/clawdhub": {
"packages/clawhub": {
"name": "clawhub",
"version": "0.8.0",
"version": "0.10.0",
"bin": {
"clawdhub": "bin/clawdhub.js",
"clawhub": "bin/clawdhub.js",
@@ -682,7 +682,7 @@
"chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
"clawhub": ["clawhub@workspace:packages/clawdhub"],
"clawhub": ["clawhub@workspace:packages/clawhub"],
"clawhub-schema": ["clawhub-schema@workspace:packages/schema"],
+3 -3
View File
@@ -3,10 +3,10 @@ import { existsSync } from 'node:fs'
import { stat } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
const packageRootPath = fileURLToPath(new URL('./packages/clawdhub/', import.meta.url))
const distCliUrl = new URL('./packages/clawdhub/dist/cli.js', import.meta.url)
const packageRootPath = fileURLToPath(new URL('./packages/clawhub/', import.meta.url))
const distCliUrl = new URL('./packages/clawhub/dist/cli.js', import.meta.url)
const distCliPath = fileURLToPath(distCliUrl)
const srcRootPath = fileURLToPath(new URL('./packages/clawdhub/src/', import.meta.url))
const srcRootPath = fileURLToPath(new URL('./packages/clawhub/src/', import.meta.url))
const shouldBuild = await (async () => {
if (!existsSync(distCliPath)) return true
+3 -3
View File
@@ -3,10 +3,10 @@ import { existsSync } from 'node:fs'
import { stat } from 'node:fs/promises'
import { fileURLToPath } from 'node:url'
const packageRootPath = fileURLToPath(new URL('./packages/clawdhub/', import.meta.url))
const distCliUrl = new URL('./packages/clawdhub/dist/cli.js', import.meta.url)
const packageRootPath = fileURLToPath(new URL('./packages/clawhub/', import.meta.url))
const distCliUrl = new URL('./packages/clawhub/dist/cli.js', import.meta.url)
const distCliPath = fileURLToPath(distCliUrl)
const srcRootPath = fileURLToPath(new URL('./packages/clawdhub/src/', import.meta.url))
const srcRootPath = fileURLToPath(new URL('./packages/clawhub/src/', import.meta.url))
const shouldBuild = await (async () => {
if (!existsSync(distCliPath)) return true
+1 -1
View File
@@ -11,7 +11,7 @@ read_when:
- Web app: TanStack Start (React) under `src/`.
- Backend: Convex under `convex/` (DB, storage, actions, HTTP routes).
- CLI: `packages/clawdhub/` (published as `clawhub`, legacy `clawdhub`).
- CLI: `packages/clawhub/` (published as `clawhub`, legacy `clawdhub`).
- Shared schemas/routes: `packages/schema/` (`clawhub-schema`).
## Data + storage
+1 -1
View File
@@ -7,7 +7,7 @@ read_when:
# CLI
CLI package: `packages/clawdhub/` (published as `clawhub`, bin: `clawhub`).
CLI package: `packages/clawhub/` (published as `clawhub`, bin: `clawhub`).
From this repo you can run it via the wrapper script:
@@ -13,7 +13,7 @@ import {
import { unzipSync } from "fflate";
import { Agent, setGlobalDispatcher } from "undici";
import { describe, expect, it } from "vitest";
import { readGlobalConfig } from "../packages/clawdhub/src/config";
import { readGlobalConfig } from "../packages/clawhub/src/config";
const REQUEST_TIMEOUT_MS = 15_000;
+2 -2
View File
@@ -14,8 +14,8 @@
"docs:list": "bun scripts/docs-list.ts",
"format": "oxfmt --write",
"lint": "bun run lint:oxlint",
"lint:fix": "oxlint --type-aware --tsconfig ./tsconfig.oxlint.json ./src ./convex ./packages/clawdhub/src ./packages/schema/src --fix && bun run format",
"lint:oxlint": "oxlint --type-aware --tsconfig ./tsconfig.oxlint.json ./src ./convex ./packages/clawdhub/src ./packages/schema/src",
"lint:fix": "oxlint --type-aware --tsconfig ./tsconfig.oxlint.json ./src ./convex ./packages/clawhub/src ./packages/schema/src --fix && bun run format",
"lint:oxlint": "oxlint --type-aware --tsconfig ./tsconfig.oxlint.json ./src ./convex ./packages/clawhub/src ./packages/schema/src",
"preinstall": "bunx only-allow bun",
"preview": "bun --bun vite preview",
"release:clawhub:cli:npm:check": "node scripts/clawhub-cli-npm-release-check.mjs",
@@ -68,10 +68,10 @@ The `clawhub` npm package is released separately from the ClawHub app deploy.
The supported verification flow for this package is package-local:
```bash
bun run --cwd packages/clawdhub test
bun run --cwd packages/clawdhub verify:build
bun run --cwd packages/clawdhub test:artifact
bun run --cwd packages/clawdhub verify
bun run --cwd packages/clawhub test
bun run --cwd packages/clawhub verify:build
bun run --cwd packages/clawhub test:artifact
bun run --cwd packages/clawhub verify
```
`test` runs source tests only. `test:artifact` builds `dist/` and runs a small smoke suite against the built CLI entrypoint.
@@ -10,7 +10,7 @@
"repository": {
"type": "git",
"url": "https://github.com/openclaw/clawhub.git",
"directory": "packages/clawdhub"
"directory": "packages/clawhub"
},
"bin": {
"clawdhub": "bin/clawdhub.js",
+3 -3
View File
@@ -21,13 +21,13 @@ package_version="$(
node --input-type=module <<'EOF'
import { readFileSync } from "node:fs";
const pkg = JSON.parse(readFileSync("./packages/clawdhub/package.json", "utf8"));
const pkg = JSON.parse(readFileSync("./packages/clawhub/package.json", "utf8"));
process.stdout.write(String(pkg.version ?? "").trim());
EOF
)"
if [[ -z "${package_version}" ]]; then
echo "Unable to resolve packages/clawdhub/package.json version." >&2
echo "Unable to resolve packages/clawhub/package.json version." >&2
exit 1
fi
@@ -46,6 +46,6 @@ if [[ -n "${publish_target}" ]]; then
fi
(
cd packages/clawdhub
cd packages/clawhub
npm publish --access public --tag latest --provenance
)
+13 -13
View File
@@ -4,7 +4,7 @@ import { execFileSync } from "node:child_process";
import { readFileSync } from "node:fs";
const EXPECTED_REPOSITORY_URL = "https://github.com/openclaw/clawhub";
const EXPECTED_REPOSITORY_DIRECTORY = "packages/clawdhub";
const EXPECTED_REPOSITORY_DIRECTORY = "packages/clawhub";
const EXPECTED_HOMEPAGE_URL = "https://clawhub.ai";
const EXPECTED_BUGS_URL = "https://github.com/openclaw/clawhub/issues";
const EXPECTED_BIN_PATH = "bin/clawdhub.js";
@@ -42,7 +42,7 @@ function normalizeUrl(value) {
}
function readPackageJson() {
return JSON.parse(readFileSync(new URL("../packages/clawdhub/package.json", import.meta.url), "utf8"));
return JSON.parse(readFileSync(new URL("../packages/clawhub/package.json", import.meta.url), "utf8"));
}
function isStableSemverVersion(value) {
@@ -61,57 +61,57 @@ function collectPackageMetadataErrors(pkg) {
pkg.bugs && typeof pkg.bugs === "object" ? normalizeUrl(pkg.bugs.url) : normalizeUrl(pkg.bugs);
if (pkg.name !== "clawhub") {
errors.push(`packages/clawdhub/package.json name must be "clawhub"; found "${pkg.name ?? ""}".`);
errors.push(`packages/clawhub/package.json name must be "clawhub"; found "${pkg.name ?? ""}".`);
}
if (!isStableSemverVersion(String(pkg.version ?? ""))) {
errors.push(
`packages/clawdhub/package.json version must be stable semver (X.Y.Z); found "${pkg.version ?? ""}".`,
`packages/clawhub/package.json version must be stable semver (X.Y.Z); found "${pkg.version ?? ""}".`,
);
}
if (!String(pkg.description ?? "").trim()) {
errors.push("packages/clawdhub/package.json description must be non-empty.");
errors.push("packages/clawhub/package.json description must be non-empty.");
}
if (pkg.license !== "MIT") {
errors.push(`packages/clawdhub/package.json license must be "MIT"; found "${pkg.license ?? ""}".`);
errors.push(`packages/clawhub/package.json license must be "MIT"; found "${pkg.license ?? ""}".`);
}
if (normalizeUrl(pkg.homepage) !== EXPECTED_HOMEPAGE_URL) {
errors.push(
`packages/clawdhub/package.json homepage must resolve to ${EXPECTED_HOMEPAGE_URL}; found "${
`packages/clawhub/package.json homepage must resolve to ${EXPECTED_HOMEPAGE_URL}; found "${
normalizeUrl(pkg.homepage) || "<missing>"
}".`,
);
}
if (bugsUrl !== EXPECTED_BUGS_URL) {
errors.push(
`packages/clawdhub/package.json bugs.url must resolve to ${EXPECTED_BUGS_URL}; found "${
`packages/clawhub/package.json bugs.url must resolve to ${EXPECTED_BUGS_URL}; found "${
bugsUrl || "<missing>"
}".`,
);
}
if (repoUrl !== EXPECTED_REPOSITORY_URL) {
errors.push(
`packages/clawdhub/package.json repository.url must resolve to ${EXPECTED_REPOSITORY_URL}; found "${
`packages/clawhub/package.json repository.url must resolve to ${EXPECTED_REPOSITORY_URL}; found "${
repoUrl || "<missing>"
}".`,
);
}
if (repoDirectory !== EXPECTED_REPOSITORY_DIRECTORY) {
errors.push(
`packages/clawdhub/package.json repository.directory must be "${EXPECTED_REPOSITORY_DIRECTORY}"; found "${
`packages/clawhub/package.json repository.directory must be "${EXPECTED_REPOSITORY_DIRECTORY}"; found "${
typeof repoDirectory === "string" ? repoDirectory : "<missing>"
}".`,
);
}
if (pkg.bin?.clawhub !== EXPECTED_BIN_PATH) {
errors.push(
`packages/clawdhub/package.json bin.clawhub must be "${EXPECTED_BIN_PATH}"; found "${
`packages/clawhub/package.json bin.clawhub must be "${EXPECTED_BIN_PATH}"; found "${
pkg.bin?.clawhub ?? ""
}".`,
);
}
if (pkg.bin?.clawdhub !== EXPECTED_BIN_PATH) {
errors.push(
`packages/clawdhub/package.json bin.clawdhub must be "${EXPECTED_BIN_PATH}"; found "${
`packages/clawhub/package.json bin.clawdhub must be "${EXPECTED_BIN_PATH}"; found "${
pkg.bin?.clawdhub ?? ""
}".`,
);
@@ -134,7 +134,7 @@ function collectReleaseTagErrors({ packageVersion, releaseTag, releaseSha, relea
}
if (normalizedTag !== `v${normalizedVersion}`) {
errors.push(
`Release tag ${normalizedTag} does not match packages/clawdhub/package.json version ${normalizedVersion}; expected v${normalizedVersion}.`,
`Release tag ${normalizedTag} does not match packages/clawhub/package.json version ${normalizedVersion}; expected v${normalizedVersion}.`,
);
}
if (releaseSha?.trim() && releaseMainRef?.trim()) {
+1 -1
View File
@@ -1,5 +1,5 @@
{
"include": ["src", "convex", "packages/clawdhub/src", "packages/schema/src"],
"include": ["src", "convex", "packages/clawhub/src", "packages/schema/src"],
"compilerOptions": {
"target": "ES2022",
"jsx": "react-jsx",
+2 -2
View File
@@ -15,7 +15,7 @@ export default defineConfig({
"**/dist/**",
"**/coverage/**",
"**/convex/_generated/**",
"packages/clawdhub/**",
"packages/clawhub/**",
"e2e/**",
"**/*.e2e.test.ts",
],
@@ -44,7 +44,7 @@ export default defineConfig({
"dist/",
"coverage/",
"convex/_generated/",
"packages/clawdhub/**",
"packages/clawhub/**",
"packages/schema/dist/",
"e2e/**",
],