Skip to content
Hoody.com

The package management endpoints on the exec service read, initialise, update, install, compare, and pin the project’s package.json dependencies. Use them to manage Node.js packages inside a container without shelling out to npm yourself. Installations run asynchronously in the background, so the service responds 202 with a startedAt timestamp that the read endpoint then reflects in lastInstall.

Returns the contents of package.json, dependency counts, and the outcome of the most recent background install.

This endpoint takes no parameters.

Terminal window
curl -X GET "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/read" \
-H "Authorization: Bearer <token>"
{
"path": "/home/user/app/package.json",
"content": {},
"dependencies": {
"axios": "^1.7.0",
"lodash": "^4.17.21"
},
"devDependencies": {
"typescript": "^5.5.0"
},
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
},
"dependencyCount": 2,
"devDependencyCount": 1,
"lastInstall": {
"status": "succeeded",
"command": "npm install --save -- lodash axios",
"packages": ["lodash", "axios"],
"startedAt": "2026-01-15T10:30:00.000Z",
"finishedAt": "2026-01-15T10:30:12.000Z",
"durationMs": 12000
}
}

The lastInstall field is null when no install has been started since the exec service booted.

FieldTypeRequiredDescription
pathstringYesPath
contentobjectYesContent
dependenciesobjectYesDependencies
devDependenciesobjectYesDev Dependencies
scriptsobjectYesScripts
dependencyCountintegerYesDependency Count
devDependencyCountintegerYesDev Dependency Count
lastInstallobjectYesThe last background install POST /package/install started since hoody-exec started (null when none): running until npm is done, then succeeded or failed
lastInstall.statusstringYesOne of running, succeeded, failed
lastInstall.commandstringYesThe npm command line
lastInstall.packagesarrayYesThe specs asked for (empty for a bare install of the manifest)
lastInstall.startedAtstringYesThe 202’s startedAt
lastInstall.finishedAtstringNoFinish timestamp
lastInstall.durationMsintegerNoDuration in milliseconds
lastInstall.errorstringNoWhy it failed (npm error lines, truncated to 2000 characters)
lastInstall.incompletearrayNoPackages npm reported installed but left unloadable

Creates a package.json if it does not already exist. The request body is optional; send {} to create with all defaults.

This endpoint takes no parameters.

FieldTypeRequiredDefaultDescription
namestringNo"hoody-exec-project"Name
versionstringNo"1.0.0"Version
descriptionstringNo"Hoody Exec project"Description
forcebooleanNofalseForce
Terminal window
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/init" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "my-app",
"version": "1.0.0",
"description": "My Hoody app",
"force": false
}'
{
"message": "package.json created successfully",
"path": "/home/user/app/package.json",
"content": {
"name": "my-app",
"version": "1.0.0",
"description": "My Hoody app",
"dependencies": {}
},
"created": true
}
FieldTypeRequiredDefaultDescription
messagestringYes-Message (always package.json created successfully)
pathstringYes-Path
contentobjectYes-The contents that were written
content.namestringYes"hoody-exec-project"Name
content.versionstringYes"1.0.0"Version
content.descriptionstringYes"Hoody Exec project"Description
content.dependenciesobjectYes{}Dependencies
createdbooleanYes-Whether the manifest was created (false when it already existed without force)

Edits an existing package.json in place. Use dependencies to add or change entries, scripts to edit scripts, metadata for top-level fields, and remove to drop names from dependencies.

This endpoint takes no parameters.

All fields are optional. null for any field behaves the same as omitting it.

FieldTypeRequiredDefaultDescription
dependenciesobject | nullNo-Dependencies to add or change, as package name → version range. A non-string version or invalid spec is refused with a 400.
scriptsobject | nullNo-scripts entries to add or change, as script name → command. A non-string command is refused with a 400.
metadataobject | nullNo-Top-level fields to set (name, version, description, and so on). dependencies, devDependencies, and scripts here are ignored.
removearray | nullNo-Package names to remove from dependencies.
Terminal window
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/update" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"dependencies": {
"lodash": "^4.17.21",
"axios": "^1.7.0"
},
"scripts": {
"lint": "eslint ."
},
"remove": ["old-package"]
}'
{
"message": "package.json updated successfully",
"changes": [
"added dependencies.lodash = ^4.17.21",
"added dependencies.axios = ^1.7.0",
"added scripts.lint = eslint .",
"removed dependencies.old-package"
],
"changeCount": 4,
"dependencies": {
"axios": "^1.7.0",
"lodash": "^4.17.21"
}
}
FieldTypeRequiredDescription
messagestringYesMessage (always package.json updated successfully)
changesarrayYesHuman-readable list of changes applied
changeCountintegerYesNumber of changes applied
dependenciesobjectYesDependencies after the update

Runs npm install for the given packages in the background. The response returns 202 with a startedAt timestamp; subsequent calls to GET /package/read report the same timestamp in lastInstall along with the final status (running, succeeded, or failed).

This endpoint takes no parameters.

All fields are optional.

FieldTypeRequiredDefaultDescription
packagesarrayNo-Package specs to install (for example ["lodash@^4.17.21", "axios"]). Empty array installs the current manifest.
devbooleanNofalseDev
savebooleanNotrueSave
forcebooleanNofalseForce
Terminal window
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/install" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"packages": ["lodash@^4.17.21", "axios"],
"dev": false,
"save": true,
"force": false
}'
{
"status": "installing",
"command": "npm install --save -- lodash@^4.17.21 axios",
"startedAt": "2026-01-15T10:30:00.000Z",
"message": "Install started in background"
}
FieldTypeRequiredDescription
statusstringYesAlways installing
commandstringYesThe exact npm command line that was spawned
startedAtstringYesISO timestamp; GET /package/read reports this same value as lastInstall.startedAt once the install finishes
messagestringYesHuman-readable summary

Compares the manifests dependencies against the packages actually installed on disk. Reports missing, outdated, unverifiable, and extra packages. The request body is not read; send no body or {}.

This endpoint takes no parameters.

Terminal window
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/compare" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{}'
{
"summary": {
"total": 5,
"installed": 3,
"missing": 1,
"outdated": 1,
"unverifiable": 0,
"extra": 0
},
"missing": ["axios"],
"outdated": [
{
"package": "lodash",
"declared": "^4.17.21",
"installed": "4.17.20"
}
],
"unverifiable": [],
"extra": [],
"allInstalled": false,
"upToDate": false
}
FieldTypeRequiredDescription
summaryobjectYesSummary
summary.totalintegerYesTotal declared dependencies
summary.installedintegerYesCount installed at the declared range
summary.missingintegerYesCount not on disk at all
summary.outdatedintegerYesCount installed but not at the declared range
summary.unverifiableintegerYesCount installed but whose declared range could not be checked
summary.extraintegerYesCount on disk but not declared
missingarrayYesPackage names not installed
outdatedarrayYesOutdated entries (each: package, declared, installed)
unverifiablearrayYesUnverifiable entries (each: package, declared, installed, reason)
extraarrayYesPackage names on disk but not declared
allInstalledbooleanYesTrue when every declared dependency is on disk (regardless of version)
upToDatebooleanYesTrue when every declared dependency matches its declared range and none are extra or unverifiable

Replaces declared version ranges with exact installed versions in package.json. Pass an explicit list of packages to pin, or pass a single module name, or both. Packages that cannot be pinned (for example those declared as a tag or git range) are reported in unpinnable.

This endpoint takes no parameters.

All fields are optional.

FieldTypeRequiredDefaultDescription
packagesarrayNo-Package names to pin
modulestringNo-Module
Terminal window
curl -X POST "https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/v1/exec/package/pin" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"packages": ["lodash", "axios"]
}'
{
"message": "Pinned 2 packages",
"pinned": ["lodash", "axios"],
"unpinnable": [],
"count": 2,
"dependencies": {
"axios": "1.7.4",
"lodash": "4.17.21"
}
}
FieldTypeRequiredDescription
messagestringYesMessage
pinnedarrayYesPackage names that were pinned
unpinnablearrayYesEntries that could not be pinned, each with package, declared (or null), and reason
countintegerYesNumber of packages pinned
dependenciesobjectNoDependencies map after pinning; present when the response matches the second anyOf shape