Repo

Repos: git repositories for the code your agents and apps write.

repo = noclick.Repo.from_name("agent-tools", create_if_missing=True)
repo.commit({"src/index.ts": source}, message="Add the lookup route")
print(repo.read("src/index.ts").decode())
print(repo.clone_url())   # plain git over HTTPS, a short-lived token inside

A repo is plain git: clone it, push to it, or move it to GitHub whole. A project (noclick.Project) deploys one to a URL.

class Repo

A git repository NoClick hosts. Repo.fromName("agent-tools", { createIfMissing: true }) is lazy; commit to it from code, or clone it and push with plain git.

Attributes
idstring
namestring
defaultBranchstring

The branch a project deploys to production.

sizeBytesnumber | null
lastCommitCommit | null

The newest commit on the default branch (null in an empty repo).

usedByUsedBy[]

The apps that deploy it (binding is always null).

userIdstring | null
createdAtDate | null

createstatic

static create(name: string, options?: RepoCreateOptions): Promise<Repo>

Create an empty repo (unique per user; a duplicate throws Conflict with existingId).

Parameters
namestringrequired
options.defaultBranchstring

The branch a project deploys to production (main unless set).

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 repo, loaded, with no commits yet.

fromNamestatic

static fromName(
  name: string,
  options?: RepoCreateOptions & { createIfMissing?: boolean },
): Repo

A lazy reference to the repo called name for the current (or given) user. With createIfMissing it's created, empty, on first use; an existing repo is used as it is.

Parameters
namestringrequired
options.createIfMissingboolean
options.defaultBranchstring

The branch a project deploys to production (main unless set).

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 repo that loads, or is created, the first time it's used. Nothing is sent yet.

fromIdstatic

static fromId(repoId: string, options?: CallOptions): Repo

A lazy reference to a repo by id.

Parameters
repoIdstringrequired
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 repo that loads the first time you read a field. Nothing is sent yet.

getstatic

static get(repoId: string, options?: CallOptions): Promise<Repo>

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

Parameters
repoIdstringrequired
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 repo, loaded.

liststatic

static list(options?: ReadOptions & { limit?: number }): Promise<Repo[]>

The current user's repos (the account's own outside asUser, or those userFilter covers).

Parameters
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 repo, newest first, fetched page by page.

listPagestatic

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

One page of repos; 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 repos and whose next_cursor is None on the last page.

cloneUrl

cloneUrl(options?: { write?: boolean; ttlS?: number }): Promise<string>

A git URL with a short-lived token inside, for git clone, fetch and, with write, push. ttlS is 3,600 by default, at most 86,400; the token reaches this repo only. Treat it as a secret until it expires. Clones and pushes cost nothing extra, within fair use. An agent's writing URL (asked for through NoClick's MCP server, by the coordinator or by a platform agent) goes through NoClick, which never lets it force-push or delete the default branch, and keeps the old head of any other branch its push rewrites or deletes (backups).

Parameters
options.writebooleandefault false
options.ttlSnumber
Returns

An https:// URL that plain git accepts as it is. Treat it as a secret until it expires.

checkoutinvite-only beta

checkout(options?: CheckoutOptions): RepoCheckout

Invite-only beta. This repo checked out in an agent's workspace, for Agent repos: cloned into /workspace/<path> (the repo's name when omitted) on branch (the default branch when omitted); push is the branches it may push to, exact or prefix/*, else it's read-only. Sends nothing.

const site = Repo.fromName("booking");
await Agent.create("site-builder", { instructions, repos: [site.checkout({ push: "agent/*" })] });
Parameters
options.branchstring

The branch it checks out (the repository's default when omitted).

options.pathstring

The folder under /workspace it's cloned into (the repository's name when omitted).

options.pushstring | string[]

Branches it may push to, exact or a prefix ending in /* ("noclick/*"); without it the checkout is read-only.

Returns

A RepoCheckout to list in an agent's repos.

commit

commit(
  files: Record<string, string | Uint8Array | null>,
  options: RepoCommitOptions,
): Promise<Commit>

Commit files in one commit: each path maps to its new content (text, or bytes for binary files) or to null to delete it. At most 1,000 files and 50 MB in one commit.

Given a folder on disk instead (Node, Deno or Bun), the branch's tree is made to match it and only what changed is sent: new and changed files written, files the folder no longer has deleted. .git is skipped, and so is any path matching one of the exclude globs, which also keeps the repo's own copies of those paths. Nothing changed resolves to null.

const commit = await site.commit("./dist", { message: "Rebuild the site", exclude: ["*.map"] });
Parameters
filesRecord<string, string | Uint8Array | null>required
options.messagestringrequired
options.branchstring

The default branch when omitted; created from the default branch's head if it doesn't exist.

options.authorstring

Name <email>.

Returns

The new commit, with its sha; for a folder with nothing changed, None.

read

read(path: string, options?: { ref?: string }): Promise<Uint8Array>

One file's bytes at ref (a branch, tag or sha; the default branch's head when omitted).

Parameters
pathstringrequired
options.refstring
Returns

The file's bytes exactly as committed; decode text yourself.

files

files(
  prefix?,
  options?: { ref?: string; recursive?: boolean },
): Promise<RepoFile[]>

What's in the directory prefix (the root when empty), directories first; recursive lists every file below it instead, without the directories.

Parameters
prefixstringdefault ""
options.refstring
options.recursiveboolean
Returns

Its files and directories, directories first, each by path from the repo's root.

branches

branches(): Promise<Branch[]>

The repo's branches, the default one first.

Returns

Each branch with its head sha and when it last moved.

backups

backups(options?: { branch?: string; limit?: number }): Promise<RepoBackup[]>

The branches agents' pushes rewrote or deleted, as NoClick kept them first: newest first, limit of them (50 by default), of branch alone when it's given; each is kept 30 days. Through NoClick an agent never force-pushes or deletes the default branch at all.

for (const backup of await repo.backups({ branch: "agent/new-form" })) console.log(backup.reason, backup.sha);
Parameters
options.branchstring
options.limitnumber

Return at most this many.

(default 50)
Returns

Up to limit backups (None for all of them), of branch alone when it's given.

restoreBackup

restoreBackup(backup: RepoBackup | string): Promise<Branch>

Make a backup's branch again at the commit it was kept at (backup: a RepoBackup or its id). When the repo has a branch by that name again, the backup comes back as <branch>-restored-<time> instead; nothing that's there moves. Resolves to the branch made.

Parameters
backupRepoBackup | stringrequired
Returns

The branch made, with its head.

commits

commits(options?: { branch?: string; limit?: number }): Promise<Commit[]>

The history of branch (the default branch when omitted), newest first: limit commits (20 by default).

Parameters
options.branchstring
options.limitnumber

Return at most this many.

(default 20)
Returns

Up to limit commits (20 by default; None for the whole history), fetched page by page.

commitsPage

commitsPage(options?: { branch?: string } & PageOptions): Promise<Page<Commit>>

One page of commits, newest first; pass nextCursor back as cursor (null on the last page).

Parameters
options.branchstring
options.cursorstring | null

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

options.limitnumber

Return at most this many.

Returns

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

diff

diff(sha: string): Promise<CommitDiff>

What the commit sha (full or short) changed against its first parent, file by file; an unknown one throws NotFound.

Parameters
shastringrequired
Returns

The commit with each file it changed, the file's status, the lines it added and deleted and its patch in git's unified format.

export

export(): Promise<Operation<ExportBundle>>

Package every branch and its history as a git bundle; wait() resolves to the ExportBundle.

Returns

An operation whose .wait() gives an noclick.ExportBundle: a zip at url (a link that expires) holding the bundle, which git clone reads as it is.

exportToGithub

exportToGithub(
  options: {
    connection: string | Connection;
    owner: string;
    name?: string;
    private?: boolean;;
  },
): Promise<Operation<string | null>>

Copy the repo, every branch and tag with its history, into a new GitHub repository owner/name (name defaults to this repo's), through connection: a GitHub connection (a Connection or its name) of the repo's user, or of the account. owner is the connected account's own login or an organization it may create repositories in; the NoClick repo stays as it was. A connection with no GitHub account connected yet throws NeedsConnection, whose connectUrl connects it. The operation fails with Conflict when GitHub already has owner/name, and PermissionDenied when the connected account can't create repositories there. wait() resolves to the new repository's URL.

Parameters
options.connectionstring | Connectionrequired
options.ownerstringrequired
options.namestring
options.privatebooleandefault true
Returns

An operation whose .wait() gives the new GitHub repository's URL.

delete

delete(): Promise<TrashItem>

Delete the repo and its history: it goes to the trash, restorable for 30 days. One an app deploys from (usedBy) throws Conflict. Returns its TrashItem.

Returns

Its TrashItem: restore() puts it back, history and all.

readTextTypeScript only

readText(path: string, options?: { ref?: string }): Promise<string>

One file as UTF-8 text.

Parameters
pathstringrequired
options.refstring

Commit

interface Commit

One commit, and how many files it added, changed or deleted.

Attributes
shastring
messagestring
authorstring | null
branchstring | null
createdAtDate | null
filesChangednumber | null
rawJsonObject

The response JSON exactly as the API sent it.

CommitDiff

interface CommitDiff

What one commit changed against its first parent (parents is empty for the first commit).

Attributes
commitCommit
parentsstring[]
additionsnumber
deletionsnumber
filesFileChange[]

FileChange

interface FileChange

One file a commit changed: status is added, modified, deleted, renamed, copied or type_changed; patch is its unified diff in git's format, null (with the line counts) for a file that isn't shown: one that isn't text, or is too large.

Attributes
pathstring
statusstring
additionsnumber | null
deletionsnumber | null
sizenumber | null
patchstring | null
oldPathstring | null
rawJsonObject

The response JSON exactly as the API sent it.

Branch

interface Branch

A branch and the sha of its head commit.

Attributes
namestring
headstring | null
updatedAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

RepoBackup

interface RepoBackup

A branch's old head NoClick kept before an agent's push rewrote it (reason "rewritten": a force-push) or deleted it ("deleted"): the branch, the commit sha it was at, the platform agent whose push it was (agentId, else null), and when it was kept. It's kept 30 days, until expiresAt, out of the branch list and clones; repo.restoreBackup makes the branch again.

Attributes
idstring
branchstring
shastring
reasonstring
agentIdstring | null
createdAtDate | null
expiresAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

RepoFile

interface RepoFile

An entry in a repo's tree; size is in bytes, null for a directory, and sha is git's blob id for a file's content (it changes whenever the content does).

Attributes
pathstring
type"file" | "dir"
sizenumber | null
shastring | null
rawJsonObject

The response JSON exactly as the API sent it.

RepoCheckout

class RepoCheckout

A git repository an agent works in, for Agent repos: a connection's repository (connection.checkout("acme/docs")) or a NoClick repo (repo.checkout(); invite-only beta). NoClick clones it into /workspace/<path> at a conversation's first turn, and the agent's git reaches that repository only, through NoClick, with a key made for its sandbox; the connection's own token never enters it. push lists the branches it may push to: exact names, or a prefix ending in /* ("noclick/*" reaches noclick/fix and noclick/a/b), which NoClick's git endpoint enforces; without it the checkout is read-only. Whatever push allows, the agent can't force-push or delete the repository's default branch, and before its push rewrites or deletes any other branch NoClick keeps the old head as a backup for 30 days (on a git host, refs/noclick/backups/<branch>/<time> in the repository; push it back to restore it). A policy can't do this job: a coding harness runs git push in its own shell, which is no tool call for a policy to judge. gh only reads the repository there.

Attributes
repositorystring | null

owner/name on the connection's service (null for a NoClick repo).

connectionConnection | null
repoRepo | null
branchstring | null

The branch it checks out (the repository's default when None).

pathstring | null

The folder under /workspace it's cloned into.

pushstring[] | null

Branches it may push to, exact or prefix/* (None: read-only).