8.8 KiB
ClawHub Scan Command Design
- Date: 2026-06-03
- Status: Approved for implementation
- Scope: authenticated ClawScan job API, public CLI scan command, admin CLI rescan routing, and scan report export shape
Problem
ClawHub runs ClawScan for published artifacts, but users do not have a first-class way to ask ClawHub to scan a local skill bundle before publishing. The existing skill verify command is read-only: it checks stored verification state for a published skill version and does not create fresh scan results.
Publishers and power users need a command like:
clawhub scan <path>
The command should upload a local skill bundle, run ClawHub's scan pipeline, wait until results are ready, print the results in the terminal, and optionally save the full scan report to a file. It should also support fresh scans of already-published skills, with strict ownership checks and an explicit update mode.
Goals
- Add
clawhub scanas a power-user and publisher command. - Support ephemeral local skill scans for any authenticated user.
- Support owner-only published-skill scans.
- Keep local uploads ephemeral. They must not create or update public registry state.
- Let published-skill scans run read-only by default and update stored ClawScan state only with an explicit
--update. - Use submit-and-poll behavior so the CLI feels synchronous without holding one long HTTP request open.
- Reuse the security-audit download shape:
manifest.json,clawscan.json,skillspector.json,static-analysis.json,virustotal.json, andREADME.md. - Update
clawhub-adminto use the canonical scan API for staff rescans while preserving moderator/admin semantics. - Update schema and docs so the scan API routes are canonical and the older rescan routes are either compatibility aliases or clearly deprecated.
Non-Goals
- No anonymous scans.
- No scanning of unpublished plugin packages in this slice; start with skill bundles.
- No automatic publish after a clean local scan.
- No local writes for ephemeral scans other than optional CLI output files.
- No change to
clawhub skill verify; it remains a read-only stored-state verification command.
API Direction
Use a canonical scan job group:
POST /api/v1/skills/-/scan
GET /api/v1/skills/-/scan/{scanId}
GET /api/v1/skills/-/scan/{scanId}/download
POST /api/v1/skills/-/scan creates a scan job and returns a scanId. The caller then polls the status endpoint until the scan reaches a terminal state.
Submit Modes
Local ephemeral scan:
{
"source": { "kind": "upload" },
"update": false
}
This request is multipart. The payload carries the JSON metadata, and file parts carry the local skill bundle files.
Published skill scan:
{
"source": { "kind": "published", "slug": "demo", "version": "1.2.3" },
"update": false
}
Published skill update scan:
{
"source": { "kind": "published", "slug": "demo", "version": "1.2.3" },
"update": true
}
If version is omitted for a published scan, the backend scans the latest version.
Authorization
All scan endpoints require a valid API token.
Local upload scans:
- allowed for any authenticated account in good standing
- always ephemeral
- cannot set
update: true - do not write skill, version, moderation, or public security state
Published skill scans:
- allowed only for the skill owner or a publisher member with management rights
update: falseruns a fresh scan and returns the result without writing it backupdate: truewrites the final ClawScan result back to the selected published version- moderators/admins may use the same backend through
clawhub-admin, preserving the existing operator capability
Existing Route Cleanup
The current POST /api/v1/skills/{slug}/rescan route should move behind the canonical scan API. For compatibility, it can remain as an alias that submits a published scan with update: true.
The current admin batch routes:
POST /api/v1/skills/-/rescan-batch
POST /api/v1/skills/-/rescan-batch/status
should move to scan group routes:
POST /api/v1/skills/-/scan/batch
POST /api/v1/skills/-/scan/batch/status
The existing GET /api/v1/skills/{slug}/scan route currently reads stored scan details. Because this name conflicts with new scan-job creation, keep it as a legacy detail route for now and document the distinction. A later API cleanup can rename stored details to a security-audit route.
CLI Direction
Add a top-level public CLI command:
clawhub scan <path>
clawhub scan <path> --output report.zip
clawhub scan --slug demo
clawhub scan --slug demo --version 1.2.3
clawhub scan --slug demo --update
clawhub scan --slug demo --output report.zip
Rules:
- Exactly one scan source is required: either
<path>or--slug. <path>must resolve to a local skill folder containingSKILL.mdorskill.md.--updateis valid only with--slug.--output <file.zip>writes the report ZIP to that exact file path.- The default terminal output should be a full report, similar to the security-audit UI, not a terse pass/fail summary.
--jsonshould print the terminal report data as JSON for automation. It does not replace--output, which always writes the ZIP report.
Terminal Report
The terminal report should mirror the security audit UI enough that a publisher can make the same judgment from the CLI:
- artifact identity and scan metadata
- ClawScan verdict, confidence, summary, guidance, and findings
- agentic risk buckets and concrete evidence when available
- SkillSpector status, score/severity, issue count, and issues
- static analysis status, reason codes, summary, and findings
- VirusTotal telemetry, including engine counts when present
- update/writeback status for published scans
The CLI should exit non-zero for failed scan jobs. A clean, suspicious, or malicious completed scan is still a successful command execution; policy interpretation belongs in the printed result and JSON.
Report ZIP
Reuse the security-audit Download button archive shape:
manifest.json
clawscan.json
skillspector.json
static-analysis.json
virustotal.json
README.md
The ZIP should be available through GET /api/v1/skills/-/scan/{scanId}/download and should match the bytes written by clawhub scan --output <file.zip>.
manifest.json should include:
- scan id
- source kind
- update mode
- artifact identity
- user-facing timestamps
- terminal status
- whether the scan result was written back
Backend Shape
The existing ClawScan worker is currently built around stored securityScanJobs that target published skill versions or package releases. This feature needs a scan-job abstraction that can also represent ephemeral uploaded skills.
Recommended implementation:
- Add a persisted scan request/job record for user-submitted scans.
- Store uploaded local files in Convex storage with ownership and expiry metadata.
- Materialize ephemeral jobs into the same worker workspace shape used by published scans.
- Store final scan result payloads on the scan job record.
- For published
update: true, also patch the selected version through the existing ClawScan result update path. - Expire or clean up ephemeral uploaded files and completed ephemeral scan records after a bounded retention window.
This keeps worker behavior shared while preventing local uploads from leaking into public artifact state.
Admin CLI
Update clawhub-admin skills rescan <slug> to call the canonical scan API in published update mode, using moderator/admin authorization. Keep its existing prompt, --version, --yes, and --json behavior.
Update clawhub-admin skills rescan-all to call the new canonical batch route. Tests should prove the admin CLI uses the canonical route.
Tests
Backend tests should cover:
- local upload scan requires auth
- local upload scan rejects
update: true - published scan rejects non-owners
- published scan allows owners
- moderator/admin path allows operator rescans
- polling returns queued/running/complete/failed states
- download endpoint returns the expected ZIP entries
update: truewrites back only for published scansupdate: falsedoes not mutate published version scan fields
CLI tests should cover:
clawhub scan <path>uploads multipart and pollsclawhub scan --slug demosubmits read-only published scansclawhub scan --slug demo --updatesends update mode--output report.zipwrites the downloaded ZIP bytes- invalid combinations fail clearly
clawhub-admin skills rescanuses the canonical route
Rollout Notes
This is a behavior and API change, so update:
packages/schemapackages/clawhubpackages/clawhub-admindocs/cli.mddocs/http-api.mdspecs/security-moderation.md
Keep the first implementation narrowly skill-focused. Plugin/package scan support can reuse the same scan-job API later once the skill path is stable.