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 insideA 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 RepoA 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.
- Like every live object, it also has hydrate(), refresh() and raw.
| id | string | |
| name | string | |
| defaultBranch | string | The branch a project deploys to production. |
| sizeBytes | number | null | |
| lastCommit | Commit | null | The newest commit on the default branch (null in an empty repo). |
| usedBy | UsedBy[] | The apps that deploy it ( |
| userId | string | null | |
| createdAt | Date | null |
createstatic
static create(name: string, options?: RepoCreateOptions): Promise<Repo>Create an empty repo (unique per user; a duplicate throws Conflict with existingId).
The branch a project deploys to production (main unless set).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The new repo, loaded, with no commits yet.
fromNamestatic
static fromName(
name: string,
options?: RepoCreateOptions & { createIfMissing?: boolean },
): RepoA 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.
The branch a project deploys to production (main unless set).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
A repo that loads, or is created, the first time it's used. Nothing is sent yet.
fromIdstatic
static fromId(repoId: string, options?: CallOptions): RepoA lazy reference to a repo by id.
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.
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).
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
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).
falseAn https:// URL that plain git accepts as it is. Treat it as a secret until it expires.
checkoutinvite-only beta
checkout(options?: CheckoutOptions): RepoCheckoutInvite-only beta. This repo checked out in an agent's workspace, for Agent repos:
cloned into /workspace/ (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/*" })] });The branch it checks out (the repository's default when omitted).
The folder under /workspace it's cloned into (the repository's name when omitted).
Branches it may push to, exact or a prefix ending in /* ("noclick/*"); without it the checkout is read-only.
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"] });The default branch when omitted; created from the default branch's head if it doesn't exist.
Name <email>.
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).
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.
""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.
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);Return at most this many.
50)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.
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).
Return at most this many.
20)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).
The next_cursor of the page before; omit it for the first page.
Return at most this many.
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.
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.
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.
trueAn 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.
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.
Commit
interface CommitOne commit, and how many files it added, changed or deleted.
| sha | string | |
| message | string | |
| author | string | null | |
| branch | string | null | |
| createdAt | Date | null | |
| filesChanged | number | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
CommitDiff
interface CommitDiffWhat one commit changed against its first parent (parents is empty for the first commit).
| commit | Commit | |
| parents | string[] | |
| additions | number | |
| deletions | number | |
| files | FileChange[] |
FileChange
interface FileChangeOne 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.
| path | string | |
| status | string | |
| additions | number | null | |
| deletions | number | null | |
| size | number | null | |
| patch | string | null | |
| oldPath | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
Branch
interface BranchA branch and the sha of its head commit.
| name | string | |
| head | string | null | |
| updatedAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
RepoBackup
interface RepoBackupA 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.
| id | string | |
| branch | string | |
| sha | string | |
| reason | string | |
| agentId | string | null | |
| createdAt | Date | null | |
| expiresAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
RepoFile
interface RepoFileAn 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).
| path | string | |
| type | "file" | "dir" | |
| size | number | null | |
| sha | string | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
RepoCheckout
class RepoCheckoutA 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/ 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.
| repository | string | null |
|
| connection | Connection | null | |
| repo | Repo | null | |
| branch | string | null | The branch it checks out (the repository's default when None). |
| path | string | null | The folder under |
| push | string[] | null | Branches it may push to, exact or |