Skip to content
Hoody.com

The agent exposes endpoints for searching, installing, scaffolding, reading, writing, renaming, deleting, toggling, and trusting skills. skills.list reports the installed skills for the requesting working-directory and config-dir, with their enabled and trust state. The skill-hub routes search, preview, install, and cache skills fetched from a remote hub. The skill-import routes scan well-known locations on disk (for claude or codex) and apply discovered skills to the local store. Skill identity is the daemon’s root_dir + rel_dir pair (with friendly aliases root and rel), except where the route is name-scoped. Realm selectors are handled per operation: skills.list ignores a client-supplied X-Hoody-Realm (or ?realm=) and uses the gateway’s own realm; the hub, import, and per-skill routes accept or reject a realm selector as each operation’s parameters describe.

Lists the installed skills (identity = root_dir + rel_dir) for the requesting working-directory and config-dir, with their enabled and trust state. The result is realm-scoped to the gateway’s OWN realm: skills.list ignores any client-supplied X-Hoody-Realm (or ?realm=) and uses the gateway’s own realm.

NameInTypeRequiredDescription
pagequeryintegerNo1-based page number for pagination.
limitqueryintegerNoMaximum items per page (0 = no pagination).
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against.
X-Hoody-RealmheaderstringNoIgnored by this route; skills.list uses the gateway’s own realm.
realmquerystringNoIn-query alias of X-Hoody-Realm. Ignored by this route; skills.list uses the gateway’s own realm.

The endpoint answers one page per request. The SDK’s skills.listIterator is an async iterator helper that sends no request until it is iterated.

import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
for await (const item of client.agent.skills.listIterator({ page: 1, limit: 20 })) {
// item is a single skill row from the daemon
}

Reads a skill’s source body. Identify the skill by the daemon keys root_dir + rel_dir in the query string (the friendly aliases ?root= and ?rel= are also accepted and translated server-side). The reply carries content, gen, and path. gen is an opaque integer token over the content and the mtime, exact in a JSON number (at most 2^53-1); pass it back as base_gen on skills.setSource to detect conflicts. A skill that does not exist is 404 not_found "skill not found", and so is a realm this login does not serve.

NameInTypeRequiredDescription
root_dirquerystringNoSkill root directory (identity; alias: root).
rel_dirquerystringNoSkill relative directory (identity; alias: rel).
rootquerystringNoFriendly alias of root_dir (translated to root_dir server-side).
relquerystringNoFriendly alias of rel_dir (translated to rel_dir server-side).
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” (not tied to a realm) or a 24-hex realm id. On a session route it names the realm the session is looked up in (a session in another realm, or in a realm this login does not serve, is 404 not_found). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const skill = await client.agent.skills.getSource({ root_dir: '/home/user/.hoody/skills', rel_dir: 'web-search' });

Scaffolds a new local skill. name is the only input: the daemon creates the skill directory in the writable skills root and writes a fixed SKILL.md template with frontmatter carrying that name and a literal description: TODO placeholder, plus a stub body. The route does not accept the skill’s description or content. A new skill is unusable until you replace them, because the description is what the model reads to decide whether to load the skill. This is step one of two: create the skill here, then take the returned root_dir + rel_dir, read the scaffold with skills.getSource, and write the real frontmatter and body with skills.setSource. The create fails when a skill of that name (or that target directory) already exists in ANY root, and when the scope has no writable skills root. The route is realm-scoped to the gateway’s OWN realm: skills.list ignores client selectors, and skills.create accepts or rejects X-Hoody-Realm (or ?realm=) as the parameters below describe.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope: the .hoody project layer / record cwd / tool+workflow cwd. Required by routes that resolve a cwd.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override selecting which on-disk .hoody install a stateless read/write resolves against.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” (not tied to a realm) or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
namestringYesSkill name (also the SKILL.md directory stem, and the frontmatter name). The description is NOT settable here. Must not collide with an existing skill in any root.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.create({ name: 'web-search' });

Overwrites a skill’s source body. Identify the skill by the daemon keys root_dir + rel_dir in the body (aliases root and rel accepted). The new body text is content (alias source). Pass the read’s gen as base_gen for conflict detection: if SKILL.md changed since that read (by content or by mtime), the save is refused with 409 revision_conflict, nothing is written, and details.current_gen carries the file’s current gen. Without base_gen (or with 0) the save is unconditional. The reply’s gen is the new file’s gen.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
root_dirstringYesSkill root directory (identity; alias: root).
rel_dirstringYesSkill relative directory (identity; alias: rel).
contentstringYesNew SKILL.md body (alias: source).
base_genintegerNoThe gen returned by skills.getSource (or a previous skills.setSource). A save whose SKILL.md changed since is refused with 409 revision_conflict and writes nothing. Omit or pass 0 to save unconditionally.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.setSource({
root_dir: '/home/user/.hoody/skills',
rel_dir: 'web-search',
content: '---\nname: web-search\ndescription: Search the web.\n---\n\n# Web search\n',
base_gen: 1234567890
});

Deletes a skill. Identify the skill by the daemon keys root_dir + rel_dir in the body (aliases root and rel accepted). A skill that does not exist is 404 not_found "skill not found", and so is a realm this login does not serve.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
root_dirstringYesSkill root directory (identity; alias: root).
rel_dirstringYesSkill relative directory (identity; alias: rel).
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.delete({ root_dir: '/home/user/.hoody/skills', rel_dir: 'web-search' });

Renames a skill. Identify the skill by the daemon keys root_dir + rel_dir in the body (aliases root and rel accepted) and pass the new name as new_name. A skill that does not exist is 404 not_found "skill not found", and so is a realm this login does not serve.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
root_dirstringYesSkill root directory (identity; alias: root).
rel_dirstringYesSkill relative directory (identity; alias: rel).
new_namestringYesNew skill directory name.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.rename({
root_dir: '/home/user/.hoody/skills',
rel_dir: 'web-search',
new_name: 'web-search-v2'
});

Toggles a skill’s enabled state. This route is name-scoped: it gates the effective skill name in the runtime registry. Identify the skill by name in the body, and pass disabled (boolean) for the new state. Disabling a skill that does not exist is 404 not_found "skill not found", and so is a realm this login does not serve.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
namestringYesEffective skill name (not root/rel; toggle is name-scoped).
disabledbooleanNotrue to disable the skill, false to enable it.

The SDK reaches this operation through two methods:

  • client.agent.skills.enable(...): sets disabled: false.
  • client.agent.skills.disable(...): sets disabled: true.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.disable({ name: 'web-search' });

Sets a skill’s trust state. Identify the skill by the daemon keys root_dir + rel_dir in the body (aliases root and rel accepted); the trust flag is trusted (boolean). Trust gates arbitrary code execution. A skill that does not exist or has no trust record is 404 not_found "skill not found", and so is a realm this login does not serve.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
root_dirstringYesSkill root directory (identity; alias: root).
rel_dirstringYesSkill relative directory (identity; alias: rel).
trustedbooleanYestrue to grant execution trust, false to revoke.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.trust({ root_dir: '/home/user/.hoody/skills', rel_dir: 'web-search', trusted: true });

Searches the remote skill hub (the only hub provider is skills.sh). Pass the search text as ?query= (required; an empty query is refused). Each result’s ref carries the provider, source, and skill_id that skills.hub.preview takes.

NameInTypeRequiredDescription
queryquerystringYesSearch text. Required and non-empty.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const results = await client.agent.skills.hub.search({ query: 'web search' });

Fetches a preview of a hub skill before install (the only hub provider is skills.sh). Name the skill with ?provider=, ?source=, and ?skill_id= (all three required), copied from a skills.hub.search result’s ref. The reply’s package_digest is what skills.hub.install installs.

NameInTypeRequiredDescription
providerquerystringYesHub provider of the skill (a search result’s ref.provider).
sourcequerystringYesSource of the skill on the hub, such as owner/repo (a search result’s ref.source).
skill_idquerystringYesHub skill id (a search result’s ref.skill_id).
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const preview = await client.agent.skills.hub.preview({
provider: 'skills.sh',
source: 'owner/repo',
skill_id: 'web-search'
});

Installs a skill from the hub. The install takes the package the cached preview refers to, identified by package_digest (returned by skills.hub.preview). A digest no longer in the cache is refused; preview again.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
package_digeststringYesThe package_digest returned by skills.hub.preview. The install takes exactly that cached package, so preview first; a digest no longer in the cache is refused (preview again).
overwritebooleanNoReplace a skill already installed under the same name. Without it (default false) such an install is refused.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.hub.install({
package_digest: 'sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
overwrite: false
});

Returns the skill-hub fetch cache statistics.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const stats = await client.agent.skills.hub.getCacheStats();

Clears the skill-hub fetch cache, including pins.

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.hub.clearCache();

Scans well-known locations for importable skills. ?source= picks which tool’s skills to scan: claude or codex (required).

NameInTypeRequiredDescription
sourcequerystringYesWhich tool’s skills to scan. One of claude or codex.
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local). Rejected (400) on routes with no container dimension.
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
const found = await client.agent.skills.scan({ source: 'claude' });

Imports a discovered skill into the local store. Pass the import source and the selected entries returned by the import scan; the daemon re-derives every source location from the source and the selected entry, so a client-supplied filesystem path is not an input. The top-level source is required; an entry’s own source is optional (it defaults to the request source, and must equal it when set).

NameInTypeRequiredDescription
X-Hoody-CwdheaderstringNoPer-request working-directory scope.
X-Hoody-Config-DirheaderstringNoPer-request --config-dir override.
X-Hoody-ContainerheaderstringNoPer-request bound remote container (omitted = local).
X-Hoody-RealmheaderstringNoPer-request realm selector: “global” or a 24-hex realm id (also accepted as ?realm=). Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
realmquerystringNoIn-query alias of X-Hoody-Realm (read only when the header is absent): “global” or a 24-hex realm id. Rejected (400 realm_scope_unsupported) on active-only / no-realm routes, and for any other realm on an agent pinned to one realm.
NameTypeRequiredDescription
sourcestringYesThe import source the entries were scanned from. One of claude or codex.
itemsarrayYesThe selected scan entries to import. At least one entry is required.
overwritebooleanNoReplace an already-installed skill at the same destination instead of refusing that entry. Defaults to false.

Each items entry carries:

NameTypeRequiredDescription
sourcestringNoThe entry’s import source. Optional; when set it must equal the request source, or that entry is refused.
rel_dirstringYesThe entry’s directory, as the import scan reported it (a single directory name, not a path).
import { HoodyClient } from 'hoody-sdk';
const client = new HoodyClient({ baseURL: 'https://{projectId}-{containerId}-agent-1.{server}.containers.hoody.com', token: process.env.HOODY_TOKEN });
await client.agent.skills.import({
source: 'claude',
items: [{ rel_dir: 'web-search' }],
overwrite: false
});