Skip to content
Hoody.com

With hoody-exec, any script in its scripts directory is a live HTTP endpoint: write the file, and the URL exists. You do not need Express, Docker, or a CI/CD pipeline. Always write exec scripts through the exec service’s own scripts/write endpoint (not the Files service) so they land in the exec-managed scripts directory and pass validation.


Terminal window
# Write a script to the exec scripts directory (path is relative to that dir)
# All kit commands require a target container: -c CONTAINER_ID (or HOODY_CONTAINER)
hoody exec scripts write -c CONTAINER_ID --path "api/hello.js" --create-dirs --content \
'// @mode serverless
const name = metadata.query.name || "World";
return { message: `Hello, ${name}!`, timestamp: new Date().toISOString() };'

Your script is already live at:

https://{projectId}-{containerId}-exec-1.{server}.containers.hoody.com/api/hello
Terminal window
# Call your new API endpoint directly via its URL
curl "https://$PROJECT_ID-$CONTAINER_ID-exec-1.$SERVER_NAME.containers.hoody.com/api/hello?name=Developer"

That URL works from anywhere: a browser, a webhook, an AI agent, a phone. There is no separate deployment step.


Exec scripts can call any other service in the container. Sibling services share the same host as your script; only the service slug changes. Derive the base host from metadata.url (the full request URL) and swap in the target service:

scripts/default/1/api/deploy-report.ts
// @mode serverless
// metadata.url is the full request URL, e.g.
// https://PROJECT_ID-CONTAINER_ID-exec-1.SERVER.containers.hoody.com/api/deploy-report
const { hostname } = new URL(metadata.url);
const host = (svc, idx = 1) =>
`https://${hostname.replace(/-exec-\d+\./, `-${svc}-${idx}.`)}`;
// Run the build. ephemeral=true creates an isolated one-shot PTY; send it to the
// terminal-0 hostname, because on any terminal-N hostname the proxy forces
// terminal_id=N and ephemeral can no longer auto-generate an id.
const build = await fetch(`${host('terminal', 0)}/api/v1/terminal/execute?ephemeral=true`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ command: 'npm run build', wait: true })
});
// wait: true returns the finished command, so read its outcome before reporting one
const result = build.ok ? await build.json() : null;
const succeeded = result?.status === 'completed' && result.exit_code === 0;
// Log to database; the first deploy has to create the table it writes to
await fetch(`${host('sqlite')}/api/v1/sqlite/db?db=logs&create_db_if_missing=true`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
transaction: [
{ statement: 'CREATE TABLE IF NOT EXISTS deploys (status TEXT NOT NULL, time TEXT NOT NULL)' },
{
statement: 'INSERT INTO deploys (status, time) VALUES (?, ?)',
values: [succeeded ? 'success' : 'failure', new Date().toISOString()]
}
]
})
});
// Send a notification: `display` is required, and `1` is the container's primary desktop
await fetch(`${host('n')}/api/v1/notifications/notify`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
display: '1',
summary: succeeded ? 'Deploy complete' : 'Deploy failed',
body: succeeded ? 'Build succeeded' : `Build exited ${result?.exit_code ?? 'without a result'}`
})
});
return { status: succeeded ? 'deployed' : 'failed', timestamp: new Date().toISOString() };

One script coordinates three services with plain HTTP requests and no additional infrastructure.


You created a live API endpoint by writing a file, with no npm install, docker build, or deploy command; maintaining a package.json is optional. The script’s path, relative to the exec scripts directory, is the URL path:

Script pathURL path
api/hello.js/api/hello
api/users/list.js/api/users/list
api/deploy.ts/api/deploy
webhooks/stripe.js/webhooks/stripe

Each script is an endpoint, each endpoint can call any service in the container, and every service speaks HTTP. Writing the script, calling it, and chaining services all happened through URLs.

Next: The Hoody Kit →