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
idstr
namestr

Its name, from its latest SKILL.md.

descriptionstr
alwaysbool

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

versionint

Its latest version's number.

digeststr

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

file_countint
sizeint

Its latest version's size in bytes.

attached_tolist[SkillAttachment]

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

user_idstr | None
created_atAny
updated_atAny

createclassmethodasync

noclick.Skill.create(files, *, allow_existing=False, user=..., client=None) -> Skill

A skill from its folder (path → text, or bytes for a file that isn't text), named by its SKILL.md; unique by name to its user, or to the account outside as_user. A taken name raises noclick.Conflict with existing_id, or with allow_existing=True returns the skill already there as it is (save_version to change it). Up to 200 files and 20 MB, SKILL.md up to 64 KB.

Parameters
filesFilesrequired
allow_existingbooldefault False
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
Skill

The new skill at version 1.

Usage
check = noclick.Skill.create({
    "SKILL.md": "---\nname: invoice-check\ndescription: Check an invoice against its purchase order.\n---\n1. ...",
    "scripts/match.py": open("match.py").read(),
})

from_dirclassmethodasync

noclick.Skill.from_dir(path, *, allow_existing=False, user=..., client=None) -> Skill

A skill from a folder on this machine: its SKILL.md and every other file under it (.git, __pycache__ and node_modules left out). A name already taken: as create.

Parameters
pathstrrequired
allow_existingbooldefault False
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
Skill

The new skill (or, with allow_existing=True, the one already there).

Usage
check = noclick.Skill.from_dir("./skills/invoice-check")

from_nameclassmethod

noclick.Skill.from_name(
    name, *, create_if_missing=False, files=None, user=..., client=None
) -> 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 create_if_missing=True it's created from files on first use.

Parameters
namestrrequired
create_if_missingbooldefault False
filesFiles | Nonedefault None
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
Skill

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

Usage
support = noclick.Agent.from_name("support", create_if_missing=True, instructions="...",
                                  skills=[noclick.Skill.from_name("invoice-check")])

from_idclassmethod

noclick.Skill.from_id(skill_id, *, client=None, user=...) -> Skill

A lazy reference to a skill by id.

Parameters
skill_idstrrequired
clientClient | None

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

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns
Skill

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

Usage
skill = noclick.Skill.from_id(support.skills[0]["id"])

getclassmethodasync

noclick.Skill.get(skill_id, *, user=..., client=None) -> Skill

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

Parameters
skill_idstrrequired
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
Skill

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

Usage
print(noclick.Skill.get(skill_id).attached_to)

listclassmethodasync

noclick.Skill.list(
    *, agent=None, limit=None, user_filter=None, user=..., client=None
) -> list[Skill]

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

Parameters
agentAnydefault None
limitint | None

Return at most this many.

(default None)
user_filterAny

Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
list[Skill]

Every matching skill, fetched page by page.

Usage
for skill in noclick.Skill.list():
    print(skill.name, skill.version, [a.name for a in skill.attached_to])

list_pageclassmethodasync

noclick.Skill.list_page(
    *, cursor=None, limit=None, user_filter=None, user=..., client=None
) -> Page

One page of skills; pass next_cursor back as cursor.

Parameters
cursorstr | None

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

(default None)
limitint | None

Return at most this many.

(default None)
user_filterAny

Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

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

(default None)
Returns
Page

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

Usage
page = noclick.Skill.list_page(limit=50)

pinned

skill.pinned(version) -> SkillLink

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

Parameters
versionintrequired
Returns
SkillLink

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

Usage
noclick.Agent.from_name("support").update(skills=[noclick.Skill.from_name("invoice-check").pinned(3)])

save_versionasync

skill.save_version(files, *, removed=(), replace=False, base_version=None) -> Skill

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

Parameters
filesFilesrequired
removedSequence[str]default ()
replacebooldefault False
base_versionint | Nonedefault None
Returns
Skill

This skill, at its new version.

Usage
check = noclick.Skill.from_name("invoice-check")
check.save_version({"scripts/match.py": open("match.py").read()}, base_version=check.version)

updateasync

skill.update(*, name=None, description=None) -> Skill

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

Parameters
namestr | Nonedefault None
descriptionstr | Nonedefault None
Returns
Skill

This skill, as it is now.

Usage
noclick.Skill.from_name("invoice-check").update(description="Check invoices and flag those over budget.")

versionsasync

skill.versions() -> list[SkillVersion]

Every version, newest first.

Returns
list[SkillVersion]

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

Usage
for v in noclick.Skill.from_name("invoice-check").versions():
    print(v.version, v.created_by.type, v.created_at)

get_versionasync

skill.get_version(version) -> SkillVersion

One version, with its files.

Parameters
versionintrequired
Returns
SkillVersion

That version; an unknown one raises noclick.NotFound.

Usage
first = noclick.Skill.from_name("invoice-check").get_version(1)

restoreasync

skill.restore(version) -> Skill

A new version holding what version held.

Parameters
versionintrequired
Returns
Skill

This skill, at its new version.

Usage
noclick.Skill.from_name("invoice-check").restore(2)

filesasync

skill.files(*, version=None) -> list[SkillFileInfo]

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

Parameters
versionint | Nonedefault None
Returns
list[SkillFileInfo]

Each file's path, size and hash.

Usage
print([f.path for f in noclick.Skill.from_name("invoice-check").files()])

readasync

skill.read(path, *, version=None) -> SkillFile

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

Parameters
pathstrrequired
versionint | Nonedefault None
Returns
SkillFile

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

Usage
print(noclick.Skill.from_name("invoice-check").read("SKILL.md").content)

deleteasync

skill.delete() -> TrashItem

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

Returns
TrashItem

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

Usage
noclick.Skill.from_name("old-checks").delete()

SkillAttachment

class SkillAttachment

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

Attributes
idstr
namestr
pinint | None

SkillAuthor

class SkillAuthor

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

Attributes
typestr | None
agent_idstr | None
agent_namestr | None

SkillFile

class SkillFile

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

Attributes
pathstr
versionint
sizeint
sha256str
contentstr
encodingstr

SkillFileInfo

class SkillFileInfo

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

Attributes
pathstr
sizeint
sha256str

SkillVersion

class SkillVersion

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

Attributes
versionint
digeststr
namestr
descriptionstr
alwaysbool
fileslist[SkillFileInfo]
sizeint
created_bySkillAuthor
created_atAny
rawdict[str, Any]

The response JSON exactly as the API sent it.