Skill

Skills: Agent Skills folders any agent of their scope can attach.

check = noclick.Skill.from_dir("./skills/invoice-check")              # SKILL.md plus its scripts and files
support = noclick.Agent.from_name("support", create_if_missing=True, instructions="...", skills=[check])

A skill is a folder: a SKILL.md whose frontmatter names it (name) and says what it does and when to use it (description; always: true puts it whole in every turn), plus any other files. Every save is a new version; an agent follows the latest unless it holds one (skill.pinned(3)). A coding harness finds its skills where it reads skills; an sdk agent sees each one's name and description every turn and reads one with skill__read.

class Skill

An Agent Skills folder of the account's (every user's agents may use it) or one user's, versioned. Delete it and it goes to the trash, off every agent that attaches it; restoring puts it back on them.

Attributes
idstring
namestring

Its name, from its latest SKILL.md.

descriptionstring
alwaysboolean

Whether it's put whole in every turn of the agents that attach it.

versionnumber

Its latest version's number.

digeststring

Its latest version's content, as a digest: what restarts a coding agent's warm sandbox when it changes.

fileCountnumber
sizenumber

Its latest version's size in bytes.

attachedToSkillAttachment[]

The agents that attach it, and the version each holds (null: the latest).

userIdstring | null
createdAtDate | null
updatedAtDate | null

createstatic

static create(
  files: SkillFiles,
  options?: CallOptions & AllowExisting,
): Promise<Skill>

A skill from its folder, named by its SKILL.md; unique by name per user, or for the account outside asUser. A taken name throws Conflict with existingId, or with allowExisting: true returns the skill already there as it is (saveVersion to change it). Up to 200 files and 20 MB, SKILL.md up to 64 KB.

Parameters
filesSkillFilesrequired
options.allowExistingboolean

A taken name returns the object already there, as it is: nothing about it changes.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The new skill at version 1.

Types
/** A folder's files: path → text, or bytes for a file that isn't text. */
type SkillFiles = Record<string, string | Uint8Array>;

/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

fromNamestatic

static fromName(
  name: string,
  options?: CallOptions & { createIfMissing?: boolean; files?: SkillFiles },
): Skill

A lazy reference to the skill called name. Acting for a user, that user's own skill is found first, then the account's. With createIfMissing it's created from files on first use.

Parameters
namestringrequired
options.createIfMissingboolean
options.filesSkillFiles
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A skill that loads (or is created) the first time it's used. Nothing is sent yet.

Types
/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

/** A folder's files: path → text, or bytes for a file that isn't text. */
type SkillFiles = Record<string, string | Uint8Array>;

fromIdstatic

static fromId(skillId: string, options?: CallOptions): Skill

A lazy reference to a skill by id.

Parameters
skillIdstringrequired
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
Returns

A skill that loads the first time you read a field. Nothing is sent yet.

Types
/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

getstatic

static get(skillId: string, options?: CallOptions): Promise<Skill>

Load a skill by id now; an unknown id raises noclick.NotFound.

Parameters
skillIdstringrequired
options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The skill, loaded: its latest version and the agents that attach it.

Types
/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

liststatic

static list(
  options?: ReadOptions & { limit?: number; agent?: string | ApiObject },
): Promise<Skill[]>

The current user's skills and the account's (or those userFilter covers), newest first. With agent, the skills that agent attaches, in its order.

Parameters
options.agentstring | ApiObject
options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Every matching skill, fetched page by page.

Types
/**
 * Which users a read covers: `ALL_USERS`, `NO_USER`, a `User` or your id for one. Sent as the
 * `user_id` query parameter, never as the `NoClick-User` header, so it filters without acting as the user.
 */
type UserFilter = typeof ALL_USERS | typeof NO_USER | UserRef;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

listPagestatic

static listPage(options?: ReadOptions & PageOptions): Promise<Page<Skill>>

One page of skills; pass nextCursor back as cursor.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.userFilterUserFilter

Which users the read covers (user_id query), instead of acting as one (user).

options.userUserOption

undefined = the ambient user (asUser), null = the account itself.

(defaults to the current user)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A page whose data holds the skills and whose next_cursor is None on the last page.

Types
/**
 * Which users a read covers: `ALL_USERS`, `NO_USER`, a `User` or your id for one. Sent as the
 * `user_id` query parameter, never as the `NoClick-User` header, so it filters without acting as the user.
 */
type UserFilter = typeof ALL_USERS | typeof NO_USER | UserRef;

/** A `User` or your own id for the user. */
type UserRef = string | UserLike;

/** Anything that can name a user lazily (a `User`). */
interface UserLike {
  _userId(): Promise<string>;
}

/** `undefined` = the ambient user (from `asUser`), `null` = the account itself. */
type UserOption = UserRef | null | undefined;

pinned

pinned(version: number): SkillLink

This skill held at one version, for an agent's skills.

Parameters
versionnumberrequired
Returns

What skills= takes for a skill the agent holds at version.

saveVersion

saveVersion(
  files: SkillFiles,
  options?: { removed?: string[]; replace?: boolean; baseVersion?: number },
): Promise<Skill>

Save a new version: files written over the latest (the whole folder with replace), removed taken out. With baseVersion it saves only while the latest is still that version (else Conflict). Agents following the latest get it in their next conversation; a running coding sandbox restarts with it.

Parameters
filesSkillFilesrequired
options.removedstring[]
options.replaceboolean
options.baseVersionnumber
Returns

This skill, at its new version.

Types
/** A folder's files: path → text, or bytes for a file that isn't text. */
type SkillFiles = Record<string, string | Uint8Array>;

update

update(changes: { name?: string; description?: string }): Promise<Skill>

Rename it or change its description: a new version with its SKILL.md frontmatter rewritten.

Parameters
changes{ name?: string; description?: string }required
Returns

This skill, as it is now.

versions

versions(): Promise<SkillVersion[]>

Every version, newest first.

Returns

Each version's frontmatter, files, size and who saved it.

getVersion

getVersion(version: number): Promise<SkillVersion>

One version, with its files.

Parameters
versionnumberrequired
Returns

That version; an unknown one raises noclick.NotFound.

restore

restore(version: number): Promise<Skill>

A new version holding what version held.

Parameters
versionnumberrequired
Returns

This skill, at its new version.

files

files(options?: { version?: number }): Promise<SkillFileInfo[]>

The files of a version (the latest unless version), by path.

Parameters
options.versionnumber
Returns

Each file's path, size and hash.

read

read(path: string, options?: { version?: number }): Promise<SkillFile>

One file of a version (the latest unless version): its text, or base64 when it isn't UTF-8.

Parameters
pathstringrequired
options.versionnumber
Returns

The file; a path the version doesn't hold raises noclick.NotFound.

delete

delete(): Promise<TrashItem>

Delete it: to the trash, restorable for 30 days, and off every agent that attaches it until it's restored.

Returns

Its TrashItem: restore() puts it back, on its agents too.

SkillAttachment

interface SkillAttachment

An agent that attaches a skill, and the version it holds (null: the latest).

Attributes
idstring
namestring
pinnumber | null

SkillAuthor

interface SkillAuthor

Who saved a version: a person in the app (console), a key (api), or an agent's turn.

Attributes
type"console" | "api" | "agent" | null
agentIdstring | null
agentNamestring | null

SkillFile

interface SkillFile

One file's content: its text, or base64 when it isn't UTF-8 (encoding).

Attributes
pathstring
versionnumber
sizenumber
sha256string
contentstring
encoding"utf-8" | "base64"

SkillFileInfo

interface SkillFileInfo

One file of a version, as its manifest lists it.

Attributes
pathstring
sizenumber
sha256string

SkillVersion

interface SkillVersion

One version of a skill: its frontmatter as that version has it, and its files.

Attributes
versionnumber
digeststring
namestring
descriptionstring
alwaysboolean
filesSkillFileInfo[]
sizenumber
createdBySkillAuthor
createdAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

Types
type JsonObject = { [key: string]: unknown };