Create a repository from a project
Create a project's git repository on your git host in one step from the web app, the CLI, the in-app chat or MCP: first commit, linked project, git connection and webhook - with connections shared between projects, git access for the agent lane, and the OAuth limit.
Added in v0.235.0 A project can create its own git repository on your git host. One step creates the repository with a first commit, links it to the project and sets up its git connection with the webhook, so commits and pull requests reach the tickets and an agent lane can clone it. Before, you created the repository on the host by hand and then added a connection.
The step needs the Edit project permission. It works with GitHub, GitLab, Azure DevOps, Bitbucket Cloud, Bitbucket Data Center, Gitea and Forgejo. A project whose only connection is plain SSH is refused with the message "ssh has no API to create a repository. Create it on the host, then add a git connection." and nothing is created.
What the step does:
- creates the repository on the host with a first commit on the default branch (
developunless you name another), private unless you turn that off; - links it to the project and creates the git connection with its webhook, in the same call;
- returns the clone URL and the default branch the repository really has: these are the Repository URL and Branch of a lane assignment (see Run a fleet);
- writes an audit entry (
project.repository_created) that names the source of the credential.
No token passes through the call. The credential of the git host is one orboto already holds; it is copied sealed into the new connection.
Where to start
Added in v0.235.0| Surface | How |
|---|---|
| Web app | Project settings > Repositories > Create a repository |
| CLI | orboto project repos create <KEY> <name>; orboto project repos sources <KEY> lists the git hosts |
| In-app chat | the tool orboto_create_repository |
| MCP | orboto_api_call with POST /projects/{id}/git-repositories (there is no named tool, the tool list has no room); GET /projects/{id}/git-repositories/sources lists the hosts |
A project without any git connection shows the creation as the fix in its setup checklist, with connecting an existing repository as the alternative.
The form has these fields: Repository name, Git host, Owner (the owner of the credential unless you name another), Default branch, Private repository, and optionally Git user of the lane with Access (see below). For Azure DevOps there is also Azure DevOps project, unless the credential already names one. The name starts with a letter or digit, holds letters, digits, dot, dash and underscore, is at most 100 characters long and does not end in .git.
orboto project repos create ACME acme-app --collaborator lane-bot --collaborator-permission writeOther options: --owner, --description, --default-branch, --public, --connection <id> or --installation <id> to pick a git host, --repo-project (Azure DevOps project, or Bitbucket Cloud project key), --read-only (the new connection is read-only) and --no-webhook. --json prints the answer.
Where the credential comes from
Added in v0.235.0 The list of git hosts holds, one per host and owner and with this project first:
- the active, writable token connections of this project;
- the token connections of other projects that you may edit and whose editors shared them (see below);
- the GitHub App installations allowed for this project. An installation serves a new project only after an administrator allowed that project under Admin > Git integration (see Which projects may use an installation).
Not a source: a read-only connection (turn read-only off on the host connection), an SSH connection, and a GitLab OAuth connection (its refresh token can be used once and cannot back a second connection).
With one source, it is used. With several, the project's own single source wins over those of other projects; Owner narrows the choice. If it is still ambiguous, the step is refused and the message lists the choices; pick one with Git host (--connection or --installation). With none, the message says to add a writable git connection with a service-user token to the project, to ask an editor of another project you edit to share one of its connections, or to have an administrator allow a GitHub App installation for the project.
Share a connection with other projects
Added in v0.235.0 A connection of another project is a source only when an editor of its project shared it. Sharing is off by default and is decided per connection:
- Project settings > Git: switch on Usable by other projects on the connection. The hint there says that people who edit this project and another project can create that project's repository with this connection, that the new connection holds a sealed copy of the token, that rotating or deleting this connection updates or removes the copies, and that every use is written to this project's audit log.
- CLI:
orboto git share --project <KEY> --connection <id>; add--offto withdraw it.
Only a connection with its own access token can be shared. A connection that uses SSH, a GitHub App or OAuth, and a connection that is itself a copy, are refused. Someone who edits both projects can use a shared connection; naming a connection of a project you do not edit is answered with "This git connection is not available as a source for this project", and naming one of a project you edit that is not shared is refused with a message that says an editor of that project turns on sharing first.
What a copy does:
- The new connection holds a sealed copy of the token and remembers its source. The Git tab marks it Token copy.
- Rotating the token of the source puts the new token into every copy.
- Deleting the source, or moving it to a GitHub App connection (which removes its token from orboto), deletes the copies and takes their webhooks down at the git host.
- A copy that its own project rotates leaves its source and keeps its own token.
- Withdrawing the switch stops later creates and leaves the copies that exist. Deactivating the source does not reach the copies.
- A copy made from a connection of the same project carries no link, because no project boundary was crossed.
Every step is written to the audit log of both projects: project.git_connection_shareable_set when the switch changes and project.git_connection_shared when a create uses the connection (on the source project), and project.git_connection_copy_rotated, _removed and _detached on the source project with project.git_connection_source_rotated, _removed and _detached on the project of the copy.
What the token needs
Added in v0.235.0 The credential must be allowed to create repositories for the owner and to install webhooks. The host's own names for this, as orboto expects them:
| Git host | The token needs |
|---|---|
| Forgejo, Gitea | write:organization for an organisation, write:user for the account itself, write:repository for the webhook, read:user to tell the two apart (without it the owner counts as an organisation) |
| GitHub | Classic token: repo. Fine-grained token or App: Administration (write) and Contents (write). The first commit is made by the host's own initialisation on the account default, renamed to the default branch |
| GitLab | api, and the right to create projects in that namespace |
| Azure DevOps | vso.code_manage; the Azure DevOps project is named in the form |
| Bitbucket Cloud | admin:repository:bitbucket and write:repository:bitbucket (repository:admin for OAuth); the project key is named in the form, otherwise Bitbucket picks the oldest project |
| Bitbucket Data Center | REPO_CREATE on the project and REPO_ADMIN for the default branch |
Azure DevOps and Bitbucket Data Center take the visibility from their project, so Private repository has no effect there and the answer shows the visibility as unknown.
Access for the lane's git user
Added in v0.235.0 A private repository can be cloned by a lane only when the git account the lane uses (ORBOTO_AGENT_GIT_USER, see Run a fleet) has access to it. Enter that account under Git user of the lane (CLI: --collaborator <user>, optionally --collaborator-permission read|write; write is the default and fits a worker lane, read fits a reviewer). After the repository exists, orboto adds the user through the git host's own API and reports one of four results. The repository stays whatever the result is.
| Result | Meaning |
|---|---|
granted | The user has the access. |
invited | The host created an invitation (GitHub: a user who is not a member of the organisation, or any user on a personal repository). The user accepts it before the lane can clone. |
unsupported | The host has no usable collaborator API; the detail names the limit. Azure DevOps has no per-repository collaborator: add the user to the Contributors group of the project, or set the permission under the repository's security settings. |
failed | The host refused; the detail carries its status and message. |
The user is a login, username or user slug on the host; on Bitbucket Cloud it is the account id or the {uuid} of a workspace member. GitHub gives a collaborator on a personal repository write access whichever permission you ask for. The call needs a token that may administer the repository: for GitHub, Classic repo or, for a fine-grained token or App, Administration (write); for Gitea and Forgejo, admin on the repository (the token's user created it); for GitLab, api (the access level is Developer for write, Reporter for read; a user who is already a member counts as granted); for Bitbucket Cloud, admin:repository:bitbucket and write:permission:bitbucket (Atlassian lists app passwords as the only way to call this endpoint and answers with an error on plans without it, which shows as failed); for Bitbucket Data Center, REPO_ADMIN on the repository (Forge and OAuth2 apps cannot call it).
When something is refused or half done
Added in v0.235.0| What you see | What it means |
|---|---|
| "... already exists on ... Add a git connection for it or pick another name." | The name is taken on the host, or this project already has a connection for it. Nothing is written. To use an existing repository, connect it. |
| "... refused the credential ... The token needs the right to create repositories." | The host answered unauthorised or forbidden. Check the token against the table above. Nothing is written. |
| "... does not know the owner ..., or the token cannot reach it" | The owner is not an account, organisation, workspace or group the token can see. |
| The repository exists but has no commit (the answer says it was not initialised and names the refusal) | The host refused the first commit or the change of the default branch. The repository stays; a lane cannot check it out before a first push. The answer always names the branch the repository really has. |
| The webhook warning | The host refused the webhook, or the webhook address comes from the request instead of your configured public address. The connection is kept. On a self-hosted instance set API_PUBLIC_URL first, then use Reinstall webhook on the connection in Project settings > Git; Connection health shows whether events arrive. |
The call to the host happens before orboto writes anything, so a refusal at the host leaves nothing behind in orboto.
The OAuth limit
Added in v0.235.0 The step creates a git connection with a webhook and, when the credential comes from another project, a sealed copy of a token. Both keep working after the person or client that asked has gone. A connection that signed in to orboto with OAuth (an AI client connected through its connector, or orboto login in the browser) is therefore refused: the create, the Usable by other projects switch and a new repository URL on a lane assignment answer 403 with errors.auth.oauth_credential_route_refused. This is the same rule as for every other call that creates a git connection; see OAuth clients.
Use the web app in your browser, or a CLI profile or an MCP setup that uses an API key. A client that connects to MCP by OAuth can read the list of git hosts, but cannot create.
Set up a project end to end from a client with MCP only
Added in v0.235.0 A chat client without a shell can set a project up, given an API-key login:
- Create the project.
- Read the git hosts:
GET /projects/{id}/git-repositories/sources. - When the credential lives on another project, an editor of that project shares the connection once:
PATCH /projects/{hostProjectId}/git-connections/{connId}with{"shareable": true}. - Create the repository:
POST /projects/{id}/git-repositorieswith{"name": "...", "collaborator": "<the lane's git user>"}and readcollaborator.statusin the answer. - Create the tickets, add the lane's bot account as a member of the project, and assign the lane with the returned clone URL and default branch.
The lane picks the assignment up with its next heartbeat, clones and starts on the ready tickets. invited or unsupported in step 4 means one manual step is left. Try the flow once per git host before you rely on it.
Git integration
Connect GitHub, GitLab, Azure DevOps, Bitbucket, Gitea, Forgejo or plain SSH - commits and pull requests link themselves to tickets, step by step.
Importing from other tools
Move existing work into orboto from Jira, Linear, GitHub, GitLab, Asana, Trello, Notion, ClickUp, Monday.com, Redmine, Azure DevOps or CSV - the full wizard, step by step.